[CIFS] Missing include shows up on some architectures
[deliverable/linux.git] / fs / cifs / connect.c
CommitLineData
1da177e4
LT
1/*
2 * fs/cifs/connect.c
3 *
5815449d 4 * Copyright (C) International Business Machines Corp., 2002,2006
1da177e4
LT
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
24#include <linux/list.h>
25#include <linux/wait.h>
26#include <linux/ipv6.h>
27#include <linux/pagemap.h>
28#include <linux/ctype.h>
29#include <linux/utsname.h>
30#include <linux/mempool.h>
b8643e1b 31#include <linux/delay.h>
f191401f 32#include <linux/completion.h>
0ae0efad 33#include <linux/pagevec.h>
1da177e4
LT
34#include <asm/uaccess.h>
35#include <asm/processor.h>
36#include "cifspdu.h"
37#include "cifsglob.h"
38#include "cifsproto.h"
39#include "cifs_unicode.h"
40#include "cifs_debug.h"
41#include "cifs_fs_sb.h"
42#include "ntlmssp.h"
43#include "nterr.h"
44#include "rfc1002pdu.h"
a2653eba 45#include "cn_cifs.h"
1da177e4
LT
46
47#define CIFS_PORT 445
48#define RFC1001_PORT 139
49
f191401f
SF
50static DECLARE_COMPLETION(cifsd_complete);
51
1da177e4
LT
52extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
53 unsigned char *p24);
54
55extern mempool_t *cifs_req_poolp;
56
57struct smb_vol {
58 char *username;
59 char *password;
60 char *domainname;
61 char *UNC;
62 char *UNCip;
63 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
64 char *iocharset; /* local code page for mapping to and from Unicode */
65 char source_rfc1001_name[16]; /* netbios name of client */
a10faeb2 66 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
1da177e4
LT
67 uid_t linux_uid;
68 gid_t linux_gid;
69 mode_t file_mode;
70 mode_t dir_mode;
71 unsigned rw:1;
72 unsigned retry:1;
73 unsigned intr:1;
74 unsigned setuids:1;
75 unsigned noperm:1;
76 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
0a4b92c0 77 unsigned cifs_acl:1;
1da177e4
LT
78 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
79 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
80 unsigned direct_io:1;
6a0b4824 81 unsigned remap:1; /* set to remap seven reserved chars in filenames */
ac67055e 82 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
d7245c2c 83 unsigned sfu_emul:1;
bf820679
SF
84 unsigned krb5:1;
85 unsigned ntlm:1;
86 unsigned ntlmv2:1;
87 unsigned nullauth:1; /* attempt to authenticate with null user */
88 unsigned sign:1;
89 unsigned seal:1; /* encrypt */
c46fa8ac
SF
90 unsigned nocase; /* request case insensitive filenames */
91 unsigned nobrl; /* disable sending byte range locks to srv */
1da177e4
LT
92 unsigned int rsize;
93 unsigned int wsize;
94 unsigned int sockopt;
95 unsigned short int port;
96};
97
98static int ipv4_connect(struct sockaddr_in *psin_server,
99 struct socket **csocket,
a10faeb2
SF
100 char * netb_name,
101 char * server_netb_name);
1da177e4
LT
102static int ipv6_connect(struct sockaddr_in6 *psin_server,
103 struct socket **csocket);
104
105
106 /*
107 * cifs tcp session reconnection
108 *
109 * mark tcp session as reconnecting so temporarily locked
110 * mark all smb sessions as reconnecting for tcp session
111 * reconnect tcp session
112 * wake up waiters on reconnection? - (not needed currently)
113 */
114
115int
116cifs_reconnect(struct TCP_Server_Info *server)
117{
118 int rc = 0;
119 struct list_head *tmp;
120 struct cifsSesInfo *ses;
121 struct cifsTconInfo *tcon;
122 struct mid_q_entry * mid_entry;
123
124 spin_lock(&GlobalMid_Lock);
125 if(server->tcpStatus == CifsExiting) {
126 /* the demux thread will exit normally
127 next time through the loop */
128 spin_unlock(&GlobalMid_Lock);
129 return rc;
130 } else
131 server->tcpStatus = CifsNeedReconnect;
132 spin_unlock(&GlobalMid_Lock);
133 server->maxBuf = 0;
134
e4eb295d 135 cFYI(1, ("Reconnecting tcp session"));
1da177e4
LT
136
137 /* before reconnecting the tcp session, mark the smb session (uid)
138 and the tid bad so they are not used until reconnected */
139 read_lock(&GlobalSMBSeslock);
140 list_for_each(tmp, &GlobalSMBSessionList) {
141 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
142 if (ses->server) {
143 if (ses->server == server) {
144 ses->status = CifsNeedReconnect;
145 ses->ipc_tid = 0;
146 }
147 }
148 /* else tcp and smb sessions need reconnection */
149 }
150 list_for_each(tmp, &GlobalTreeConnectionList) {
151 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
152 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
153 tcon->tidStatus = CifsNeedReconnect;
154 }
155 }
156 read_unlock(&GlobalSMBSeslock);
157 /* do not want to be sending data on a socket we are freeing */
158 down(&server->tcpSem);
159 if(server->ssocket) {
160 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
161 server->ssocket->flags));
162 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
163 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
164 server->ssocket->flags));
165 sock_release(server->ssocket);
166 server->ssocket = NULL;
167 }
168
169 spin_lock(&GlobalMid_Lock);
170 list_for_each(tmp, &server->pending_mid_q) {
171 mid_entry = list_entry(tmp, struct
172 mid_q_entry,
173 qhead);
174 if(mid_entry) {
175 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
09d1db5c
SF
176 /* Mark other intransit requests as needing
177 retry so we do not immediately mark the
178 session bad again (ie after we reconnect
179 below) as they timeout too */
1da177e4
LT
180 mid_entry->midState = MID_RETRY_NEEDED;
181 }
182 }
183 }
184 spin_unlock(&GlobalMid_Lock);
185 up(&server->tcpSem);
186
187 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
188 {
189 if(server->protocolType == IPV6) {
190 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
191 } else {
192 rc = ipv4_connect(&server->addr.sockAddr,
193 &server->ssocket,
a10faeb2
SF
194 server->workstation_RFC1001_name,
195 server->server_RFC1001_name);
1da177e4
LT
196 }
197 if(rc) {
b387eaeb 198 cFYI(1,("reconnect error %d",rc));
0cb766ae 199 msleep(3000);
1da177e4
LT
200 } else {
201 atomic_inc(&tcpSesReconnectCount);
202 spin_lock(&GlobalMid_Lock);
203 if(server->tcpStatus != CifsExiting)
204 server->tcpStatus = CifsGood;
ad009ac9
SF
205 server->sequence_number = 0;
206 spin_unlock(&GlobalMid_Lock);
1da177e4
LT
207 /* atomic_set(&server->inFlight,0);*/
208 wake_up(&server->response_q);
209 }
210 }
211 return rc;
212}
213
e4eb295d
SF
214/*
215 return codes:
216 0 not a transact2, or all data present
217 >0 transact2 with that much data missing
218 -EINVAL = invalid transact2
219
220 */
221static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
222{
223 struct smb_t2_rsp * pSMBt;
224 int total_data_size;
225 int data_in_this_rsp;
226 int remaining;
227
228 if(pSMB->Command != SMB_COM_TRANSACTION2)
229 return 0;
230
231 /* check for plausible wct, bcc and t2 data and parm sizes */
232 /* check for parm and data offset going beyond end of smb */
233 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
234 cFYI(1,("invalid transact2 word count"));
235 return -EINVAL;
236 }
237
238 pSMBt = (struct smb_t2_rsp *)pSMB;
239
240 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
241 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
242
243 remaining = total_data_size - data_in_this_rsp;
244
245 if(remaining == 0)
246 return 0;
247 else if(remaining < 0) {
248 cFYI(1,("total data %d smaller than data in frame %d",
249 total_data_size, data_in_this_rsp));
250 return -EINVAL;
251 } else {
252 cFYI(1,("missing %d bytes from transact2, check next response",
253 remaining));
254 if(total_data_size > maxBufSize) {
255 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
256 total_data_size,maxBufSize));
257 return -EINVAL;
258 }
259 return remaining;
260 }
261}
262
263static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
264{
265 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
266 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
267 int total_data_size;
268 int total_in_buf;
269 int remaining;
270 int total_in_buf2;
271 char * data_area_of_target;
272 char * data_area_of_buf2;
273 __u16 byte_count;
274
275 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
276
277 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
278 cFYI(1,("total data sizes of primary and secondary t2 differ"));
279 }
280
281 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
282
283 remaining = total_data_size - total_in_buf;
284
285 if(remaining < 0)
286 return -EINVAL;
287
288 if(remaining == 0) /* nothing to do, ignore */
289 return 0;
290
291 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
292 if(remaining < total_in_buf2) {
293 cFYI(1,("transact2 2nd response contains too much data"));
294 }
295
296 /* find end of first SMB data area */
297 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
298 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
299 /* validate target area */
300
301 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
302 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
303
304 data_area_of_target += total_in_buf;
305
306 /* copy second buffer into end of first buffer */
307 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
308 total_in_buf += total_in_buf2;
309 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
310 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
311 byte_count += total_in_buf2;
312 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
313
70ca734a 314 byte_count = pTargetSMB->smb_buf_length;
e4eb295d
SF
315 byte_count += total_in_buf2;
316
317 /* BB also add check that we are not beyond maximum buffer size */
318
70ca734a 319 pTargetSMB->smb_buf_length = byte_count;
e4eb295d
SF
320
321 if(remaining == total_in_buf2) {
322 cFYI(1,("found the last secondary response"));
323 return 0; /* we are done */
324 } else /* more responses to go */
325 return 1;
326
327}
328
1da177e4
LT
329static int
330cifs_demultiplex_thread(struct TCP_Server_Info *server)
331{
332 int length;
333 unsigned int pdu_length, total_read;
334 struct smb_hdr *smb_buffer = NULL;
b8643e1b
SF
335 struct smb_hdr *bigbuf = NULL;
336 struct smb_hdr *smallbuf = NULL;
1da177e4
LT
337 struct msghdr smb_msg;
338 struct kvec iov;
339 struct socket *csocket = server->ssocket;
340 struct list_head *tmp;
341 struct cifsSesInfo *ses;
342 struct task_struct *task_to_wake = NULL;
343 struct mid_q_entry *mid_entry;
70ca734a 344 char temp;
b8643e1b 345 int isLargeBuf = FALSE;
e4eb295d
SF
346 int isMultiRsp;
347 int reconnect;
1da177e4
LT
348
349 daemonize("cifsd");
350 allow_signal(SIGKILL);
351 current->flags |= PF_MEMALLOC;
352 server->tsk = current; /* save process info to wake at shutdown */
353 cFYI(1, ("Demultiplex PID: %d", current->pid));
354 write_lock(&GlobalSMBSeslock);
355 atomic_inc(&tcpSesAllocCount);
356 length = tcpSesAllocCount.counter;
357 write_unlock(&GlobalSMBSeslock);
f191401f 358 complete(&cifsd_complete);
1da177e4
LT
359 if(length > 1) {
360 mempool_resize(cifs_req_poolp,
361 length + cifs_min_rcv,
362 GFP_KERNEL);
363 }
364
365 while (server->tcpStatus != CifsExiting) {
ede1327e
SF
366 if (try_to_freeze())
367 continue;
b8643e1b
SF
368 if (bigbuf == NULL) {
369 bigbuf = cifs_buf_get();
370 if(bigbuf == NULL) {
371 cERROR(1,("No memory for large SMB response"));
372 msleep(3000);
373 /* retry will check if exiting */
374 continue;
375 }
376 } else if(isLargeBuf) {
377 /* we are reusing a dirtry large buf, clear its start */
378 memset(bigbuf, 0, sizeof (struct smb_hdr));
1da177e4 379 }
b8643e1b
SF
380
381 if (smallbuf == NULL) {
382 smallbuf = cifs_small_buf_get();
383 if(smallbuf == NULL) {
384 cERROR(1,("No memory for SMB response"));
385 msleep(1000);
386 /* retry will check if exiting */
387 continue;
388 }
389 /* beginning of smb buffer is cleared in our buf_get */
390 } else /* if existing small buf clear beginning */
391 memset(smallbuf, 0, sizeof (struct smb_hdr));
392
393 isLargeBuf = FALSE;
e4eb295d 394 isMultiRsp = FALSE;
b8643e1b 395 smb_buffer = smallbuf;
1da177e4
LT
396 iov.iov_base = smb_buffer;
397 iov.iov_len = 4;
398 smb_msg.msg_control = NULL;
399 smb_msg.msg_controllen = 0;
400 length =
401 kernel_recvmsg(csocket, &smb_msg,
402 &iov, 1, 4, 0 /* BB see socket.h flags */);
403
404 if(server->tcpStatus == CifsExiting) {
405 break;
406 } else if (server->tcpStatus == CifsNeedReconnect) {
57337e42 407 cFYI(1,("Reconnect after server stopped responding"));
1da177e4
LT
408 cifs_reconnect(server);
409 cFYI(1,("call to reconnect done"));
410 csocket = server->ssocket;
411 continue;
412 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
b8643e1b 413 msleep(1); /* minimum sleep to prevent looping
1da177e4
LT
414 allowing socket to clear and app threads to set
415 tcpStatus CifsNeedReconnect if server hung */
416 continue;
417 } else if (length <= 0) {
418 if(server->tcpStatus == CifsNew) {
57337e42 419 cFYI(1,("tcp session abend after SMBnegprot"));
09d1db5c
SF
420 /* some servers kill the TCP session rather than
421 returning an SMB negprot error, in which
422 case reconnecting here is not going to help,
423 and so simply return error to mount */
1da177e4
LT
424 break;
425 }
426 if(length == -EINTR) {
427 cFYI(1,("cifsd thread killed"));
428 break;
429 }
57337e42
SF
430 cFYI(1,("Reconnect after unexpected peek error %d",
431 length));
1da177e4
LT
432 cifs_reconnect(server);
433 csocket = server->ssocket;
434 wake_up(&server->response_q);
435 continue;
46810cbf
SF
436 } else if (length < 4) {
437 cFYI(1,
57337e42 438 ("Frame under four bytes received (%d bytes long)",
46810cbf
SF
439 length));
440 cifs_reconnect(server);
441 csocket = server->ssocket;
442 wake_up(&server->response_q);
443 continue;
444 }
1da177e4 445
70ca734a
SF
446 /* The right amount was read from socket - 4 bytes */
447 /* so we can now interpret the length field */
46810cbf 448
70ca734a
SF
449 /* the first byte big endian of the length field,
450 is actually not part of the length but the type
451 with the most common, zero, as regular data */
452 temp = *((char *) smb_buffer);
46810cbf 453
70ca734a
SF
454 /* Note that FC 1001 length is big endian on the wire,
455 but we convert it here so it is always manipulated
456 as host byte order */
46810cbf 457 pdu_length = ntohl(smb_buffer->smb_buf_length);
70ca734a
SF
458 smb_buffer->smb_buf_length = pdu_length;
459
460 cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
46810cbf 461
70ca734a 462 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
e4eb295d 463 continue;
70ca734a 464 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
e4eb295d
SF
465 cFYI(1,("Good RFC 1002 session rsp"));
466 continue;
70ca734a 467 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
46810cbf
SF
468 /* we get this from Windows 98 instead of
469 an error on SMB negprot response */
e4eb295d 470 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
70ca734a 471 pdu_length));
46810cbf
SF
472 if(server->tcpStatus == CifsNew) {
473 /* if nack on negprot (rather than
474 ret of smb negprot error) reconnecting
475 not going to help, ret error to mount */
476 break;
477 } else {
478 /* give server a second to
479 clean up before reconnect attempt */
480 msleep(1000);
481 /* always try 445 first on reconnect
482 since we get NACK on some if we ever
483 connected to port 139 (the NACK is
484 since we do not begin with RFC1001
485 session initialize frame) */
486 server->addr.sockAddr.sin_port =
487 htons(CIFS_PORT);
1da177e4
LT
488 cifs_reconnect(server);
489 csocket = server->ssocket;
46810cbf 490 wake_up(&server->response_q);
1da177e4 491 continue;
46810cbf 492 }
70ca734a 493 } else if (temp != (char) 0) {
46810cbf 494 cERROR(1,("Unknown RFC 1002 frame"));
70ca734a
SF
495 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
496 length);
46810cbf
SF
497 cifs_reconnect(server);
498 csocket = server->ssocket;
499 continue;
e4eb295d
SF
500 }
501
502 /* else we have an SMB response */
503 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
46810cbf 504 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
e4eb295d 505 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
46810cbf 506 length, pdu_length+4));
e4eb295d
SF
507 cifs_reconnect(server);
508 csocket = server->ssocket;
509 wake_up(&server->response_q);
510 continue;
511 }
512
513 /* else length ok */
514 reconnect = 0;
515
ec637e3f 516 if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
e4eb295d
SF
517 isLargeBuf = TRUE;
518 memcpy(bigbuf, smallbuf, 4);
519 smb_buffer = bigbuf;
520 }
521 length = 0;
522 iov.iov_base = 4 + (char *)smb_buffer;
523 iov.iov_len = pdu_length;
524 for (total_read = 0; total_read < pdu_length;
525 total_read += length) {
526 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
527 pdu_length - total_read, 0);
528 if((server->tcpStatus == CifsExiting) ||
529 (length == -EINTR)) {
530 /* then will exit */
531 reconnect = 2;
532 break;
533 } else if (server->tcpStatus == CifsNeedReconnect) {
46810cbf
SF
534 cifs_reconnect(server);
535 csocket = server->ssocket;
e4eb295d
SF
536 /* Reconnect wakes up rspns q */
537 /* Now we will reread sock */
538 reconnect = 1;
539 break;
540 } else if ((length == -ERESTARTSYS) ||
541 (length == -EAGAIN)) {
542 msleep(1); /* minimum sleep to prevent looping,
543 allowing socket to clear and app
544 threads to set tcpStatus
545 CifsNeedReconnect if server hung*/
46810cbf 546 continue;
e4eb295d
SF
547 } else if (length <= 0) {
548 cERROR(1,("Received no data, expecting %d",
549 pdu_length - total_read));
550 cifs_reconnect(server);
551 csocket = server->ssocket;
552 reconnect = 1;
553 break;
46810cbf 554 }
e4eb295d
SF
555 }
556 if(reconnect == 2)
557 break;
558 else if(reconnect == 1)
559 continue;
1da177e4 560
e4eb295d
SF
561 length += 4; /* account for rfc1002 hdr */
562
09d1db5c 563
e4eb295d 564 dump_smb(smb_buffer, length);
184ed211 565 if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
b387eaeb 566 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
e4eb295d
SF
567 continue;
568 }
1da177e4 569
e4eb295d
SF
570
571 task_to_wake = NULL;
572 spin_lock(&GlobalMid_Lock);
573 list_for_each(tmp, &server->pending_mid_q) {
574 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
575
576 if ((mid_entry->mid == smb_buffer->Mid) &&
577 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
578 (mid_entry->command == smb_buffer->Command)) {
e4eb295d
SF
579 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
580 /* We have a multipart transact2 resp */
cd63499c 581 isMultiRsp = TRUE;
e4eb295d
SF
582 if(mid_entry->resp_buf) {
583 /* merge response - fix up 1st*/
584 if(coalesce_t2(smb_buffer,
585 mid_entry->resp_buf)) {
3979877e 586 mid_entry->multiRsp = 1;
e4eb295d
SF
587 break;
588 } else {
589 /* all parts received */
3979877e 590 mid_entry->multiEnd = 1;
e4eb295d
SF
591 goto multi_t2_fnd;
592 }
593 } else {
594 if(!isLargeBuf) {
595 cERROR(1,("1st trans2 resp needs bigbuf"));
596 /* BB maybe we can fix this up, switch
597 to already allocated large buffer? */
598 } else {
cd63499c 599 /* Have first buffer */
e4eb295d
SF
600 mid_entry->resp_buf =
601 smb_buffer;
602 mid_entry->largeBuf = 1;
e4eb295d
SF
603 bigbuf = NULL;
604 }
605 }
606 break;
607 }
608 mid_entry->resp_buf = smb_buffer;
46810cbf 609 if(isLargeBuf)
e4eb295d 610 mid_entry->largeBuf = 1;
46810cbf 611 else
e4eb295d
SF
612 mid_entry->largeBuf = 0;
613multi_t2_fnd:
614 task_to_wake = mid_entry->tsk;
615 mid_entry->midState = MID_RESPONSE_RECEIVED;
1047abc1
SF
616#ifdef CONFIG_CIFS_STATS2
617 mid_entry->when_received = jiffies;
618#endif
e4eb295d 619 break;
46810cbf 620 }
1da177e4 621 }
e4eb295d
SF
622 spin_unlock(&GlobalMid_Lock);
623 if (task_to_wake) {
cd63499c
SF
624 /* Was previous buf put in mpx struct for multi-rsp? */
625 if(!isMultiRsp) {
626 /* smb buffer will be freed by user thread */
627 if(isLargeBuf) {
628 bigbuf = NULL;
629 } else
630 smallbuf = NULL;
631 }
e4eb295d 632 wake_up_process(task_to_wake);
d7c8c94d 633 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
e4eb295d 634 && (isMultiRsp == FALSE)) {
3979877e 635 cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter));
70ca734a
SF
636 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
637 sizeof(struct smb_hdr));
3979877e
SF
638#ifdef CONFIG_CIFS_DEBUG2
639 cifs_dump_detail(smb_buffer);
640 cifs_dump_mids(server);
641#endif /* CIFS_DEBUG2 */
642
e4eb295d
SF
643 }
644 } /* end while !EXITING */
645
1da177e4
LT
646 spin_lock(&GlobalMid_Lock);
647 server->tcpStatus = CifsExiting;
648 server->tsk = NULL;
31ca3bc3
SF
649 /* check if we have blocked requests that need to free */
650 /* Note that cifs_max_pending is normally 50, but
651 can be set at module install time to as little as two */
652 if(atomic_read(&server->inFlight) >= cifs_max_pending)
653 atomic_set(&server->inFlight, cifs_max_pending - 1);
654 /* We do not want to set the max_pending too low or we
655 could end up with the counter going negative */
1da177e4
LT
656 spin_unlock(&GlobalMid_Lock);
657 /* Although there should not be any requests blocked on
658 this queue it can not hurt to be paranoid and try to wake up requests
09d1db5c 659 that may haven been blocked when more than 50 at time were on the wire
1da177e4
LT
660 to the same server - they now will see the session is in exit state
661 and get out of SendReceive. */
662 wake_up_all(&server->request_q);
663 /* give those requests time to exit */
b8643e1b
SF
664 msleep(125);
665
1da177e4
LT
666 if(server->ssocket) {
667 sock_release(csocket);
668 server->ssocket = NULL;
669 }
b8643e1b
SF
670 /* buffer usuallly freed in free_mid - need to free it here on exit */
671 if (bigbuf != NULL)
672 cifs_buf_release(bigbuf);
673 if (smallbuf != NULL)
674 cifs_small_buf_release(smallbuf);
1da177e4
LT
675
676 read_lock(&GlobalSMBSeslock);
677 if (list_empty(&server->pending_mid_q)) {
09d1db5c
SF
678 /* loop through server session structures attached to this and
679 mark them dead */
1da177e4
LT
680 list_for_each(tmp, &GlobalSMBSessionList) {
681 ses =
682 list_entry(tmp, struct cifsSesInfo,
683 cifsSessionList);
684 if (ses->server == server) {
685 ses->status = CifsExiting;
686 ses->server = NULL;
687 }
688 }
689 read_unlock(&GlobalSMBSeslock);
690 } else {
31ca3bc3
SF
691 /* although we can not zero the server struct pointer yet,
692 since there are active requests which may depnd on them,
693 mark the corresponding SMB sessions as exiting too */
694 list_for_each(tmp, &GlobalSMBSessionList) {
695 ses = list_entry(tmp, struct cifsSesInfo,
696 cifsSessionList);
697 if (ses->server == server) {
698 ses->status = CifsExiting;
699 }
700 }
701
1da177e4
LT
702 spin_lock(&GlobalMid_Lock);
703 list_for_each(tmp, &server->pending_mid_q) {
704 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
705 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
706 cFYI(1,
09d1db5c 707 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
1da177e4
LT
708 task_to_wake = mid_entry->tsk;
709 if(task_to_wake) {
710 wake_up_process(task_to_wake);
711 }
712 }
713 }
714 spin_unlock(&GlobalMid_Lock);
715 read_unlock(&GlobalSMBSeslock);
1da177e4 716 /* 1/8th of sec is more than enough time for them to exit */
b8643e1b 717 msleep(125);
1da177e4
LT
718 }
719
f191401f 720 if (!list_empty(&server->pending_mid_q)) {
1da177e4
LT
721 /* mpx threads have not exited yet give them
722 at least the smb send timeout time for long ops */
31ca3bc3
SF
723 /* due to delays on oplock break requests, we need
724 to wait at least 45 seconds before giving up
725 on a request getting a response and going ahead
726 and killing cifsd */
1da177e4 727 cFYI(1, ("Wait for exit from demultiplex thread"));
31ca3bc3 728 msleep(46000);
1da177e4
LT
729 /* if threads still have not exited they are probably never
730 coming home not much else we can do but free the memory */
731 }
1da177e4
LT
732
733 write_lock(&GlobalSMBSeslock);
734 atomic_dec(&tcpSesAllocCount);
735 length = tcpSesAllocCount.counter;
31ca3bc3
SF
736
737 /* last chance to mark ses pointers invalid
738 if there are any pointing to this (e.g
739 if a crazy root user tried to kill cifsd
740 kernel thread explicitly this might happen) */
741 list_for_each(tmp, &GlobalSMBSessionList) {
742 ses = list_entry(tmp, struct cifsSesInfo,
743 cifsSessionList);
744 if (ses->server == server) {
745 ses->server = NULL;
746 }
747 }
1da177e4 748 write_unlock(&GlobalSMBSeslock);
31ca3bc3
SF
749
750 kfree(server);
1da177e4
LT
751 if(length > 0) {
752 mempool_resize(cifs_req_poolp,
753 length + cifs_min_rcv,
754 GFP_KERNEL);
755 }
b8643e1b 756
f191401f 757 complete_and_exit(&cifsd_complete, 0);
1da177e4
LT
758 return 0;
759}
760
1da177e4
LT
761static int
762cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
763{
764 char *value;
765 char *data;
766 unsigned int temp_len, i, j;
767 char separator[2];
768
769 separator[0] = ',';
770 separator[1] = 0;
771
772 memset(vol->source_rfc1001_name,0x20,15);
773 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
774 /* does not have to be a perfect mapping since the field is
775 informational, only used for servers that do not support
776 port 445 and it can be overridden at mount time */
09d1db5c
SF
777 vol->source_rfc1001_name[i] =
778 toupper(system_utsname.nodename[i]);
1da177e4
LT
779 }
780 vol->source_rfc1001_name[15] = 0;
a10faeb2
SF
781 /* null target name indicates to use *SMBSERVR default called name
782 if we end up sending RFC1001 session initialize */
783 vol->target_rfc1001_name[0] = 0;
1da177e4
LT
784 vol->linux_uid = current->uid; /* current->euid instead? */
785 vol->linux_gid = current->gid;
786 vol->dir_mode = S_IRWXUGO;
787 /* 2767 perms indicate mandatory locking support */
788 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
789
790 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
791 vol->rw = TRUE;
bf820679 792 vol->ntlm = TRUE;
ac67055e
JA
793 /* default is always to request posix paths. */
794 vol->posix_paths = 1;
795
1da177e4
LT
796 if (!options)
797 return 1;
798
799 if(strncmp(options,"sep=",4) == 0) {
800 if(options[4] != 0) {
801 separator[0] = options[4];
802 options += 5;
803 } else {
804 cFYI(1,("Null separator not allowed"));
805 }
806 }
807
808 while ((data = strsep(&options, separator)) != NULL) {
809 if (!*data)
810 continue;
811 if ((value = strchr(data, '=')) != NULL)
812 *value++ = '\0';
813
814 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
815 vol->no_xattr = 0;
816 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
817 vol->no_xattr = 1;
818 } else if (strnicmp(data, "user", 4) == 0) {
819 if (!value || !*value) {
820 printk(KERN_WARNING
821 "CIFS: invalid or missing username\n");
822 return 1; /* needs_arg; */
823 }
824 if (strnlen(value, 200) < 200) {
825 vol->username = value;
826 } else {
827 printk(KERN_WARNING "CIFS: username too long\n");
828 return 1;
829 }
830 } else if (strnicmp(data, "pass", 4) == 0) {
831 if (!value) {
832 vol->password = NULL;
833 continue;
834 } else if(value[0] == 0) {
835 /* check if string begins with double comma
836 since that would mean the password really
837 does start with a comma, and would not
838 indicate an empty string */
839 if(value[1] != separator[0]) {
840 vol->password = NULL;
841 continue;
842 }
843 }
844 temp_len = strlen(value);
845 /* removed password length check, NTLM passwords
846 can be arbitrarily long */
847
848 /* if comma in password, the string will be
849 prematurely null terminated. Commas in password are
850 specified across the cifs mount interface by a double
851 comma ie ,, and a comma used as in other cases ie ','
852 as a parameter delimiter/separator is single and due
853 to the strsep above is temporarily zeroed. */
854
855 /* NB: password legally can have multiple commas and
856 the only illegal character in a password is null */
857
09d1db5c
SF
858 if ((value[temp_len] == 0) &&
859 (value[temp_len+1] == separator[0])) {
1da177e4
LT
860 /* reinsert comma */
861 value[temp_len] = separator[0];
862 temp_len+=2; /* move after the second comma */
863 while(value[temp_len] != 0) {
864 if (value[temp_len] == separator[0]) {
09d1db5c
SF
865 if (value[temp_len+1] ==
866 separator[0]) {
867 /* skip second comma */
868 temp_len++;
1da177e4
LT
869 } else {
870 /* single comma indicating start
871 of next parm */
872 break;
873 }
874 }
875 temp_len++;
876 }
877 if(value[temp_len] == 0) {
878 options = NULL;
879 } else {
880 value[temp_len] = 0;
881 /* point option to start of next parm */
882 options = value + temp_len + 1;
883 }
884 /* go from value to value + temp_len condensing
885 double commas to singles. Note that this ends up
886 allocating a few bytes too many, which is ok */
e915fc49 887 vol->password = kzalloc(temp_len, GFP_KERNEL);
433dc24f
SF
888 if(vol->password == NULL) {
889 printk("CIFS: no memory for pass\n");
890 return 1;
891 }
1da177e4
LT
892 for(i=0,j=0;i<temp_len;i++,j++) {
893 vol->password[j] = value[i];
09d1db5c
SF
894 if(value[i] == separator[0]
895 && value[i+1] == separator[0]) {
1da177e4
LT
896 /* skip second comma */
897 i++;
898 }
899 }
900 vol->password[j] = 0;
901 } else {
e915fc49 902 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
433dc24f
SF
903 if(vol->password == NULL) {
904 printk("CIFS: no memory for pass\n");
905 return 1;
906 }
1da177e4
LT
907 strcpy(vol->password, value);
908 }
909 } else if (strnicmp(data, "ip", 2) == 0) {
910 if (!value || !*value) {
911 vol->UNCip = NULL;
912 } else if (strnlen(value, 35) < 35) {
913 vol->UNCip = value;
914 } else {
915 printk(KERN_WARNING "CIFS: ip address too long\n");
916 return 1;
917 }
bf820679
SF
918 } else if (strnicmp(data, "sec", 3) == 0) {
919 if (!value || !*value) {
920 cERROR(1,("no security value specified"));
921 continue;
922 } else if (strnicmp(value, "krb5i", 5) == 0) {
923 vol->sign = 1;
924 vol->krb5 = 1;
925 } else if (strnicmp(value, "krb5p", 5) == 0) {
926 /* vol->seal = 1;
927 vol->krb5 = 1; */
928 cERROR(1,("Krb5 cifs privacy not supported"));
929 return 1;
930 } else if (strnicmp(value, "krb5", 4) == 0) {
931 vol->krb5 = 1;
932 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
933 vol->ntlmv2 = 1;
934 vol->sign = 1;
935 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
936 vol->ntlmv2 = 1;
937 } else if (strnicmp(value, "ntlmi", 5) == 0) {
938 vol->ntlm = 1;
939 vol->sign = 1;
940 } else if (strnicmp(value, "ntlm", 4) == 0) {
941 /* ntlm is default so can be turned off too */
942 vol->ntlm = 1;
943 } else if (strnicmp(value, "nontlm", 6) == 0) {
944 vol->ntlm = 0;
945 } else if (strnicmp(value, "none", 4) == 0) {
946 vol->nullauth = 1;
947 } else {
948 cERROR(1,("bad security option: %s", value));
949 return 1;
950 }
1da177e4
LT
951 } else if ((strnicmp(data, "unc", 3) == 0)
952 || (strnicmp(data, "target", 6) == 0)
953 || (strnicmp(data, "path", 4) == 0)) {
954 if (!value || !*value) {
955 printk(KERN_WARNING
956 "CIFS: invalid path to network resource\n");
957 return 1; /* needs_arg; */
958 }
959 if ((temp_len = strnlen(value, 300)) < 300) {
960 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
961 if(vol->UNC == NULL)
962 return 1;
963 strcpy(vol->UNC,value);
964 if (strncmp(vol->UNC, "//", 2) == 0) {
965 vol->UNC[0] = '\\';
966 vol->UNC[1] = '\\';
967 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
968 printk(KERN_WARNING
969 "CIFS: UNC Path does not begin with // or \\\\ \n");
970 return 1;
971 }
972 } else {
973 printk(KERN_WARNING "CIFS: UNC name too long\n");
974 return 1;
975 }
976 } else if ((strnicmp(data, "domain", 3) == 0)
977 || (strnicmp(data, "workgroup", 5) == 0)) {
978 if (!value || !*value) {
979 printk(KERN_WARNING "CIFS: invalid domain name\n");
980 return 1; /* needs_arg; */
981 }
982 /* BB are there cases in which a comma can be valid in
983 a domain name and need special handling? */
3979877e 984 if (strnlen(value, 256) < 256) {
1da177e4
LT
985 vol->domainname = value;
986 cFYI(1, ("Domain name set"));
987 } else {
988 printk(KERN_WARNING "CIFS: domain name too long\n");
989 return 1;
990 }
991 } else if (strnicmp(data, "iocharset", 9) == 0) {
992 if (!value || !*value) {
993 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
994 return 1; /* needs_arg; */
995 }
996 if (strnlen(value, 65) < 65) {
997 if(strnicmp(value,"default",7))
998 vol->iocharset = value;
999 /* if iocharset not set load_nls_default used by caller */
1000 cFYI(1, ("iocharset set to %s",value));
1001 } else {
1002 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
1003 return 1;
1004 }
1005 } else if (strnicmp(data, "uid", 3) == 0) {
1006 if (value && *value) {
1007 vol->linux_uid =
1008 simple_strtoul(value, &value, 0);
1009 }
1010 } else if (strnicmp(data, "gid", 3) == 0) {
1011 if (value && *value) {
1012 vol->linux_gid =
1013 simple_strtoul(value, &value, 0);
1014 }
1015 } else if (strnicmp(data, "file_mode", 4) == 0) {
1016 if (value && *value) {
1017 vol->file_mode =
1018 simple_strtoul(value, &value, 0);
1019 }
1020 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1021 if (value && *value) {
1022 vol->dir_mode =
1023 simple_strtoul(value, &value, 0);
1024 }
1025 } else if (strnicmp(data, "dirmode", 4) == 0) {
1026 if (value && *value) {
1027 vol->dir_mode =
1028 simple_strtoul(value, &value, 0);
1029 }
1030 } else if (strnicmp(data, "port", 4) == 0) {
1031 if (value && *value) {
1032 vol->port =
1033 simple_strtoul(value, &value, 0);
1034 }
1035 } else if (strnicmp(data, "rsize", 5) == 0) {
1036 if (value && *value) {
1037 vol->rsize =
1038 simple_strtoul(value, &value, 0);
1039 }
1040 } else if (strnicmp(data, "wsize", 5) == 0) {
1041 if (value && *value) {
1042 vol->wsize =
1043 simple_strtoul(value, &value, 0);
1044 }
1045 } else if (strnicmp(data, "sockopt", 5) == 0) {
1046 if (value && *value) {
1047 vol->sockopt =
1048 simple_strtoul(value, &value, 0);
1049 }
1050 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1051 if (!value || !*value || (*value == ' ')) {
1052 cFYI(1,("invalid (empty) netbiosname specified"));
1053 } else {
1054 memset(vol->source_rfc1001_name,0x20,15);
1055 for(i=0;i<15;i++) {
1056 /* BB are there cases in which a comma can be
1057 valid in this workstation netbios name (and need
1058 special handling)? */
1059
1060 /* We do not uppercase netbiosname for user */
1061 if (value[i]==0)
1062 break;
1063 else
1064 vol->source_rfc1001_name[i] = value[i];
1065 }
1066 /* The string has 16th byte zero still from
1067 set at top of the function */
1068 if((i==15) && (value[i] != 0))
a10faeb2
SF
1069 printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
1070 }
1071 } else if (strnicmp(data, "servern", 7) == 0) {
1072 /* servernetbiosname specified override *SMBSERVER */
1073 if (!value || !*value || (*value == ' ')) {
1074 cFYI(1,("empty server netbiosname specified"));
1075 } else {
1076 /* last byte, type, is 0x20 for servr type */
1077 memset(vol->target_rfc1001_name,0x20,16);
1078
1079 for(i=0;i<15;i++) {
1080 /* BB are there cases in which a comma can be
1081 valid in this workstation netbios name (and need
1082 special handling)? */
1083
1084 /* user or mount helper must uppercase netbiosname */
1085 if (value[i]==0)
1086 break;
1087 else
1088 vol->target_rfc1001_name[i] = value[i];
1089 }
1090 /* The string has 16th byte zero still from
1091 set at top of the function */
1092 if((i==15) && (value[i] != 0))
1093 printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
1da177e4
LT
1094 }
1095 } else if (strnicmp(data, "credentials", 4) == 0) {
1096 /* ignore */
1097 } else if (strnicmp(data, "version", 3) == 0) {
1098 /* ignore */
1099 } else if (strnicmp(data, "guest",5) == 0) {
1100 /* ignore */
1101 } else if (strnicmp(data, "rw", 2) == 0) {
1102 vol->rw = TRUE;
1103 } else if ((strnicmp(data, "suid", 4) == 0) ||
1104 (strnicmp(data, "nosuid", 6) == 0) ||
1105 (strnicmp(data, "exec", 4) == 0) ||
1106 (strnicmp(data, "noexec", 6) == 0) ||
1107 (strnicmp(data, "nodev", 5) == 0) ||
1108 (strnicmp(data, "noauto", 6) == 0) ||
1109 (strnicmp(data, "dev", 3) == 0)) {
1110 /* The mount tool or mount.cifs helper (if present)
1111 uses these opts to set flags, and the flags are read
1112 by the kernel vfs layer before we get here (ie
1113 before read super) so there is no point trying to
1114 parse these options again and set anything and it
1115 is ok to just ignore them */
1116 continue;
1117 } else if (strnicmp(data, "ro", 2) == 0) {
1118 vol->rw = FALSE;
1119 } else if (strnicmp(data, "hard", 4) == 0) {
1120 vol->retry = 1;
1121 } else if (strnicmp(data, "soft", 4) == 0) {
1122 vol->retry = 0;
1123 } else if (strnicmp(data, "perm", 4) == 0) {
1124 vol->noperm = 0;
1125 } else if (strnicmp(data, "noperm", 6) == 0) {
1126 vol->noperm = 1;
6a0b4824
SF
1127 } else if (strnicmp(data, "mapchars", 8) == 0) {
1128 vol->remap = 1;
1129 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1130 vol->remap = 0;
d7245c2c
SF
1131 } else if (strnicmp(data, "sfu", 3) == 0) {
1132 vol->sfu_emul = 1;
1133 } else if (strnicmp(data, "nosfu", 5) == 0) {
1134 vol->sfu_emul = 0;
ac67055e
JA
1135 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1136 vol->posix_paths = 1;
1137 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1138 vol->posix_paths = 0;
a10faeb2
SF
1139 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1140 (strnicmp(data, "ignorecase", 10) == 0)) {
c46fa8ac
SF
1141 vol->nocase = 1;
1142 } else if (strnicmp(data, "brl", 3) == 0) {
1143 vol->nobrl = 0;
cb8be640 1144 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1c955187 1145 (strnicmp(data, "nolock", 6) == 0)) {
c46fa8ac 1146 vol->nobrl = 1;
d3485d37
SF
1147 /* turn off mandatory locking in mode
1148 if remote locking is turned off since the
1149 local vfs will do advisory */
1150 if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1151 vol->file_mode = S_IALLUGO;
1da177e4
LT
1152 } else if (strnicmp(data, "setuids", 7) == 0) {
1153 vol->setuids = 1;
1154 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1155 vol->setuids = 0;
1156 } else if (strnicmp(data, "nohard", 6) == 0) {
1157 vol->retry = 0;
1158 } else if (strnicmp(data, "nosoft", 6) == 0) {
1159 vol->retry = 1;
1160 } else if (strnicmp(data, "nointr", 6) == 0) {
1161 vol->intr = 0;
1162 } else if (strnicmp(data, "intr", 4) == 0) {
1163 vol->intr = 1;
1164 } else if (strnicmp(data, "serverino",7) == 0) {
1165 vol->server_ino = 1;
1166 } else if (strnicmp(data, "noserverino",9) == 0) {
1167 vol->server_ino = 0;
0a4b92c0
SF
1168 } else if (strnicmp(data, "cifsacl",7) == 0) {
1169 vol->cifs_acl = 1;
1170 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1171 vol->cifs_acl = 0;
1da177e4
LT
1172 } else if (strnicmp(data, "acl",3) == 0) {
1173 vol->no_psx_acl = 0;
1174 } else if (strnicmp(data, "noacl",5) == 0) {
1175 vol->no_psx_acl = 1;
1176 } else if (strnicmp(data, "direct",6) == 0) {
1177 vol->direct_io = 1;
1178 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1179 vol->direct_io = 1;
1180 } else if (strnicmp(data, "in6_addr",8) == 0) {
1181 if (!value || !*value) {
1182 vol->in6_addr = NULL;
1183 } else if (strnlen(value, 49) == 48) {
1184 vol->in6_addr = value;
1185 } else {
1186 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1187 return 1;
1188 }
1189 } else if (strnicmp(data, "noac", 4) == 0) {
1190 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1191 } else
1192 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1193 }
1194 if (vol->UNC == NULL) {
1195 if(devname == NULL) {
1196 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1197 return 1;
1198 }
1199 if ((temp_len = strnlen(devname, 300)) < 300) {
1200 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1201 if(vol->UNC == NULL)
1202 return 1;
1203 strcpy(vol->UNC,devname);
1204 if (strncmp(vol->UNC, "//", 2) == 0) {
1205 vol->UNC[0] = '\\';
1206 vol->UNC[1] = '\\';
1207 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1208 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1209 return 1;
1210 }
1211 } else {
1212 printk(KERN_WARNING "CIFS: UNC name too long\n");
1213 return 1;
1214 }
1215 }
1216 if(vol->UNCip == NULL)
1217 vol->UNCip = &vol->UNC[2];
1218
1219 return 0;
1220}
1221
1222static struct cifsSesInfo *
1223cifs_find_tcp_session(struct in_addr * target_ip_addr,
1224 struct in6_addr *target_ip6_addr,
1225 char *userName, struct TCP_Server_Info **psrvTcp)
1226{
1227 struct list_head *tmp;
1228 struct cifsSesInfo *ses;
1229 *psrvTcp = NULL;
1230 read_lock(&GlobalSMBSeslock);
1231
1232 list_for_each(tmp, &GlobalSMBSessionList) {
1233 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1234 if (ses->server) {
1235 if((target_ip_addr &&
1236 (ses->server->addr.sockAddr.sin_addr.s_addr
1237 == target_ip_addr->s_addr)) || (target_ip6_addr
1238 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1239 target_ip6_addr,sizeof(*target_ip6_addr)))){
1240 /* BB lock server and tcp session and increment use count here?? */
1241 *psrvTcp = ses->server; /* found a match on the TCP session */
1242 /* BB check if reconnection needed */
1243 if (strncmp
1244 (ses->userName, userName,
1245 MAX_USERNAME_SIZE) == 0){
1246 read_unlock(&GlobalSMBSeslock);
1247 return ses; /* found exact match on both tcp and SMB sessions */
1248 }
1249 }
1250 }
1251 /* else tcp and smb sessions need reconnection */
1252 }
1253 read_unlock(&GlobalSMBSeslock);
1254 return NULL;
1255}
1256
1257static struct cifsTconInfo *
1258find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1259{
1260 struct list_head *tmp;
1261 struct cifsTconInfo *tcon;
1262
1263 read_lock(&GlobalSMBSeslock);
1264 list_for_each(tmp, &GlobalTreeConnectionList) {
1265 cFYI(1, ("Next tcon - "));
1266 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1267 if (tcon->ses) {
1268 if (tcon->ses->server) {
1269 cFYI(1,
1270 (" old ip addr: %x == new ip %x ?",
1271 tcon->ses->server->addr.sockAddr.sin_addr.
1272 s_addr, new_target_ip_addr));
1273 if (tcon->ses->server->addr.sockAddr.sin_addr.
1274 s_addr == new_target_ip_addr) {
1275 /* BB lock tcon and server and tcp session and increment use count here? */
1276 /* found a match on the TCP session */
1277 /* BB check if reconnection needed */
1278 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1279 tcon->treeName, uncName));
1280 if (strncmp
1281 (tcon->treeName, uncName,
1282 MAX_TREE_SIZE) == 0) {
1283 cFYI(1,
1284 ("Matched UNC, old user: %s == new: %s ?",
1285 tcon->treeName, uncName));
1286 if (strncmp
1287 (tcon->ses->userName,
1288 userName,
1289 MAX_USERNAME_SIZE) == 0) {
1290 read_unlock(&GlobalSMBSeslock);
1291 return tcon;/* also matched user (smb session)*/
1292 }
1293 }
1294 }
1295 }
1296 }
1297 }
1298 read_unlock(&GlobalSMBSeslock);
1299 return NULL;
1300}
1301
1302int
1303connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
737b758c
SF
1304 const char *old_path, const struct nls_table *nls_codepage,
1305 int remap)
1da177e4
LT
1306{
1307 unsigned char *referrals = NULL;
1308 unsigned int num_referrals;
1309 int rc = 0;
1310
1311 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
737b758c 1312 &num_referrals, &referrals, remap);
1da177e4
LT
1313
1314 /* BB Add in code to: if valid refrl, if not ip address contact
1315 the helper that resolves tcp names, mount to it, try to
1316 tcon to it unmount it if fail */
1317
f99d49ad 1318 kfree(referrals);
1da177e4
LT
1319
1320 return rc;
1321}
1322
1323int
1324get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1325 const char *old_path, const struct nls_table *nls_codepage,
737b758c
SF
1326 unsigned int *pnum_referrals,
1327 unsigned char ** preferrals, int remap)
1da177e4
LT
1328{
1329 char *temp_unc;
1330 int rc = 0;
1331
1332 *pnum_referrals = 0;
1333
1334 if (pSesInfo->ipc_tid == 0) {
1335 temp_unc = kmalloc(2 /* for slashes */ +
1336 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1337 + 1 + 4 /* slash IPC$ */ + 2,
1338 GFP_KERNEL);
1339 if (temp_unc == NULL)
1340 return -ENOMEM;
1341 temp_unc[0] = '\\';
1342 temp_unc[1] = '\\';
1343 strcpy(temp_unc + 2, pSesInfo->serverName);
1344 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1345 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1346 cFYI(1,
1347 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1348 kfree(temp_unc);
1349 }
1350 if (rc == 0)
1351 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
737b758c 1352 pnum_referrals, nls_codepage, remap);
1da177e4
LT
1353
1354 return rc;
1355}
1356
1357/* See RFC1001 section 14 on representation of Netbios names */
1358static void rfc1002mangle(char * target,char * source, unsigned int length)
1359{
1360 unsigned int i,j;
1361
1362 for(i=0,j=0;i<(length);i++) {
1363 /* mask a nibble at a time and encode */
1364 target[j] = 'A' + (0x0F & (source[i] >> 4));
1365 target[j+1] = 'A' + (0x0F & source[i]);
1366 j+=2;
1367 }
1368
1369}
1370
1371
1372static int
1373ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
a10faeb2 1374 char * netbios_name, char * target_name)
1da177e4
LT
1375{
1376 int rc = 0;
1377 int connected = 0;
1378 __be16 orig_port = 0;
1379
1380 if(*csocket == NULL) {
1381 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1382 if (rc < 0) {
1383 cERROR(1, ("Error %d creating socket",rc));
1384 *csocket = NULL;
1385 return rc;
1386 } else {
1387 /* BB other socket options to set KEEPALIVE, NODELAY? */
1388 cFYI(1,("Socket created"));
1389 (*csocket)->sk->sk_allocation = GFP_NOFS;
1390 }
1391 }
1392
1393 psin_server->sin_family = AF_INET;
1394 if(psin_server->sin_port) { /* user overrode default port */
1395 rc = (*csocket)->ops->connect(*csocket,
1396 (struct sockaddr *) psin_server,
1397 sizeof (struct sockaddr_in),0);
1398 if (rc >= 0)
1399 connected = 1;
1400 }
1401
1402 if(!connected) {
1403 /* save original port so we can retry user specified port
1404 later if fall back ports fail this time */
1405 orig_port = psin_server->sin_port;
1406
1407 /* do not retry on the same port we just failed on */
1408 if(psin_server->sin_port != htons(CIFS_PORT)) {
1409 psin_server->sin_port = htons(CIFS_PORT);
1410
1411 rc = (*csocket)->ops->connect(*csocket,
1412 (struct sockaddr *) psin_server,
1413 sizeof (struct sockaddr_in),0);
1414 if (rc >= 0)
1415 connected = 1;
1416 }
1417 }
1418 if (!connected) {
1419 psin_server->sin_port = htons(RFC1001_PORT);
1420 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1421 psin_server, sizeof (struct sockaddr_in),0);
1422 if (rc >= 0)
1423 connected = 1;
1424 }
1425
1426 /* give up here - unless we want to retry on different
1427 protocol families some day */
1428 if (!connected) {
1429 if(orig_port)
1430 psin_server->sin_port = orig_port;
1431 cFYI(1,("Error %d connecting to server via ipv4",rc));
1432 sock_release(*csocket);
1433 *csocket = NULL;
1434 return rc;
1435 }
1436 /* Eventually check for other socket options to change from
1437 the default. sock_setsockopt not used because it expects
1438 user space buffer */
b387eaeb
SF
1439 cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf,
1440 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1da177e4 1441 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
b387eaeb
SF
1442 /* make the bufsizes depend on wsize/rsize and max requests */
1443 if((*csocket)->sk->sk_sndbuf < (200 * 1024))
1444 (*csocket)->sk->sk_sndbuf = 200 * 1024;
1445 if((*csocket)->sk->sk_rcvbuf < (140 * 1024))
1446 (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1da177e4
LT
1447
1448 /* send RFC1001 sessinit */
1da177e4
LT
1449 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1450 /* some servers require RFC1001 sessinit before sending
1451 negprot - BB check reconnection in case where second
1452 sessinit is sent but no second negprot */
1453 struct rfc1002_session_packet * ses_init_buf;
1454 struct smb_hdr * smb_buf;
e915fc49 1455 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1da177e4
LT
1456 if(ses_init_buf) {
1457 ses_init_buf->trailer.session_req.called_len = 32;
a10faeb2
SF
1458 if(target_name && (target_name[0] != 0)) {
1459 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1460 target_name, 16);
1461 } else {
1462 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1463 DEFAULT_CIFS_CALLED_NAME,16);
1464 }
1465
1da177e4
LT
1466 ses_init_buf->trailer.session_req.calling_len = 32;
1467 /* calling name ends in null (byte 16) from old smb
1468 convention. */
1469 if(netbios_name && (netbios_name[0] !=0)) {
1470 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1471 netbios_name,16);
1472 } else {
1473 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1474 "LINUX_CIFS_CLNT",16);
1475 }
1476 ses_init_buf->trailer.session_req.scope1 = 0;
1477 ses_init_buf->trailer.session_req.scope2 = 0;
1478 smb_buf = (struct smb_hdr *)ses_init_buf;
1479 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1480 smb_buf->smb_buf_length = 0x81000044;
1481 rc = smb_send(*csocket, smb_buf, 0x44,
1482 (struct sockaddr *)psin_server);
1483 kfree(ses_init_buf);
083d3a2c
SF
1484 msleep(1); /* RFC1001 layer in at least one server
1485 requires very short break before negprot
1486 presumably because not expecting negprot
1487 to follow so fast. This is a simple
1488 solution that works without
1489 complicating the code and causes no
1490 significant slowing down on mount
1491 for everyone else */
1da177e4
LT
1492 }
1493 /* else the negprot may still work without this
1494 even though malloc failed */
1495
1496 }
1497
1498 return rc;
1499}
1500
1501static int
1502ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1503{
1504 int rc = 0;
1505 int connected = 0;
1506 __be16 orig_port = 0;
1507
1508 if(*csocket == NULL) {
1509 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1510 if (rc < 0) {
1511 cERROR(1, ("Error %d creating ipv6 socket",rc));
1512 *csocket = NULL;
1513 return rc;
1514 } else {
1515 /* BB other socket options to set KEEPALIVE, NODELAY? */
1516 cFYI(1,("ipv6 Socket created"));
1517 (*csocket)->sk->sk_allocation = GFP_NOFS;
1518 }
1519 }
1520
1521 psin_server->sin6_family = AF_INET6;
1522
1523 if(psin_server->sin6_port) { /* user overrode default port */
1524 rc = (*csocket)->ops->connect(*csocket,
1525 (struct sockaddr *) psin_server,
1526 sizeof (struct sockaddr_in6),0);
1527 if (rc >= 0)
1528 connected = 1;
1529 }
1530
1531 if(!connected) {
1532 /* save original port so we can retry user specified port
1533 later if fall back ports fail this time */
1534
1535 orig_port = psin_server->sin6_port;
1536 /* do not retry on the same port we just failed on */
1537 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1538 psin_server->sin6_port = htons(CIFS_PORT);
1539
1540 rc = (*csocket)->ops->connect(*csocket,
1541 (struct sockaddr *) psin_server,
1542 sizeof (struct sockaddr_in6),0);
1543 if (rc >= 0)
1544 connected = 1;
1545 }
1546 }
1547 if (!connected) {
1548 psin_server->sin6_port = htons(RFC1001_PORT);
1549 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1550 psin_server, sizeof (struct sockaddr_in6),0);
1551 if (rc >= 0)
1552 connected = 1;
1553 }
1554
1555 /* give up here - unless we want to retry on different
1556 protocol families some day */
1557 if (!connected) {
1558 if(orig_port)
1559 psin_server->sin6_port = orig_port;
1560 cFYI(1,("Error %d connecting to server via ipv6",rc));
1561 sock_release(*csocket);
1562 *csocket = NULL;
1563 return rc;
1564 }
1565 /* Eventually check for other socket options to change from
1566 the default. sock_setsockopt not used because it expects
1567 user space buffer */
1568 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1569
1570 return rc;
1571}
1572
1573int
1574cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1575 char *mount_data, const char *devname)
1576{
1577 int rc = 0;
1578 int xid;
1579 int address_type = AF_INET;
1580 struct socket *csocket = NULL;
1581 struct sockaddr_in sin_server;
1582 struct sockaddr_in6 sin_server6;
1583 struct smb_vol volume_info;
1584 struct cifsSesInfo *pSesInfo = NULL;
1585 struct cifsSesInfo *existingCifsSes = NULL;
1586 struct cifsTconInfo *tcon = NULL;
1587 struct TCP_Server_Info *srvTcp = NULL;
1588
1589 xid = GetXid();
1590
1591/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1592
1593 memset(&volume_info,0,sizeof(struct smb_vol));
1594 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
f99d49ad
JJ
1595 kfree(volume_info.UNC);
1596 kfree(volume_info.password);
1da177e4
LT
1597 FreeXid(xid);
1598 return -EINVAL;
1599 }
1600
1601 if (volume_info.username) {
1602 /* BB fixme parse for domain name here */
1603 cFYI(1, ("Username: %s ", volume_info.username));
1604
1605 } else {
bf820679 1606 cifserror("No username specified");
1da177e4
LT
1607 /* In userspace mount helper we can get user name from alternate
1608 locations such as env variables and files on disk */
f99d49ad
JJ
1609 kfree(volume_info.UNC);
1610 kfree(volume_info.password);
1da177e4
LT
1611 FreeXid(xid);
1612 return -EINVAL;
1613 }
1614
1615 if (volume_info.UNCip && volume_info.UNC) {
1616 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1617
1618 if(rc <= 0) {
1619 /* not ipv4 address, try ipv6 */
1620 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1621 if(rc > 0)
1622 address_type = AF_INET6;
1623 } else {
1624 address_type = AF_INET;
1625 }
1626
1627 if(rc <= 0) {
1628 /* we failed translating address */
f99d49ad
JJ
1629 kfree(volume_info.UNC);
1630 kfree(volume_info.password);
1da177e4
LT
1631 FreeXid(xid);
1632 return -EINVAL;
1633 }
1634
1635 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1636 /* success */
1637 rc = 0;
1638 } else if (volume_info.UNCip){
1639 /* BB using ip addr as server name connect to the DFS root below */
1640 cERROR(1,("Connecting to DFS root not implemented yet"));
f99d49ad
JJ
1641 kfree(volume_info.UNC);
1642 kfree(volume_info.password);
1da177e4
LT
1643 FreeXid(xid);
1644 return -EINVAL;
1645 } else /* which servers DFS root would we conect to */ {
1646 cERROR(1,
bf820679 1647 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
f99d49ad
JJ
1648 kfree(volume_info.UNC);
1649 kfree(volume_info.password);
1da177e4
LT
1650 FreeXid(xid);
1651 return -EINVAL;
1652 }
1653
1654 /* this is needed for ASCII cp to Unicode converts */
1655 if(volume_info.iocharset == NULL) {
1656 cifs_sb->local_nls = load_nls_default();
1657 /* load_nls_default can not return null */
1658 } else {
1659 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1660 if(cifs_sb->local_nls == NULL) {
1661 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
f99d49ad
JJ
1662 kfree(volume_info.UNC);
1663 kfree(volume_info.password);
1da177e4
LT
1664 FreeXid(xid);
1665 return -ELIBACC;
1666 }
1667 }
1668
1669 if(address_type == AF_INET)
1670 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1671 NULL /* no ipv6 addr */,
1672 volume_info.username, &srvTcp);
1673 else if(address_type == AF_INET6)
1674 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1675 &sin_server6.sin6_addr,
1676 volume_info.username, &srvTcp);
1677 else {
f99d49ad
JJ
1678 kfree(volume_info.UNC);
1679 kfree(volume_info.password);
1da177e4
LT
1680 FreeXid(xid);
1681 return -EINVAL;
1682 }
1683
1684
1685 if (srvTcp) {
bf820679 1686 cFYI(1, ("Existing tcp session with server found"));
1da177e4
LT
1687 } else { /* create socket */
1688 if(volume_info.port)
1689 sin_server.sin_port = htons(volume_info.port);
1690 else
1691 sin_server.sin_port = 0;
a10faeb2
SF
1692 rc = ipv4_connect(&sin_server,&csocket,
1693 volume_info.source_rfc1001_name,
1694 volume_info.target_rfc1001_name);
1da177e4
LT
1695 if (rc < 0) {
1696 cERROR(1,
1697 ("Error connecting to IPv4 socket. Aborting operation"));
1698 if(csocket != NULL)
1699 sock_release(csocket);
f99d49ad
JJ
1700 kfree(volume_info.UNC);
1701 kfree(volume_info.password);
1da177e4
LT
1702 FreeXid(xid);
1703 return rc;
1704 }
1705
1706 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1707 if (srvTcp == NULL) {
1708 rc = -ENOMEM;
1709 sock_release(csocket);
f99d49ad
JJ
1710 kfree(volume_info.UNC);
1711 kfree(volume_info.password);
1da177e4
LT
1712 FreeXid(xid);
1713 return rc;
1714 } else {
1715 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1716 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1717 atomic_set(&srvTcp->inFlight,0);
1718 /* BB Add code for ipv6 case too */
1719 srvTcp->ssocket = csocket;
1720 srvTcp->protocolType = IPV4;
1721 init_waitqueue_head(&srvTcp->response_q);
1722 init_waitqueue_head(&srvTcp->request_q);
1723 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1724 /* at this point we are the only ones with the pointer
1725 to the struct since the kernel thread not created yet
1726 so no need to spinlock this init of tcpStatus */
1727 srvTcp->tcpStatus = CifsNew;
1728 init_MUTEX(&srvTcp->tcpSem);
1729 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1730 CLONE_FS | CLONE_FILES | CLONE_VM);
1731 if(rc < 0) {
1732 rc = -ENOMEM;
1733 sock_release(csocket);
f99d49ad
JJ
1734 kfree(volume_info.UNC);
1735 kfree(volume_info.password);
1da177e4
LT
1736 FreeXid(xid);
1737 return rc;
f191401f
SF
1738 }
1739 wait_for_completion(&cifsd_complete);
1740 rc = 0;
1da177e4 1741 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
a10faeb2 1742 memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
ad009ac9 1743 srvTcp->sequence_number = 0;
1da177e4
LT
1744 }
1745 }
1746
1747 if (existingCifsSes) {
1748 pSesInfo = existingCifsSes;
bf820679 1749 cFYI(1, ("Existing smb sess found"));
f99d49ad 1750 kfree(volume_info.password);
1da177e4
LT
1751 /* volume_info.UNC freed at end of function */
1752 } else if (!rc) {
bf820679 1753 cFYI(1, ("Existing smb sess not found"));
1da177e4
LT
1754 pSesInfo = sesInfoAlloc();
1755 if (pSesInfo == NULL)
1756 rc = -ENOMEM;
1757 else {
1758 pSesInfo->server = srvTcp;
1759 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1760 NIPQUAD(sin_server.sin_addr.s_addr));
1761 }
1762
1763 if (!rc){
1764 /* volume_info.password freed at unmount */
1765 if (volume_info.password)
1766 pSesInfo->password = volume_info.password;
1767 if (volume_info.username)
1768 strncpy(pSesInfo->userName,
1769 volume_info.username,MAX_USERNAME_SIZE);
3979877e
SF
1770 if (volume_info.domainname) {
1771 int len = strlen(volume_info.domainname);
1772 pSesInfo->domainName =
1773 kmalloc(len + 1, GFP_KERNEL);
1774 if(pSesInfo->domainName)
1775 strcpy(pSesInfo->domainName,
1776 volume_info.domainname);
1777 }
1da177e4
LT
1778 pSesInfo->linux_uid = volume_info.linux_uid;
1779 down(&pSesInfo->sesSem);
1780 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1781 up(&pSesInfo->sesSem);
1782 if(!rc)
1783 atomic_inc(&srvTcp->socketUseCount);
1784 } else
f99d49ad 1785 kfree(volume_info.password);
1da177e4
LT
1786 }
1787
1788 /* search for existing tcon to this server share */
1789 if (!rc) {
0ae0efad
SF
1790 if(volume_info.rsize > CIFSMaxBufSize) {
1791 cERROR(1,("rsize %d too large, using MaxBufSize",
1792 volume_info.rsize));
1793 cifs_sb->rsize = CIFSMaxBufSize;
1794 } else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1da177e4 1795 cifs_sb->rsize = volume_info.rsize;
0ae0efad
SF
1796 else /* default */
1797 cifs_sb->rsize = CIFSMaxBufSize;
1798
1799 if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
1800 cERROR(1,("wsize %d too large using 4096 instead",
1801 volume_info.wsize));
1802 cifs_sb->wsize = 4096;
1803 } else if(volume_info.wsize)
1da177e4
LT
1804 cifs_sb->wsize = volume_info.wsize;
1805 else
17cbbafe 1806 cifs_sb->wsize =
1877c9ea
SF
1807 min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
1808 127*1024);
17cbbafe
SF
1809 /* old default of CIFSMaxBufSize was too small now
1810 that SMB Write2 can send multiple pages in kvec.
1811 RFC1001 does not describe what happens when frame
1812 bigger than 128K is sent so use that as max in
1813 conjunction with 52K kvec constraint on arch with 4K
1814 page size */
1815
6cec2aed
SF
1816 if(cifs_sb->rsize < 2048) {
1817 cifs_sb->rsize = 2048;
1818 /* Windows ME may prefer this */
1819 cFYI(1,("readsize set to minimum 2048"));
1da177e4
LT
1820 }
1821 cifs_sb->mnt_uid = volume_info.linux_uid;
1822 cifs_sb->mnt_gid = volume_info.linux_gid;
1823 cifs_sb->mnt_file_mode = volume_info.file_mode;
1824 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
eeac8047
SF
1825 cFYI(1,("file mode: 0x%x dir mode: 0x%x",
1826 cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1da177e4
LT
1827
1828 if(volume_info.noperm)
1829 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1830 if(volume_info.setuids)
1831 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1832 if(volume_info.server_ino)
1833 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
6a0b4824
SF
1834 if(volume_info.remap)
1835 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1da177e4
LT
1836 if(volume_info.no_xattr)
1837 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
d7245c2c
SF
1838 if(volume_info.sfu_emul)
1839 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
c46fa8ac
SF
1840 if(volume_info.nobrl)
1841 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
0a4b92c0
SF
1842 if(volume_info.cifs_acl)
1843 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
ac67055e 1844
1da177e4 1845 if(volume_info.direct_io) {
c46fa8ac 1846 cFYI(1,("mounting share using direct i/o"));
1da177e4
LT
1847 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1848 }
1849
1850 tcon =
1851 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1852 volume_info.username);
1853 if (tcon) {
bf820679 1854 cFYI(1, ("Found match on UNC path"));
1da177e4
LT
1855 /* we can have only one retry value for a connection
1856 to a share so for resources mounted more than once
1857 to the same server share the last value passed in
1858 for the retry flag is used */
1859 tcon->retry = volume_info.retry;
d3485d37 1860 tcon->nocase = volume_info.nocase;
1da177e4
LT
1861 } else {
1862 tcon = tconInfoAlloc();
1863 if (tcon == NULL)
1864 rc = -ENOMEM;
1865 else {
1866 /* check for null share name ie connect to dfs root */
1867
1868 /* BB check if this works for exactly length three strings */
1869 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1870 && (strchr(volume_info.UNC + 3, '/') ==
1871 NULL)) {
737b758c
SF
1872 rc = connect_to_dfs_path(xid, pSesInfo,
1873 "", cifs_sb->local_nls,
1874 cifs_sb->mnt_cifs_flags &
1875 CIFS_MOUNT_MAP_SPECIAL_CHR);
f99d49ad 1876 kfree(volume_info.UNC);
1da177e4
LT
1877 FreeXid(xid);
1878 return -ENODEV;
1879 } else {
1880 rc = CIFSTCon(xid, pSesInfo,
1881 volume_info.UNC,
1882 tcon, cifs_sb->local_nls);
1883 cFYI(1, ("CIFS Tcon rc = %d", rc));
1884 }
1885 if (!rc) {
1886 atomic_inc(&pSesInfo->inUse);
1887 tcon->retry = volume_info.retry;
d3485d37 1888 tcon->nocase = volume_info.nocase;
1da177e4
LT
1889 }
1890 }
1891 }
1892 }
1893 if(pSesInfo) {
1894 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1895 sb->s_maxbytes = (u64) 1 << 63;
1896 } else
1897 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1898 }
1899
1900 sb->s_time_gran = 100;
1901
1902/* on error free sesinfo and tcon struct if needed */
1903 if (rc) {
1904 /* if session setup failed, use count is zero but
1905 we still need to free cifsd thread */
1906 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1907 spin_lock(&GlobalMid_Lock);
1908 srvTcp->tcpStatus = CifsExiting;
1909 spin_unlock(&GlobalMid_Lock);
f191401f 1910 if(srvTcp->tsk) {
1da177e4 1911 send_sig(SIGKILL,srvTcp->tsk,1);
f191401f
SF
1912 wait_for_completion(&cifsd_complete);
1913 }
1da177e4
LT
1914 }
1915 /* If find_unc succeeded then rc == 0 so we can not end */
1916 if (tcon) /* up accidently freeing someone elses tcon struct */
1917 tconInfoFree(tcon);
1918 if (existingCifsSes == NULL) {
1919 if (pSesInfo) {
1920 if ((pSesInfo->server) &&
1921 (pSesInfo->status == CifsGood)) {
1922 int temp_rc;
1923 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1924 /* if the socketUseCount is now zero */
1925 if((temp_rc == -ESHUTDOWN) &&
f191401f 1926 (pSesInfo->server->tsk)) {
1da177e4 1927 send_sig(SIGKILL,pSesInfo->server->tsk,1);
f191401f
SF
1928 wait_for_completion(&cifsd_complete);
1929 }
1da177e4
LT
1930 } else
1931 cFYI(1, ("No session or bad tcon"));
1932 sesInfoFree(pSesInfo);
1933 /* pSesInfo = NULL; */
1934 }
1935 }
1936 } else {
1937 atomic_inc(&tcon->useCount);
1938 cifs_sb->tcon = tcon;
1939 tcon->ses = pSesInfo;
1940
82940a46 1941 /* do not care if following two calls succeed - informational */
737b758c
SF
1942 CIFSSMBQFSDeviceInfo(xid, tcon);
1943 CIFSSMBQFSAttributeInfo(xid, tcon);
82940a46 1944
1da177e4 1945 if (tcon->ses->capabilities & CAP_UNIX) {
737b758c 1946 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
82940a46
SF
1947 __u64 cap =
1948 le64_to_cpu(tcon->fsUnixInfo.Capability);
1949 cap &= CIFS_UNIX_CAP_MASK;
1950 if(volume_info.no_psx_acl)
1951 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1952 else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
1953 cFYI(1,("negotiated posix acl support"));
1954 sb->s_flags |= MS_POSIXACL;
1da177e4 1955 }
ac67055e 1956
82940a46
SF
1957 if(volume_info.posix_paths == 0)
1958 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1959 else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
1960 cFYI(1,("negotiate posix pathnames"));
1961 cifs_sb->mnt_cifs_flags |=
1962 CIFS_MOUNT_POSIX_PATHS;
1963 }
1964
1965 cFYI(1,("Negotiate caps 0x%x",(int)cap));
1966
1967 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1968 cFYI(1,("setting capabilities failed"));
ac67055e 1969 }
1da177e4
LT
1970 }
1971 }
3e84469d
SF
1972 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
1973 cifs_sb->wsize = min(cifs_sb->wsize,
1974 (tcon->ses->server->maxBuf -
1975 MAX_CIFS_HDR_SIZE));
0ae0efad
SF
1976 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
1977 cifs_sb->rsize = min(cifs_sb->rsize,
1978 (tcon->ses->server->maxBuf -
1979 MAX_CIFS_HDR_SIZE));
1da177e4
LT
1980 }
1981
1982 /* volume_info.password is freed above when existing session found
1983 (in which case it is not needed anymore) but when new sesion is created
1984 the password ptr is put in the new session structure (in which case the
1985 password will be freed at unmount time) */
f99d49ad 1986 kfree(volume_info.UNC);
1da177e4
LT
1987 FreeXid(xid);
1988 return rc;
1989}
1990
1991static int
1992CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1993 char session_key[CIFS_SESSION_KEY_SIZE],
1994 const struct nls_table *nls_codepage)
1995{
1996 struct smb_hdr *smb_buffer;
1997 struct smb_hdr *smb_buffer_response;
1998 SESSION_SETUP_ANDX *pSMB;
1999 SESSION_SETUP_ANDX *pSMBr;
2000 char *bcc_ptr;
2001 char *user;
2002 char *domain;
2003 int rc = 0;
2004 int remaining_words = 0;
2005 int bytes_returned = 0;
2006 int len;
2007 __u32 capabilities;
2008 __u16 count;
2009
eeac8047 2010 cFYI(1, ("In sesssetup"));
1da177e4
LT
2011 if(ses == NULL)
2012 return -EINVAL;
2013 user = ses->userName;
2014 domain = ses->domainName;
2015 smb_buffer = cifs_buf_get();
2016 if (smb_buffer == NULL) {
2017 return -ENOMEM;
2018 }
2019 smb_buffer_response = smb_buffer;
2020 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2021
2022 /* send SMBsessionSetup here */
2023 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2024 NULL /* no tCon exists yet */ , 13 /* wct */ );
2025
1982c344 2026 smb_buffer->Mid = GetNextMid(ses->server);
1da177e4
LT
2027 pSMB->req_no_secext.AndXCommand = 0xFF;
2028 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2029 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2030
2031 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2032 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2033
2034 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2035 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
2036 if (ses->capabilities & CAP_UNICODE) {
2037 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2038 capabilities |= CAP_UNICODE;
2039 }
2040 if (ses->capabilities & CAP_STATUS32) {
2041 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2042 capabilities |= CAP_STATUS32;
2043 }
2044 if (ses->capabilities & CAP_DFS) {
2045 smb_buffer->Flags2 |= SMBFLG2_DFS;
2046 capabilities |= CAP_DFS;
2047 }
2048 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2049
2050 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2051 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2052
2053 pSMB->req_no_secext.CaseSensitivePasswordLength =
2054 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2055 bcc_ptr = pByteArea(smb_buffer);
2056 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
2057 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2058 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
2059 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2060
2061 if (ses->capabilities & CAP_UNICODE) {
2062 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
2063 *bcc_ptr = 0;
2064 bcc_ptr++;
2065 }
2066 if(user == NULL)
3979877e 2067 bytes_returned = 0; /* skip null user */
1da177e4
LT
2068 else
2069 bytes_returned =
e89dc920 2070 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
1da177e4
LT
2071 nls_codepage);
2072 /* convert number of 16 bit words to bytes */
2073 bcc_ptr += 2 * bytes_returned;
2074 bcc_ptr += 2; /* trailing null */
2075 if (domain == NULL)
2076 bytes_returned =
e89dc920 2077 cifs_strtoUCS((__le16 *) bcc_ptr,
1da177e4
LT
2078 "CIFS_LINUX_DOM", 32, nls_codepage);
2079 else
2080 bytes_returned =
e89dc920 2081 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
1da177e4
LT
2082 nls_codepage);
2083 bcc_ptr += 2 * bytes_returned;
2084 bcc_ptr += 2;
2085 bytes_returned =
e89dc920 2086 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
1da177e4
LT
2087 32, nls_codepage);
2088 bcc_ptr += 2 * bytes_returned;
2089 bytes_returned =
e89dc920 2090 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
1da177e4
LT
2091 32, nls_codepage);
2092 bcc_ptr += 2 * bytes_returned;
2093 bcc_ptr += 2;
2094 bytes_returned =
e89dc920 2095 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
1da177e4
LT
2096 64, nls_codepage);
2097 bcc_ptr += 2 * bytes_returned;
2098 bcc_ptr += 2;
2099 } else {
2100 if(user != NULL) {
2101 strncpy(bcc_ptr, user, 200);
2102 bcc_ptr += strnlen(user, 200);
2103 }
2104 *bcc_ptr = 0;
2105 bcc_ptr++;
2106 if (domain == NULL) {
2107 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2108 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2109 } else {
2110 strncpy(bcc_ptr, domain, 64);
2111 bcc_ptr += strnlen(domain, 64);
2112 *bcc_ptr = 0;
2113 bcc_ptr++;
2114 }
2115 strcpy(bcc_ptr, "Linux version ");
2116 bcc_ptr += strlen("Linux version ");
2117 strcpy(bcc_ptr, system_utsname.release);
2118 bcc_ptr += strlen(system_utsname.release) + 1;
2119 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2120 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2121 }
2122 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2123 smb_buffer->smb_buf_length += count;
2124 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2125
2126 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2127 &bytes_returned, 1);
2128 if (rc) {
2129/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2130 } else if ((smb_buffer_response->WordCount == 3)
2131 || (smb_buffer_response->WordCount == 4)) {
2132 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2133 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2134 if (action & GUEST_LOGIN)
2135 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
2136 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2137 cFYI(1, ("UID = %d ", ses->Suid));
2138 /* response can have either 3 or 4 word count - Samba sends 3 */
2139 bcc_ptr = pByteArea(smb_buffer_response);
2140 if ((pSMBr->resp.hdr.WordCount == 3)
2141 || ((pSMBr->resp.hdr.WordCount == 4)
2142 && (blob_len < pSMBr->resp.ByteCount))) {
2143 if (pSMBr->resp.hdr.WordCount == 4)
2144 bcc_ptr += blob_len;
2145
2146 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2147 if ((long) (bcc_ptr) % 2) {
2148 remaining_words =
2149 (BCC(smb_buffer_response) - 1) /2;
2150 bcc_ptr++; /* Unicode strings must be word aligned */
2151 } else {
2152 remaining_words =
2153 BCC(smb_buffer_response) / 2;
2154 }
2155 len =
2156 UniStrnlen((wchar_t *) bcc_ptr,
2157 remaining_words - 1);
2158/* We look for obvious messed up bcc or strings in response so we do not go off
2159 the end since (at least) WIN2K and Windows XP have a major bug in not null
2160 terminating last Unicode string in response */
a424f8bf
SF
2161 if(ses->serverOS)
2162 kfree(ses->serverOS);
e915fc49 2163 ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
433dc24f
SF
2164 if(ses->serverOS == NULL)
2165 goto sesssetup_nomem;
1da177e4 2166 cifs_strfromUCS_le(ses->serverOS,
e89dc920 2167 (__le16 *)bcc_ptr, len,nls_codepage);
1da177e4
LT
2168 bcc_ptr += 2 * (len + 1);
2169 remaining_words -= len + 1;
2170 ses->serverOS[2 * len] = 0;
2171 ses->serverOS[1 + (2 * len)] = 0;
2172 if (remaining_words > 0) {
2173 len = UniStrnlen((wchar_t *)bcc_ptr,
2174 remaining_words-1);
a424f8bf
SF
2175 if(ses->serverNOS)
2176 kfree(ses->serverNOS);
e915fc49 2177 ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
433dc24f
SF
2178 if(ses->serverNOS == NULL)
2179 goto sesssetup_nomem;
1da177e4 2180 cifs_strfromUCS_le(ses->serverNOS,
e89dc920 2181 (__le16 *)bcc_ptr,len,nls_codepage);
1da177e4
LT
2182 bcc_ptr += 2 * (len + 1);
2183 ses->serverNOS[2 * len] = 0;
2184 ses->serverNOS[1 + (2 * len)] = 0;
2185 if(strncmp(ses->serverNOS,
2186 "NT LAN Manager 4",16) == 0) {
2187 cFYI(1,("NT4 server"));
2188 ses->flags |= CIFS_SES_NT4;
2189 }
2190 remaining_words -= len + 1;
2191 if (remaining_words > 0) {
433dc24f 2192 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1da177e4 2193 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
a424f8bf
SF
2194 if(ses->serverDomain)
2195 kfree(ses->serverDomain);
1da177e4 2196 ses->serverDomain =
e915fc49 2197 kzalloc(2*(len+1),GFP_KERNEL);
433dc24f
SF
2198 if(ses->serverDomain == NULL)
2199 goto sesssetup_nomem;
1da177e4 2200 cifs_strfromUCS_le(ses->serverDomain,
e89dc920 2201 (__le16 *)bcc_ptr,len,nls_codepage);
1da177e4
LT
2202 bcc_ptr += 2 * (len + 1);
2203 ses->serverDomain[2*len] = 0;
2204 ses->serverDomain[1+(2*len)] = 0;
2205 } /* else no more room so create dummy domain string */
a424f8bf
SF
2206 else {
2207 if(ses->serverDomain)
2208 kfree(ses->serverDomain);
433dc24f 2209 ses->serverDomain =
e915fc49 2210 kzalloc(2, GFP_KERNEL);
a424f8bf 2211 }
1da177e4 2212 } else { /* no room so create dummy domain and NOS string */
433dc24f
SF
2213 /* if these kcallocs fail not much we
2214 can do, but better to not fail the
2215 sesssetup itself */
a424f8bf
SF
2216 if(ses->serverDomain)
2217 kfree(ses->serverDomain);
1da177e4 2218 ses->serverDomain =
e915fc49 2219 kzalloc(2, GFP_KERNEL);
a424f8bf
SF
2220 if(ses->serverNOS)
2221 kfree(ses->serverNOS);
1da177e4 2222 ses->serverNOS =
e915fc49 2223 kzalloc(2, GFP_KERNEL);
1da177e4
LT
2224 }
2225 } else { /* ASCII */
2226 len = strnlen(bcc_ptr, 1024);
2227 if (((long) bcc_ptr + len) - (long)
2228 pByteArea(smb_buffer_response)
2229 <= BCC(smb_buffer_response)) {
a424f8bf
SF
2230 if(ses->serverOS)
2231 kfree(ses->serverOS);
e915fc49 2232 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
433dc24f
SF
2233 if(ses->serverOS == NULL)
2234 goto sesssetup_nomem;
1da177e4
LT
2235 strncpy(ses->serverOS,bcc_ptr, len);
2236
2237 bcc_ptr += len;
2238 bcc_ptr[0] = 0; /* null terminate the string */
2239 bcc_ptr++;
2240
2241 len = strnlen(bcc_ptr, 1024);
a424f8bf
SF
2242 if(ses->serverNOS)
2243 kfree(ses->serverNOS);
e915fc49 2244 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
433dc24f
SF
2245 if(ses->serverNOS == NULL)
2246 goto sesssetup_nomem;
1da177e4
LT
2247 strncpy(ses->serverNOS, bcc_ptr, len);
2248 bcc_ptr += len;
2249 bcc_ptr[0] = 0;
2250 bcc_ptr++;
2251
2252 len = strnlen(bcc_ptr, 1024);
a424f8bf
SF
2253 if(ses->serverDomain)
2254 kfree(ses->serverDomain);
e915fc49 2255 ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
433dc24f
SF
2256 if(ses->serverDomain == NULL)
2257 goto sesssetup_nomem;
1da177e4
LT
2258 strncpy(ses->serverDomain, bcc_ptr, len);
2259 bcc_ptr += len;
2260 bcc_ptr[0] = 0;
2261 bcc_ptr++;
2262 } else
2263 cFYI(1,
2264 ("Variable field of length %d extends beyond end of smb ",
2265 len));
2266 }
2267 } else {
2268 cERROR(1,
2269 (" Security Blob Length extends beyond end of SMB"));
2270 }
2271 } else {
2272 cERROR(1,
2273 (" Invalid Word count %d: ",
2274 smb_buffer_response->WordCount));
2275 rc = -EIO;
2276 }
433dc24f
SF
2277sesssetup_nomem: /* do not return an error on nomem for the info strings,
2278 since that could make reconnection harder, and
2279 reconnection might be needed to free memory */
1da177e4
LT
2280 if (smb_buffer)
2281 cifs_buf_release(smb_buffer);
2282
2283 return rc;
2284}
2285
2286static int
2287CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2288 char *SecurityBlob,int SecurityBlobLength,
2289 const struct nls_table *nls_codepage)
2290{
2291 struct smb_hdr *smb_buffer;
2292 struct smb_hdr *smb_buffer_response;
2293 SESSION_SETUP_ANDX *pSMB;
2294 SESSION_SETUP_ANDX *pSMBr;
2295 char *bcc_ptr;
2296 char *user;
2297 char *domain;
2298 int rc = 0;
2299 int remaining_words = 0;
2300 int bytes_returned = 0;
2301 int len;
2302 __u32 capabilities;
2303 __u16 count;
2304
2305 cFYI(1, ("In spnego sesssetup "));
2306 if(ses == NULL)
2307 return -EINVAL;
2308 user = ses->userName;
2309 domain = ses->domainName;
2310
2311 smb_buffer = cifs_buf_get();
2312 if (smb_buffer == NULL) {
2313 return -ENOMEM;
2314 }
2315 smb_buffer_response = smb_buffer;
2316 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2317
2318 /* send SMBsessionSetup here */
2319 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2320 NULL /* no tCon exists yet */ , 12 /* wct */ );
1982c344
SF
2321
2322 smb_buffer->Mid = GetNextMid(ses->server);
1da177e4
LT
2323 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2324 pSMB->req.AndXCommand = 0xFF;
184ed211
SF
2325 if(ses->server->maxBuf > 64*1024)
2326 ses->server->maxBuf = (64*1023);
1da177e4
LT
2327 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2328 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2329
2330 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2331 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2332
2333 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2334 CAP_EXTENDED_SECURITY;
2335 if (ses->capabilities & CAP_UNICODE) {
2336 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2337 capabilities |= CAP_UNICODE;
2338 }
2339 if (ses->capabilities & CAP_STATUS32) {
2340 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2341 capabilities |= CAP_STATUS32;
2342 }
2343 if (ses->capabilities & CAP_DFS) {
2344 smb_buffer->Flags2 |= SMBFLG2_DFS;
2345 capabilities |= CAP_DFS;
2346 }
2347 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2348
2349 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2350 bcc_ptr = pByteArea(smb_buffer);
2351 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2352 bcc_ptr += SecurityBlobLength;
2353
2354 if (ses->capabilities & CAP_UNICODE) {
2355 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2356 *bcc_ptr = 0;
2357 bcc_ptr++;
2358 }
2359 bytes_returned =
e89dc920 2360 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage);
1da177e4
LT
2361 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2362 bcc_ptr += 2; /* trailing null */
2363 if (domain == NULL)
2364 bytes_returned =
e89dc920 2365 cifs_strtoUCS((__le16 *) bcc_ptr,
1da177e4
LT
2366 "CIFS_LINUX_DOM", 32, nls_codepage);
2367 else
2368 bytes_returned =
e89dc920 2369 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
1da177e4
LT
2370 nls_codepage);
2371 bcc_ptr += 2 * bytes_returned;
2372 bcc_ptr += 2;
2373 bytes_returned =
e89dc920 2374 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
1da177e4
LT
2375 32, nls_codepage);
2376 bcc_ptr += 2 * bytes_returned;
2377 bytes_returned =
e89dc920 2378 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
1da177e4
LT
2379 nls_codepage);
2380 bcc_ptr += 2 * bytes_returned;
2381 bcc_ptr += 2;
2382 bytes_returned =
e89dc920 2383 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
1da177e4
LT
2384 64, nls_codepage);
2385 bcc_ptr += 2 * bytes_returned;
2386 bcc_ptr += 2;
2387 } else {
2388 strncpy(bcc_ptr, user, 200);
2389 bcc_ptr += strnlen(user, 200);
2390 *bcc_ptr = 0;
2391 bcc_ptr++;
2392 if (domain == NULL) {
2393 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2394 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2395 } else {
2396 strncpy(bcc_ptr, domain, 64);
2397 bcc_ptr += strnlen(domain, 64);
2398 *bcc_ptr = 0;
2399 bcc_ptr++;
2400 }
2401 strcpy(bcc_ptr, "Linux version ");
2402 bcc_ptr += strlen("Linux version ");
2403 strcpy(bcc_ptr, system_utsname.release);
2404 bcc_ptr += strlen(system_utsname.release) + 1;
2405 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2406 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2407 }
2408 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2409 smb_buffer->smb_buf_length += count;
2410 pSMB->req.ByteCount = cpu_to_le16(count);
2411
2412 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2413 &bytes_returned, 1);
2414 if (rc) {
2415/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2416 } else if ((smb_buffer_response->WordCount == 3)
2417 || (smb_buffer_response->WordCount == 4)) {
2418 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2419 __u16 blob_len =
2420 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2421 if (action & GUEST_LOGIN)
2422 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2423 if (ses) {
2424 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2425 cFYI(1, ("UID = %d ", ses->Suid));
2426 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2427
2428 /* BB Fix below to make endian neutral !! */
2429
2430 if ((pSMBr->resp.hdr.WordCount == 3)
2431 || ((pSMBr->resp.hdr.WordCount == 4)
2432 && (blob_len <
2433 pSMBr->resp.ByteCount))) {
2434 if (pSMBr->resp.hdr.WordCount == 4) {
2435 bcc_ptr +=
2436 blob_len;
2437 cFYI(1,
2438 ("Security Blob Length %d ",
2439 blob_len));
2440 }
2441
2442 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2443 if ((long) (bcc_ptr) % 2) {
2444 remaining_words =
2445 (BCC(smb_buffer_response)
2446 - 1) / 2;
2447 bcc_ptr++; /* Unicode strings must be word aligned */
2448 } else {
2449 remaining_words =
2450 BCC
2451 (smb_buffer_response) / 2;
2452 }
2453 len =
2454 UniStrnlen((wchar_t *) bcc_ptr,
2455 remaining_words - 1);
2456/* We look for obvious messed up bcc or strings in response so we do not go off
2457 the end since (at least) WIN2K and Windows XP have a major bug in not null
2458 terminating last Unicode string in response */
a424f8bf
SF
2459 if(ses->serverOS)
2460 kfree(ses->serverOS);
1da177e4 2461 ses->serverOS =
e915fc49 2462 kzalloc(2 * (len + 1), GFP_KERNEL);
1da177e4 2463 cifs_strfromUCS_le(ses->serverOS,
e89dc920 2464 (__le16 *)
1da177e4
LT
2465 bcc_ptr, len,
2466 nls_codepage);
2467 bcc_ptr += 2 * (len + 1);
2468 remaining_words -= len + 1;
2469 ses->serverOS[2 * len] = 0;
2470 ses->serverOS[1 + (2 * len)] = 0;
2471 if (remaining_words > 0) {
2472 len = UniStrnlen((wchar_t *)bcc_ptr,
2473 remaining_words
2474 - 1);
a424f8bf
SF
2475 if(ses->serverNOS)
2476 kfree(ses->serverNOS);
1da177e4 2477 ses->serverNOS =
e915fc49 2478 kzalloc(2 * (len + 1),
1da177e4
LT
2479 GFP_KERNEL);
2480 cifs_strfromUCS_le(ses->serverNOS,
e89dc920 2481 (__le16 *)bcc_ptr,
1da177e4
LT
2482 len,
2483 nls_codepage);
2484 bcc_ptr += 2 * (len + 1);
2485 ses->serverNOS[2 * len] = 0;
2486 ses->serverNOS[1 + (2 * len)] = 0;
2487 remaining_words -= len + 1;
2488 if (remaining_words > 0) {
2489 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
a424f8bf
SF
2490 /* last string not null terminated (e.g.Windows XP/2000) */
2491 if(ses->serverDomain)
2492 kfree(ses->serverDomain);
e915fc49 2493 ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
1da177e4 2494 cifs_strfromUCS_le(ses->serverDomain,
e89dc920
SF
2495 (__le16 *)bcc_ptr,
2496 len, nls_codepage);
1da177e4
LT
2497 bcc_ptr += 2*(len+1);
2498 ses->serverDomain[2*len] = 0;
2499 ses->serverDomain[1+(2*len)] = 0;
2500 } /* else no more room so create dummy domain string */
a424f8bf
SF
2501 else {
2502 if(ses->serverDomain)
08775834 2503 kfree(ses->serverDomain);
1da177e4 2504 ses->serverDomain =
e915fc49 2505 kzalloc(2,GFP_KERNEL);
a424f8bf
SF
2506 }
2507 } else {/* no room use dummy domain&NOS */
2508 if(ses->serverDomain)
2509 kfree(ses->serverDomain);
e915fc49 2510 ses->serverDomain = kzalloc(2, GFP_KERNEL);
a424f8bf
SF
2511 if(ses->serverNOS)
2512 kfree(ses->serverNOS);
e915fc49 2513 ses->serverNOS = kzalloc(2, GFP_KERNEL);
1da177e4
LT
2514 }
2515 } else { /* ASCII */
2516
2517 len = strnlen(bcc_ptr, 1024);
2518 if (((long) bcc_ptr + len) - (long)
2519 pByteArea(smb_buffer_response)
2520 <= BCC(smb_buffer_response)) {
a424f8bf
SF
2521 if(ses->serverOS)
2522 kfree(ses->serverOS);
e915fc49 2523 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
1da177e4
LT
2524 strncpy(ses->serverOS, bcc_ptr, len);
2525
2526 bcc_ptr += len;
2527 bcc_ptr[0] = 0; /* null terminate the string */
2528 bcc_ptr++;
2529
2530 len = strnlen(bcc_ptr, 1024);
a424f8bf
SF
2531 if(ses->serverNOS)
2532 kfree(ses->serverNOS);
e915fc49 2533 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
1da177e4
LT
2534 strncpy(ses->serverNOS, bcc_ptr, len);
2535 bcc_ptr += len;
2536 bcc_ptr[0] = 0;
2537 bcc_ptr++;
2538
2539 len = strnlen(bcc_ptr, 1024);
a424f8bf 2540 if(ses->serverDomain)
08775834 2541 kfree(ses->serverDomain);
e915fc49 2542 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
1da177e4
LT
2543 strncpy(ses->serverDomain, bcc_ptr, len);
2544 bcc_ptr += len;
2545 bcc_ptr[0] = 0;
2546 bcc_ptr++;
2547 } else
2548 cFYI(1,
2549 ("Variable field of length %d extends beyond end of smb ",
2550 len));
2551 }
2552 } else {
2553 cERROR(1,
2554 (" Security Blob Length extends beyond end of SMB"));
2555 }
2556 } else {
2557 cERROR(1, ("No session structure passed in."));
2558 }
2559 } else {
2560 cERROR(1,
2561 (" Invalid Word count %d: ",
2562 smb_buffer_response->WordCount));
2563 rc = -EIO;
2564 }
2565
2566 if (smb_buffer)
2567 cifs_buf_release(smb_buffer);
2568
2569 return rc;
2570}
2571
2572static int
2573CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2574 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2575 const struct nls_table *nls_codepage)
2576{
2577 struct smb_hdr *smb_buffer;
2578 struct smb_hdr *smb_buffer_response;
2579 SESSION_SETUP_ANDX *pSMB;
2580 SESSION_SETUP_ANDX *pSMBr;
2581 char *bcc_ptr;
2582 char *domain;
2583 int rc = 0;
2584 int remaining_words = 0;
2585 int bytes_returned = 0;
2586 int len;
2587 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2588 PNEGOTIATE_MESSAGE SecurityBlob;
2589 PCHALLENGE_MESSAGE SecurityBlob2;
2590 __u32 negotiate_flags, capabilities;
2591 __u16 count;
2592
12b3b8ff 2593 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
1da177e4
LT
2594 if(ses == NULL)
2595 return -EINVAL;
2596 domain = ses->domainName;
2597 *pNTLMv2_flag = FALSE;
2598 smb_buffer = cifs_buf_get();
2599 if (smb_buffer == NULL) {
2600 return -ENOMEM;
2601 }
2602 smb_buffer_response = smb_buffer;
2603 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2604 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2605
2606 /* send SMBsessionSetup here */
2607 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2608 NULL /* no tCon exists yet */ , 12 /* wct */ );
1982c344
SF
2609
2610 smb_buffer->Mid = GetNextMid(ses->server);
1da177e4
LT
2611 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2612 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2613
2614 pSMB->req.AndXCommand = 0xFF;
2615 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2616 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2617
2618 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2619 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2620
2621 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2622 CAP_EXTENDED_SECURITY;
2623 if (ses->capabilities & CAP_UNICODE) {
2624 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2625 capabilities |= CAP_UNICODE;
2626 }
2627 if (ses->capabilities & CAP_STATUS32) {
2628 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2629 capabilities |= CAP_STATUS32;
2630 }
2631 if (ses->capabilities & CAP_DFS) {
2632 smb_buffer->Flags2 |= SMBFLG2_DFS;
2633 capabilities |= CAP_DFS;
2634 }
2635 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2636
2637 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2638 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2639 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2640 SecurityBlob->MessageType = NtLmNegotiate;
2641 negotiate_flags =
2642 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
12b3b8ff
SF
2643 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2644 NTLMSSP_NEGOTIATE_56 |
1da177e4
LT
2645 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2646 if(sign_CIFS_PDUs)
2647 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
3979877e
SF
2648/* if(ntlmv2_support)
2649 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
1da177e4
LT
2650 /* setup pointers to domain name and workstation name */
2651 bcc_ptr += SecurityBlobLength;
2652
2653 SecurityBlob->WorkstationName.Buffer = 0;
2654 SecurityBlob->WorkstationName.Length = 0;
2655 SecurityBlob->WorkstationName.MaximumLength = 0;
2656
12b3b8ff
SF
2657 /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2658 along with username on auth request (ie the response to challenge) */
2659 SecurityBlob->DomainName.Buffer = 0;
2660 SecurityBlob->DomainName.Length = 0;
2661 SecurityBlob->DomainName.MaximumLength = 0;
1da177e4
LT
2662 if (ses->capabilities & CAP_UNICODE) {
2663 if ((long) bcc_ptr % 2) {
2664 *bcc_ptr = 0;
2665 bcc_ptr++;
2666 }
2667
2668 bytes_returned =
e89dc920 2669 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
1da177e4
LT
2670 32, nls_codepage);
2671 bcc_ptr += 2 * bytes_returned;
2672 bytes_returned =
e89dc920 2673 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
1da177e4
LT
2674 nls_codepage);
2675 bcc_ptr += 2 * bytes_returned;
2676 bcc_ptr += 2; /* null terminate Linux version */
2677 bytes_returned =
e89dc920 2678 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
1da177e4
LT
2679 64, nls_codepage);
2680 bcc_ptr += 2 * bytes_returned;
2681 *(bcc_ptr + 1) = 0;
2682 *(bcc_ptr + 2) = 0;
2683 bcc_ptr += 2; /* null terminate network opsys string */
2684 *(bcc_ptr + 1) = 0;
2685 *(bcc_ptr + 2) = 0;
2686 bcc_ptr += 2; /* null domain */
2687 } else { /* ASCII */
2688 strcpy(bcc_ptr, "Linux version ");
2689 bcc_ptr += strlen("Linux version ");
2690 strcpy(bcc_ptr, system_utsname.release);
2691 bcc_ptr += strlen(system_utsname.release) + 1;
2692 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2693 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2694 bcc_ptr++; /* empty domain field */
2695 *bcc_ptr = 0;
2696 }
2697 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2698 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2699 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2700 smb_buffer->smb_buf_length += count;
2701 pSMB->req.ByteCount = cpu_to_le16(count);
2702
2703 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2704 &bytes_returned, 1);
2705
2706 if (smb_buffer_response->Status.CifsError ==
2707 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2708 rc = 0;
2709
2710 if (rc) {
2711/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2712 } else if ((smb_buffer_response->WordCount == 3)
2713 || (smb_buffer_response->WordCount == 4)) {
2714 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2715 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2716
2717 if (action & GUEST_LOGIN)
2718 cFYI(1, (" Guest login"));
2719 /* Do we want to set anything in SesInfo struct when guest login? */
2720
2721 bcc_ptr = pByteArea(smb_buffer_response);
2722 /* response can have either 3 or 4 word count - Samba sends 3 */
2723
2724 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2725 if (SecurityBlob2->MessageType != NtLmChallenge) {
2726 cFYI(1,
2727 ("Unexpected NTLMSSP message type received %d",
2728 SecurityBlob2->MessageType));
2729 } else if (ses) {
2730 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
12b3b8ff 2731 cFYI(1, ("UID = %d", ses->Suid));
1da177e4
LT
2732 if ((pSMBr->resp.hdr.WordCount == 3)
2733 || ((pSMBr->resp.hdr.WordCount == 4)
2734 && (blob_len <
2735 pSMBr->resp.ByteCount))) {
2736
2737 if (pSMBr->resp.hdr.WordCount == 4) {
2738 bcc_ptr += blob_len;
12b3b8ff 2739 cFYI(1, ("Security Blob Length %d",
1da177e4
LT
2740 blob_len));
2741 }
2742
12b3b8ff 2743 cFYI(1, ("NTLMSSP Challenge rcvd"));
1da177e4
LT
2744
2745 memcpy(ses->server->cryptKey,
2746 SecurityBlob2->Challenge,
2747 CIFS_CRYPTO_KEY_SIZE);
12b3b8ff
SF
2748 if(SecurityBlob2->NegotiateFlags &
2749 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
1da177e4
LT
2750 *pNTLMv2_flag = TRUE;
2751
2752 if((SecurityBlob2->NegotiateFlags &
2753 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2754 || (sign_CIFS_PDUs > 1))
2755 ses->server->secMode |=
2756 SECMODE_SIGN_REQUIRED;
2757 if ((SecurityBlob2->NegotiateFlags &
2758 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2759 ses->server->secMode |=
2760 SECMODE_SIGN_ENABLED;
2761
2762 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2763 if ((long) (bcc_ptr) % 2) {
2764 remaining_words =
2765 (BCC(smb_buffer_response)
2766 - 1) / 2;
2767 bcc_ptr++; /* Unicode strings must be word aligned */
2768 } else {
2769 remaining_words =
2770 BCC
2771 (smb_buffer_response) / 2;
2772 }
2773 len =
2774 UniStrnlen((wchar_t *) bcc_ptr,
2775 remaining_words - 1);
2776/* We look for obvious messed up bcc or strings in response so we do not go off
2777 the end since (at least) WIN2K and Windows XP have a major bug in not null
2778 terminating last Unicode string in response */
a424f8bf
SF
2779 if(ses->serverOS)
2780 kfree(ses->serverOS);
1da177e4 2781 ses->serverOS =
e915fc49 2782 kzalloc(2 * (len + 1), GFP_KERNEL);
1da177e4 2783 cifs_strfromUCS_le(ses->serverOS,
e89dc920 2784 (__le16 *)
1da177e4
LT
2785 bcc_ptr, len,
2786 nls_codepage);
2787 bcc_ptr += 2 * (len + 1);
2788 remaining_words -= len + 1;
2789 ses->serverOS[2 * len] = 0;
2790 ses->serverOS[1 + (2 * len)] = 0;
2791 if (remaining_words > 0) {
2792 len = UniStrnlen((wchar_t *)
2793 bcc_ptr,
2794 remaining_words
2795 - 1);
a424f8bf
SF
2796 if(ses->serverNOS)
2797 kfree(ses->serverNOS);
1da177e4 2798 ses->serverNOS =
e915fc49 2799 kzalloc(2 * (len + 1),
1da177e4
LT
2800 GFP_KERNEL);
2801 cifs_strfromUCS_le(ses->
2802 serverNOS,
e89dc920 2803 (__le16 *)
1da177e4
LT
2804 bcc_ptr,
2805 len,
2806 nls_codepage);
2807 bcc_ptr += 2 * (len + 1);
2808 ses->serverNOS[2 * len] = 0;
2809 ses->serverNOS[1 +
2810 (2 * len)] = 0;
2811 remaining_words -= len + 1;
2812 if (remaining_words > 0) {
2813 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2814 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
a424f8bf
SF
2815 if(ses->serverDomain)
2816 kfree(ses->serverDomain);
1da177e4 2817 ses->serverDomain =
e915fc49 2818 kzalloc(2 *
1da177e4
LT
2819 (len +
2820 1),
2821 GFP_KERNEL);
2822 cifs_strfromUCS_le
e89dc920
SF
2823 (ses->serverDomain,
2824 (__le16 *)bcc_ptr,
2825 len, nls_codepage);
1da177e4
LT
2826 bcc_ptr +=
2827 2 * (len + 1);
e89dc920 2828 ses->serverDomain[2*len]
1da177e4 2829 = 0;
e89dc920
SF
2830 ses->serverDomain
2831 [1 + (2 * len)]
1da177e4
LT
2832 = 0;
2833 } /* else no more room so create dummy domain string */
a424f8bf
SF
2834 else {
2835 if(ses->serverDomain)
2836 kfree(ses->serverDomain);
1da177e4 2837 ses->serverDomain =
e915fc49 2838 kzalloc(2,
1da177e4 2839 GFP_KERNEL);
a424f8bf 2840 }
1da177e4 2841 } else { /* no room so create dummy domain and NOS string */
a424f8bf
SF
2842 if(ses->serverDomain);
2843 kfree(ses->serverDomain);
1da177e4 2844 ses->serverDomain =
e915fc49 2845 kzalloc(2, GFP_KERNEL);
a424f8bf
SF
2846 if(ses->serverNOS)
2847 kfree(ses->serverNOS);
1da177e4 2848 ses->serverNOS =
e915fc49 2849 kzalloc(2, GFP_KERNEL);
1da177e4
LT
2850 }
2851 } else { /* ASCII */
2852 len = strnlen(bcc_ptr, 1024);
2853 if (((long) bcc_ptr + len) - (long)
2854 pByteArea(smb_buffer_response)
2855 <= BCC(smb_buffer_response)) {
a424f8bf
SF
2856 if(ses->serverOS)
2857 kfree(ses->serverOS);
1da177e4 2858 ses->serverOS =
e915fc49 2859 kzalloc(len + 1,
1da177e4
LT
2860 GFP_KERNEL);
2861 strncpy(ses->serverOS,
2862 bcc_ptr, len);
2863
2864 bcc_ptr += len;
2865 bcc_ptr[0] = 0; /* null terminate string */
2866 bcc_ptr++;
2867
2868 len = strnlen(bcc_ptr, 1024);
a424f8bf
SF
2869 if(ses->serverNOS)
2870 kfree(ses->serverNOS);
1da177e4 2871 ses->serverNOS =
e915fc49 2872 kzalloc(len + 1,
1da177e4
LT
2873 GFP_KERNEL);
2874 strncpy(ses->serverNOS, bcc_ptr, len);
2875 bcc_ptr += len;
2876 bcc_ptr[0] = 0;
2877 bcc_ptr++;
2878
2879 len = strnlen(bcc_ptr, 1024);
a424f8bf
SF
2880 if(ses->serverDomain)
2881 kfree(ses->serverDomain);
1da177e4 2882 ses->serverDomain =
e915fc49 2883 kzalloc(len + 1,
1da177e4
LT
2884 GFP_KERNEL);
2885 strncpy(ses->serverDomain, bcc_ptr, len);
2886 bcc_ptr += len;
2887 bcc_ptr[0] = 0;
2888 bcc_ptr++;
2889 } else
2890 cFYI(1,
12b3b8ff 2891 ("Variable field of length %d extends beyond end of smb",
1da177e4
LT
2892 len));
2893 }
2894 } else {
2895 cERROR(1,
2896 (" Security Blob Length extends beyond end of SMB"));
2897 }
2898 } else {
2899 cERROR(1, ("No session structure passed in."));
2900 }
2901 } else {
2902 cERROR(1,
5815449d 2903 (" Invalid Word count %d:",
1da177e4
LT
2904 smb_buffer_response->WordCount));
2905 rc = -EIO;
2906 }
2907
2908 if (smb_buffer)
2909 cifs_buf_release(smb_buffer);
2910
2911 return rc;
2912}
2913static int
2914CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2915 char *ntlm_session_key, int ntlmv2_flag,
2916 const struct nls_table *nls_codepage)
2917{
2918 struct smb_hdr *smb_buffer;
2919 struct smb_hdr *smb_buffer_response;
2920 SESSION_SETUP_ANDX *pSMB;
2921 SESSION_SETUP_ANDX *pSMBr;
2922 char *bcc_ptr;
2923 char *user;
2924 char *domain;
2925 int rc = 0;
2926 int remaining_words = 0;
2927 int bytes_returned = 0;
2928 int len;
2929 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2930 PAUTHENTICATE_MESSAGE SecurityBlob;
2931 __u32 negotiate_flags, capabilities;
2932 __u16 count;
2933
2934 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2935 if(ses == NULL)
2936 return -EINVAL;
2937 user = ses->userName;
2938 domain = ses->domainName;
2939 smb_buffer = cifs_buf_get();
2940 if (smb_buffer == NULL) {
2941 return -ENOMEM;
2942 }
2943 smb_buffer_response = smb_buffer;
2944 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2945 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2946
2947 /* send SMBsessionSetup here */
2948 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2949 NULL /* no tCon exists yet */ , 12 /* wct */ );
1982c344
SF
2950
2951 smb_buffer->Mid = GetNextMid(ses->server);
1da177e4
LT
2952 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2953 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2954 pSMB->req.AndXCommand = 0xFF;
2955 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2956 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2957
2958 pSMB->req.hdr.Uid = ses->Suid;
2959
2960 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2961 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2962
2963 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2964 CAP_EXTENDED_SECURITY;
2965 if (ses->capabilities & CAP_UNICODE) {
2966 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2967 capabilities |= CAP_UNICODE;
2968 }
2969 if (ses->capabilities & CAP_STATUS32) {
2970 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2971 capabilities |= CAP_STATUS32;
2972 }
2973 if (ses->capabilities & CAP_DFS) {
2974 smb_buffer->Flags2 |= SMBFLG2_DFS;
2975 capabilities |= CAP_DFS;
2976 }
2977 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2978
2979 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2980 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2981 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2982 SecurityBlob->MessageType = NtLmAuthenticate;
2983 bcc_ptr += SecurityBlobLength;
2984 negotiate_flags =
2985 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2986 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2987 0x80000000 | NTLMSSP_NEGOTIATE_128;
2988 if(sign_CIFS_PDUs)
2989 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2990 if(ntlmv2_flag)
2991 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2992
2993/* setup pointers to domain name and workstation name */
2994
2995 SecurityBlob->WorkstationName.Buffer = 0;
2996 SecurityBlob->WorkstationName.Length = 0;
2997 SecurityBlob->WorkstationName.MaximumLength = 0;
2998 SecurityBlob->SessionKey.Length = 0;
2999 SecurityBlob->SessionKey.MaximumLength = 0;
3000 SecurityBlob->SessionKey.Buffer = 0;
3001
3002 SecurityBlob->LmChallengeResponse.Length = 0;
3003 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
3004 SecurityBlob->LmChallengeResponse.Buffer = 0;
3005
3006 SecurityBlob->NtChallengeResponse.Length =
3007 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
3008 SecurityBlob->NtChallengeResponse.MaximumLength =
3009 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
3010 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
3011 SecurityBlob->NtChallengeResponse.Buffer =
3012 cpu_to_le32(SecurityBlobLength);
3013 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
3014 bcc_ptr += CIFS_SESSION_KEY_SIZE;
3015
3016 if (ses->capabilities & CAP_UNICODE) {
3017 if (domain == NULL) {
3018 SecurityBlob->DomainName.Buffer = 0;
3019 SecurityBlob->DomainName.Length = 0;
3020 SecurityBlob->DomainName.MaximumLength = 0;
3021 } else {
3022 __u16 len =
e89dc920 3023 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
1da177e4
LT
3024 nls_codepage);
3025 len *= 2;
3026 SecurityBlob->DomainName.MaximumLength =
3027 cpu_to_le16(len);
3028 SecurityBlob->DomainName.Buffer =
3029 cpu_to_le32(SecurityBlobLength);
3030 bcc_ptr += len;
3031 SecurityBlobLength += len;
3032 SecurityBlob->DomainName.Length =
3033 cpu_to_le16(len);
3034 }
3035 if (user == NULL) {
3036 SecurityBlob->UserName.Buffer = 0;
3037 SecurityBlob->UserName.Length = 0;
3038 SecurityBlob->UserName.MaximumLength = 0;
3039 } else {
3040 __u16 len =
e89dc920 3041 cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
1da177e4
LT
3042 nls_codepage);
3043 len *= 2;
3044 SecurityBlob->UserName.MaximumLength =
3045 cpu_to_le16(len);
3046 SecurityBlob->UserName.Buffer =
3047 cpu_to_le32(SecurityBlobLength);
3048 bcc_ptr += len;
3049 SecurityBlobLength += len;
3050 SecurityBlob->UserName.Length =
3051 cpu_to_le16(len);
3052 }
3053
e89dc920 3054 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
1da177e4
LT
3055 SecurityBlob->WorkstationName.Length *= 2;
3056 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
3057 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
3058 bcc_ptr += SecurityBlob->WorkstationName.Length;
3059 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
3060 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
3061
3062 if ((long) bcc_ptr % 2) {
3063 *bcc_ptr = 0;
3064 bcc_ptr++;
3065 }
3066 bytes_returned =
e89dc920 3067 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
1da177e4
LT
3068 32, nls_codepage);
3069 bcc_ptr += 2 * bytes_returned;
3070 bytes_returned =
e89dc920 3071 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
1da177e4
LT
3072 nls_codepage);
3073 bcc_ptr += 2 * bytes_returned;
3074 bcc_ptr += 2; /* null term version string */
3075 bytes_returned =
e89dc920 3076 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
1da177e4
LT
3077 64, nls_codepage);
3078 bcc_ptr += 2 * bytes_returned;
3079 *(bcc_ptr + 1) = 0;
3080 *(bcc_ptr + 2) = 0;
3081 bcc_ptr += 2; /* null terminate network opsys string */
3082 *(bcc_ptr + 1) = 0;
3083 *(bcc_ptr + 2) = 0;
3084 bcc_ptr += 2; /* null domain */
3085 } else { /* ASCII */
3086 if (domain == NULL) {
3087 SecurityBlob->DomainName.Buffer = 0;
3088 SecurityBlob->DomainName.Length = 0;
3089 SecurityBlob->DomainName.MaximumLength = 0;
3090 } else {
3091 __u16 len;
3092 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3093 strncpy(bcc_ptr, domain, 63);
3094 len = strnlen(domain, 64);
3095 SecurityBlob->DomainName.MaximumLength =
3096 cpu_to_le16(len);
3097 SecurityBlob->DomainName.Buffer =
3098 cpu_to_le32(SecurityBlobLength);
3099 bcc_ptr += len;
3100 SecurityBlobLength += len;
3101 SecurityBlob->DomainName.Length = cpu_to_le16(len);
3102 }
3103 if (user == NULL) {
3104 SecurityBlob->UserName.Buffer = 0;
3105 SecurityBlob->UserName.Length = 0;
3106 SecurityBlob->UserName.MaximumLength = 0;
3107 } else {
3108 __u16 len;
3109 strncpy(bcc_ptr, user, 63);
3110 len = strnlen(user, 64);
3111 SecurityBlob->UserName.MaximumLength =
3112 cpu_to_le16(len);
3113 SecurityBlob->UserName.Buffer =
3114 cpu_to_le32(SecurityBlobLength);
3115 bcc_ptr += len;
3116 SecurityBlobLength += len;
3117 SecurityBlob->UserName.Length = cpu_to_le16(len);
3118 }
3119 /* BB fill in our workstation name if known BB */
3120
3121 strcpy(bcc_ptr, "Linux version ");
3122 bcc_ptr += strlen("Linux version ");
3123 strcpy(bcc_ptr, system_utsname.release);
3124 bcc_ptr += strlen(system_utsname.release) + 1;
3125 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3126 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3127 bcc_ptr++; /* null domain */
3128 *bcc_ptr = 0;
3129 }
3130 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3131 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3132 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3133 smb_buffer->smb_buf_length += count;
3134 pSMB->req.ByteCount = cpu_to_le16(count);
3135
3136 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3137 &bytes_returned, 1);
3138 if (rc) {
3139/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
3140 } else if ((smb_buffer_response->WordCount == 3)
3141 || (smb_buffer_response->WordCount == 4)) {
3142 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3143 __u16 blob_len =
3144 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3145 if (action & GUEST_LOGIN)
3146 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
3147/* if(SecurityBlob2->MessageType != NtLm??){
3148 cFYI("Unexpected message type on auth response is %d "));
3149 } */
3150 if (ses) {
3151 cFYI(1,
3152 ("Does UID on challenge %d match auth response UID %d ",
3153 ses->Suid, smb_buffer_response->Uid));
3154 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
3155 bcc_ptr = pByteArea(smb_buffer_response);
3156 /* response can have either 3 or 4 word count - Samba sends 3 */
3157 if ((pSMBr->resp.hdr.WordCount == 3)
3158 || ((pSMBr->resp.hdr.WordCount == 4)
3159 && (blob_len <
3160 pSMBr->resp.ByteCount))) {
3161 if (pSMBr->resp.hdr.WordCount == 4) {
3162 bcc_ptr +=
3163 blob_len;
3164 cFYI(1,
3165 ("Security Blob Length %d ",
3166 blob_len));
3167 }
3168
3169 cFYI(1,
3170 ("NTLMSSP response to Authenticate "));
3171
3172 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3173 if ((long) (bcc_ptr) % 2) {
3174 remaining_words =
3175 (BCC(smb_buffer_response)
3176 - 1) / 2;
3177 bcc_ptr++; /* Unicode strings must be word aligned */
3178 } else {
3179 remaining_words = BCC(smb_buffer_response) / 2;
3180 }
3181 len =
3182 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
3183/* We look for obvious messed up bcc or strings in response so we do not go off
3184 the end since (at least) WIN2K and Windows XP have a major bug in not null
3185 terminating last Unicode string in response */
a424f8bf 3186 if(ses->serverOS)
08775834 3187 kfree(ses->serverOS);
1da177e4 3188 ses->serverOS =
e915fc49 3189 kzalloc(2 * (len + 1), GFP_KERNEL);
1da177e4 3190 cifs_strfromUCS_le(ses->serverOS,
e89dc920 3191 (__le16 *)
1da177e4
LT
3192 bcc_ptr, len,
3193 nls_codepage);
3194 bcc_ptr += 2 * (len + 1);
3195 remaining_words -= len + 1;
3196 ses->serverOS[2 * len] = 0;
3197 ses->serverOS[1 + (2 * len)] = 0;
3198 if (remaining_words > 0) {
3199 len = UniStrnlen((wchar_t *)
3200 bcc_ptr,
3201 remaining_words
3202 - 1);
a424f8bf
SF
3203 if(ses->serverNOS)
3204 kfree(ses->serverNOS);
1da177e4 3205 ses->serverNOS =
e915fc49 3206 kzalloc(2 * (len + 1),
1da177e4
LT
3207 GFP_KERNEL);
3208 cifs_strfromUCS_le(ses->
3209 serverNOS,
e89dc920 3210 (__le16 *)
1da177e4
LT
3211 bcc_ptr,
3212 len,
3213 nls_codepage);
3214 bcc_ptr += 2 * (len + 1);
3215 ses->serverNOS[2 * len] = 0;
3216 ses->serverNOS[1+(2*len)] = 0;
3217 remaining_words -= len + 1;
3218 if (remaining_words > 0) {
3219 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3220 /* last string not always null terminated (e.g. for Windows XP & 2000) */
a424f8bf
SF
3221 if(ses->serverDomain)
3222 kfree(ses->serverDomain);
1da177e4 3223 ses->serverDomain =
e915fc49 3224 kzalloc(2 *
1da177e4
LT
3225 (len +
3226 1),
3227 GFP_KERNEL);
3228 cifs_strfromUCS_le
3229 (ses->
3230 serverDomain,
e89dc920 3231 (__le16 *)
1da177e4
LT
3232 bcc_ptr, len,
3233 nls_codepage);
3234 bcc_ptr +=
3235 2 * (len + 1);
3236 ses->
3237 serverDomain[2
3238 * len]
3239 = 0;
3240 ses->
3241 serverDomain[1
3242 +
3243 (2
3244 *
3245 len)]
3246 = 0;
3247 } /* else no more room so create dummy domain string */
a424f8bf
SF
3248 else {
3249 if(ses->serverDomain)
3250 kfree(ses->serverDomain);
e915fc49 3251 ses->serverDomain = kzalloc(2,GFP_KERNEL);
a424f8bf 3252 }
1da177e4 3253 } else { /* no room so create dummy domain and NOS string */
a424f8bf
SF
3254 if(ses->serverDomain)
3255 kfree(ses->serverDomain);
e915fc49 3256 ses->serverDomain = kzalloc(2, GFP_KERNEL);
a424f8bf
SF
3257 if(ses->serverNOS)
3258 kfree(ses->serverNOS);
e915fc49 3259 ses->serverNOS = kzalloc(2, GFP_KERNEL);
1da177e4
LT
3260 }
3261 } else { /* ASCII */
3262 len = strnlen(bcc_ptr, 1024);
3263 if (((long) bcc_ptr + len) -
3264 (long) pByteArea(smb_buffer_response)
3265 <= BCC(smb_buffer_response)) {
a424f8bf
SF
3266 if(ses->serverOS)
3267 kfree(ses->serverOS);
e915fc49 3268 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
1da177e4
LT
3269 strncpy(ses->serverOS,bcc_ptr, len);
3270
3271 bcc_ptr += len;
3272 bcc_ptr[0] = 0; /* null terminate the string */
3273 bcc_ptr++;
3274
3275 len = strnlen(bcc_ptr, 1024);
a424f8bf
SF
3276 if(ses->serverNOS)
3277 kfree(ses->serverNOS);
e915fc49 3278 ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
1da177e4
LT
3279 strncpy(ses->serverNOS, bcc_ptr, len);
3280 bcc_ptr += len;
3281 bcc_ptr[0] = 0;
3282 bcc_ptr++;
3283
3284 len = strnlen(bcc_ptr, 1024);
a424f8bf
SF
3285 if(ses->serverDomain)
3286 kfree(ses->serverDomain);
e915fc49 3287 ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
1da177e4
LT
3288 strncpy(ses->serverDomain, bcc_ptr, len);
3289 bcc_ptr += len;
3290 bcc_ptr[0] = 0;
3291 bcc_ptr++;
3292 } else
3293 cFYI(1,
3294 ("Variable field of length %d extends beyond end of smb ",
3295 len));
3296 }
3297 } else {
3298 cERROR(1,
3299 (" Security Blob Length extends beyond end of SMB"));
3300 }
3301 } else {
3302 cERROR(1, ("No session structure passed in."));
3303 }
3304 } else {
3305 cERROR(1,
3306 (" Invalid Word count %d: ",
3307 smb_buffer_response->WordCount));
3308 rc = -EIO;
3309 }
3310
3311 if (smb_buffer)
3312 cifs_buf_release(smb_buffer);
3313
3314 return rc;
3315}
3316
3317int
3318CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3319 const char *tree, struct cifsTconInfo *tcon,
3320 const struct nls_table *nls_codepage)
3321{
3322 struct smb_hdr *smb_buffer;
3323 struct smb_hdr *smb_buffer_response;
3324 TCONX_REQ *pSMB;
3325 TCONX_RSP *pSMBr;
3326 unsigned char *bcc_ptr;
3327 int rc = 0;
3328 int length;
3329 __u16 count;
3330
3331 if (ses == NULL)
3332 return -EIO;
3333
3334 smb_buffer = cifs_buf_get();
3335 if (smb_buffer == NULL) {
3336 return -ENOMEM;
3337 }
3338 smb_buffer_response = smb_buffer;
3339
3340 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3341 NULL /*no tid */ , 4 /*wct */ );
1982c344
SF
3342
3343 smb_buffer->Mid = GetNextMid(ses->server);
1da177e4
LT
3344 smb_buffer->Uid = ses->Suid;
3345 pSMB = (TCONX_REQ *) smb_buffer;
3346 pSMBr = (TCONX_RSP *) smb_buffer_response;
3347
3348 pSMB->AndXCommand = 0xFF;
3349 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
1da177e4 3350 bcc_ptr = &pSMB->Password[0];
eeac8047
SF
3351 if((ses->server->secMode) & SECMODE_USER) {
3352 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3353 bcc_ptr++; /* skip password */
3354 } else {
3355 pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE);
3356 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3357 specified as required (when that support is added to
3358 the vfs in the future) as only NTLM or the much
3359 weaker LANMAN (which we do not send) is accepted
3360 by Samba (not sure whether other servers allow
3361 NTLMv2 password here) */
3362 SMBNTencrypt(ses->password,
3363 ses->server->cryptKey,
3364 bcc_ptr);
3365
3366 bcc_ptr += CIFS_SESSION_KEY_SIZE;
3367 *bcc_ptr = 0;
3368 bcc_ptr++; /* align */
3369 }
1da177e4 3370
a878fb22
SF
3371 if(ses->server->secMode &
3372 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1da177e4
LT
3373 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3374
3375 if (ses->capabilities & CAP_STATUS32) {
3376 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3377 }
3378 if (ses->capabilities & CAP_DFS) {
3379 smb_buffer->Flags2 |= SMBFLG2_DFS;
3380 }
3381 if (ses->capabilities & CAP_UNICODE) {
3382 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3383 length =
a878fb22
SF
3384 cifs_strtoUCS((__le16 *) bcc_ptr, tree,
3385 6 /* max utf8 char length in bytes */ *
3386 (/* server len*/ + 256 /* share len */), nls_codepage);
3387 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
1da177e4
LT
3388 bcc_ptr += 2; /* skip trailing null */
3389 } else { /* ASCII */
1da177e4
LT
3390 strcpy(bcc_ptr, tree);
3391 bcc_ptr += strlen(tree) + 1;
3392 }
3393 strcpy(bcc_ptr, "?????");
3394 bcc_ptr += strlen("?????");
3395 bcc_ptr += 1;
3396 count = bcc_ptr - &pSMB->Password[0];
3397 pSMB->hdr.smb_buf_length += count;
3398 pSMB->ByteCount = cpu_to_le16(count);
3399
3400 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3401
3402 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3403 /* above now done in SendReceive */
3404 if ((rc == 0) && (tcon != NULL)) {
3405 tcon->tidStatus = CifsGood;
3406 tcon->tid = smb_buffer_response->Tid;
3407 bcc_ptr = pByteArea(smb_buffer_response);
3408 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3409 /* skip service field (NB: this field is always ASCII) */
3410 bcc_ptr += length + 1;
3411 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3412 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3413 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3414 if ((bcc_ptr + (2 * length)) -
3415 pByteArea(smb_buffer_response) <=
3416 BCC(smb_buffer_response)) {
f99d49ad 3417 kfree(tcon->nativeFileSystem);
1da177e4 3418 tcon->nativeFileSystem =
e915fc49 3419 kzalloc(length + 2, GFP_KERNEL);
1da177e4 3420 cifs_strfromUCS_le(tcon->nativeFileSystem,
e89dc920 3421 (__le16 *) bcc_ptr,
1da177e4
LT
3422 length, nls_codepage);
3423 bcc_ptr += 2 * length;
3424 bcc_ptr[0] = 0; /* null terminate the string */
3425 bcc_ptr[1] = 0;
3426 bcc_ptr += 2;
3427 }
3428 /* else do not bother copying these informational fields */
3429 } else {
3430 length = strnlen(bcc_ptr, 1024);
3431 if ((bcc_ptr + length) -
3432 pByteArea(smb_buffer_response) <=
3433 BCC(smb_buffer_response)) {
f99d49ad 3434 kfree(tcon->nativeFileSystem);
1da177e4 3435 tcon->nativeFileSystem =
e915fc49 3436 kzalloc(length + 1, GFP_KERNEL);
1da177e4
LT
3437 strncpy(tcon->nativeFileSystem, bcc_ptr,
3438 length);
3439 }
3440 /* else do not bother copying these informational fields */
3441 }
3979877e
SF
3442 if(smb_buffer_response->WordCount == 3)
3443 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3444 else
3445 tcon->Flags = 0;
1da177e4
LT
3446 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3447 } else if ((rc == 0) && tcon == NULL) {
3448 /* all we need to save for IPC$ connection */
3449 ses->ipc_tid = smb_buffer_response->Tid;
3450 }
3451
3452 if (smb_buffer)
3453 cifs_buf_release(smb_buffer);
3454 return rc;
3455}
3456
3457int
3458cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3459{
3460 int rc = 0;
3461 int xid;
3462 struct cifsSesInfo *ses = NULL;
3463 struct task_struct *cifsd_task;
3464
3465 xid = GetXid();
3466
3467 if (cifs_sb->tcon) {
3468 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3469 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3470 if (rc == -EBUSY) {
3471 FreeXid(xid);
3472 return 0;
3473 }
3474 tconInfoFree(cifs_sb->tcon);
3475 if ((ses) && (ses->server)) {
3476 /* save off task so we do not refer to ses later */
3477 cifsd_task = ses->server->tsk;
3478 cFYI(1, ("About to do SMBLogoff "));
3479 rc = CIFSSMBLogoff(xid, ses);
3480 if (rc == -EBUSY) {
3481 FreeXid(xid);
3482 return 0;
3483 } else if (rc == -ESHUTDOWN) {
3484 cFYI(1,("Waking up socket by sending it signal"));
f191401f 3485 if(cifsd_task) {
1da177e4 3486 send_sig(SIGKILL,cifsd_task,1);
f191401f
SF
3487 wait_for_completion(&cifsd_complete);
3488 }
1da177e4
LT
3489 rc = 0;
3490 } /* else - we have an smb session
3491 left on this socket do not kill cifsd */
3492 } else
3493 cFYI(1, ("No session or bad tcon"));
3494 }
3495
3496 cifs_sb->tcon = NULL;
041e0e3b
NA
3497 if (ses)
3498 schedule_timeout_interruptible(msecs_to_jiffies(500));
1da177e4
LT
3499 if (ses)
3500 sesInfoFree(ses);
3501
3502 FreeXid(xid);
3503 return rc; /* BB check if we should always return zero here */
3504}
3505
3506int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3507 struct nls_table * nls_info)
3508{
3509 int rc = 0;
3510 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3511 int ntlmv2_flag = FALSE;
ad009ac9 3512 int first_time = 0;
1da177e4
LT
3513
3514 /* what if server changes its buffer size after dropping the session? */
3515 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3516 rc = CIFSSMBNegotiate(xid, pSesInfo);
3517 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3518 rc = CIFSSMBNegotiate(xid, pSesInfo);
3519 if(rc == -EAGAIN)
3520 rc = -EHOSTDOWN;
3521 }
3522 if(rc == 0) {
3523 spin_lock(&GlobalMid_Lock);
3524 if(pSesInfo->server->tcpStatus != CifsExiting)
3525 pSesInfo->server->tcpStatus = CifsGood;
3526 else
3527 rc = -EHOSTDOWN;
3528 spin_unlock(&GlobalMid_Lock);
3529
3530 }
ad009ac9 3531 first_time = 1;
1da177e4
LT
3532 }
3533 if (!rc) {
3534 pSesInfo->capabilities = pSesInfo->server->capabilities;
3535 if(linuxExtEnabled == 0)
3536 pSesInfo->capabilities &= (~CAP_UNIX);
ad009ac9 3537 /* pSesInfo->sequence_number = 0;*/
1da177e4
LT
3538 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3539 pSesInfo->server->secMode,
3540 pSesInfo->server->capabilities,
3541 pSesInfo->server->timeZone));
301dc3e6 3542#ifdef CONFIG_CIFS_EXPERIMENTAL
60808233 3543 if(experimEnabled > 1)
3979877e
SF
3544 rc = CIFS_SessSetup(xid, pSesInfo,
3545 first_time, nls_info);
301dc3e6
SF
3546 else
3547#endif
3548 if (extended_security
1da177e4
LT
3549 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3550 && (pSesInfo->server->secType == NTLMSSP)) {
5815449d 3551 cFYI(1, ("New style sesssetup"));
1da177e4
LT
3552 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3553 NULL /* security blob */,
3554 0 /* blob length */,
3555 nls_info);
3556 } else if (extended_security
3557 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3558 && (pSesInfo->server->secType == RawNTLMSSP)) {
5815449d 3559 cFYI(1, ("NTLMSSP sesssetup"));
1da177e4
LT
3560 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3561 pSesInfo,
3562 &ntlmv2_flag,
3563 nls_info);
3564 if (!rc) {
3565 if(ntlmv2_flag) {
3566 char * v2_response;
3567 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3568 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3569 nls_info)) {
3570 rc = -ENOMEM;
3571 goto ss_err_exit;
3572 } else
3573 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3574 if(v2_response) {
3575 CalcNTLMv2_response(pSesInfo,v2_response);
ad009ac9
SF
3576 /* if(first_time)
3577 cifs_calculate_ntlmv2_mac_key(
3578 pSesInfo->server->mac_signing_key,
3579 response, ntlm_session_key, */
1da177e4
LT
3580 kfree(v2_response);
3581 /* BB Put dummy sig in SessSetup PDU? */
3582 } else {
3583 rc = -ENOMEM;
3584 goto ss_err_exit;
3585 }
3586
3587 } else {
3588 SMBNTencrypt(pSesInfo->password,
3589 pSesInfo->server->cryptKey,
3590 ntlm_session_key);
3591
ad009ac9
SF
3592 if(first_time)
3593 cifs_calculate_mac_key(
3594 pSesInfo->server->mac_signing_key,
3595 ntlm_session_key,
3596 pSesInfo->password);
1da177e4
LT
3597 }
3598 /* for better security the weaker lanman hash not sent
3599 in AuthSessSetup so we no longer calculate it */
3600
3601 rc = CIFSNTLMSSPAuthSessSetup(xid,
3602 pSesInfo,
3603 ntlm_session_key,
3604 ntlmv2_flag,
3605 nls_info);
3606 }
3607 } else { /* old style NTLM 0.12 session setup */
3608 SMBNTencrypt(pSesInfo->password,
3609 pSesInfo->server->cryptKey,
3610 ntlm_session_key);
3611
ad009ac9
SF
3612 if(first_time)
3613 cifs_calculate_mac_key(
3614 pSesInfo->server->mac_signing_key,
3615 ntlm_session_key, pSesInfo->password);
3616
1da177e4
LT
3617 rc = CIFSSessSetup(xid, pSesInfo,
3618 ntlm_session_key, nls_info);
3619 }
3620 if (rc) {
3621 cERROR(1,("Send error in SessSetup = %d",rc));
3622 } else {
3623 cFYI(1,("CIFS Session Established successfully"));
3624 pSesInfo->status = CifsGood;
3625 }
3626 }
3627ss_err_exit:
3628 return rc;
3629}
3630
This page took 0.268544 seconds and 5 git commands to generate.