[CIFS] Support for setting up SMB sessions to legacy lanman servers
[linux-2.6/libata-dev.git] / fs / cifs / connect.c
blob7ffb8f244f6a1c8abe8bb6ec54bba6d53a6b99e6
1 /*
2 * fs/cifs/connect.c
4 * Copyright (C) International Business Machines Corp., 2002,2006
5 * Author(s): Steve French (sfrench@us.ibm.com)
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.
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.
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
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>
31 #include <linux/delay.h>
32 #include <linux/completion.h>
33 #include <linux/pagevec.h>
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"
45 #include "cn_cifs.h"
47 #define CIFS_PORT 445
48 #define RFC1001_PORT 139
50 static DECLARE_COMPLETION(cifsd_complete);
52 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
53 unsigned char *p24);
55 extern mempool_t *cifs_req_poolp;
57 struct 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 */
66 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
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 */
77 unsigned cifs_acl:1;
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;
81 unsigned remap:1; /* set to remap seven reserved chars in filenames */
82 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
83 unsigned sfu_emul:1;
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 */
90 unsigned nocase; /* request case insensitive filenames */
91 unsigned nobrl; /* disable sending byte range locks to srv */
92 unsigned int rsize;
93 unsigned int wsize;
94 unsigned int sockopt;
95 unsigned short int port;
98 static int ipv4_connect(struct sockaddr_in *psin_server,
99 struct socket **csocket,
100 char * netb_name,
101 char * server_netb_name);
102 static int ipv6_connect(struct sockaddr_in6 *psin_server,
103 struct socket **csocket);
107 * cifs tcp session reconnection
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)
116 cifs_reconnect(struct TCP_Server_Info *server)
118 int rc = 0;
119 struct list_head *tmp;
120 struct cifsSesInfo *ses;
121 struct cifsTconInfo *tcon;
122 struct mid_q_entry * mid_entry;
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;
135 cFYI(1, ("Reconnecting tcp session"));
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;
148 /* else tcp and smb sessions need reconnection */
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;
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;
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) {
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 */
180 mid_entry->midState = MID_RETRY_NEEDED;
184 spin_unlock(&GlobalMid_Lock);
185 up(&server->tcpSem);
187 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
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,
194 server->workstation_RFC1001_name,
195 server->server_RFC1001_name);
197 if(rc) {
198 cFYI(1,("reconnect error %d",rc));
199 msleep(3000);
200 } else {
201 atomic_inc(&tcpSesReconnectCount);
202 spin_lock(&GlobalMid_Lock);
203 if(server->tcpStatus != CifsExiting)
204 server->tcpStatus = CifsGood;
205 server->sequence_number = 0;
206 spin_unlock(&GlobalMid_Lock);
207 /* atomic_set(&server->inFlight,0);*/
208 wake_up(&server->response_q);
211 return rc;
215 return codes:
216 0 not a transact2, or all data present
217 >0 transact2 with that much data missing
218 -EINVAL = invalid transact2
221 static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
223 struct smb_t2_rsp * pSMBt;
224 int total_data_size;
225 int data_in_this_rsp;
226 int remaining;
228 if(pSMB->Command != SMB_COM_TRANSACTION2)
229 return 0;
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;
238 pSMBt = (struct smb_t2_rsp *)pSMB;
240 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
241 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
243 remaining = total_data_size - data_in_this_rsp;
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;
259 return remaining;
263 static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
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;
275 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
277 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
278 cFYI(1,("total data sizes of primary and secondary t2 differ"));
281 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
283 remaining = total_data_size - total_in_buf;
285 if(remaining < 0)
286 return -EINVAL;
288 if(remaining == 0) /* nothing to do, ignore */
289 return 0;
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"));
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 */
301 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
302 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
304 data_area_of_target += total_in_buf;
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);
314 byte_count = pTargetSMB->smb_buf_length;
315 byte_count += total_in_buf2;
317 /* BB also add check that we are not beyond maximum buffer size */
319 pTargetSMB->smb_buf_length = byte_count;
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;
329 static int
330 cifs_demultiplex_thread(struct TCP_Server_Info *server)
332 int length;
333 unsigned int pdu_length, total_read;
334 struct smb_hdr *smb_buffer = NULL;
335 struct smb_hdr *bigbuf = NULL;
336 struct smb_hdr *smallbuf = NULL;
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;
344 char temp;
345 int isLargeBuf = FALSE;
346 int isMultiRsp;
347 int reconnect;
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);
358 complete(&cifsd_complete);
359 if(length > 1) {
360 mempool_resize(cifs_req_poolp,
361 length + cifs_min_rcv,
362 GFP_KERNEL);
365 while (server->tcpStatus != CifsExiting) {
366 if (try_to_freeze())
367 continue;
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;
376 } else if(isLargeBuf) {
377 /* we are reusing a dirtry large buf, clear its start */
378 memset(bigbuf, 0, sizeof (struct smb_hdr));
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;
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));
393 isLargeBuf = FALSE;
394 isMultiRsp = FALSE;
395 smb_buffer = smallbuf;
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 */);
404 if(server->tcpStatus == CifsExiting) {
405 break;
406 } else if (server->tcpStatus == CifsNeedReconnect) {
407 cFYI(1,("Reconnect after server stopped responding"));
408 cifs_reconnect(server);
409 cFYI(1,("call to reconnect done"));
410 csocket = server->ssocket;
411 continue;
412 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
413 msleep(1); /* minimum sleep to prevent looping
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) {
419 cFYI(1,("tcp session abend after SMBnegprot"));
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 */
424 break;
426 if(length == -EINTR) {
427 cFYI(1,("cifsd thread killed"));
428 break;
430 cFYI(1,("Reconnect after unexpected peek error %d",
431 length));
432 cifs_reconnect(server);
433 csocket = server->ssocket;
434 wake_up(&server->response_q);
435 continue;
436 } else if (length < 4) {
437 cFYI(1,
438 ("Frame under four bytes received (%d bytes long)",
439 length));
440 cifs_reconnect(server);
441 csocket = server->ssocket;
442 wake_up(&server->response_q);
443 continue;
446 /* The right amount was read from socket - 4 bytes */
447 /* so we can now interpret the length field */
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);
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 */
457 pdu_length = ntohl(smb_buffer->smb_buf_length);
458 smb_buffer->smb_buf_length = pdu_length;
460 cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
462 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
463 continue;
464 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
465 cFYI(1,("Good RFC 1002 session rsp"));
466 continue;
467 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
468 /* we get this from Windows 98 instead of
469 an error on SMB negprot response */
470 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
471 pdu_length));
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);
488 cifs_reconnect(server);
489 csocket = server->ssocket;
490 wake_up(&server->response_q);
491 continue;
493 } else if (temp != (char) 0) {
494 cERROR(1,("Unknown RFC 1002 frame"));
495 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
496 length);
497 cifs_reconnect(server);
498 csocket = server->ssocket;
499 continue;
502 /* else we have an SMB response */
503 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
504 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
505 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
506 length, pdu_length+4));
507 cifs_reconnect(server);
508 csocket = server->ssocket;
509 wake_up(&server->response_q);
510 continue;
513 /* else length ok */
514 reconnect = 0;
516 if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
517 isLargeBuf = TRUE;
518 memcpy(bigbuf, smallbuf, 4);
519 smb_buffer = bigbuf;
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) {
534 cifs_reconnect(server);
535 csocket = server->ssocket;
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*/
546 continue;
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;
556 if(reconnect == 2)
557 break;
558 else if(reconnect == 1)
559 continue;
561 length += 4; /* account for rfc1002 hdr */
564 dump_smb(smb_buffer, length);
565 if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
566 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
567 continue;
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);
576 if ((mid_entry->mid == smb_buffer->Mid) &&
577 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
578 (mid_entry->command == smb_buffer->Command)) {
579 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
580 /* We have a multipart transact2 resp */
581 isMultiRsp = TRUE;
582 if(mid_entry->resp_buf) {
583 /* merge response - fix up 1st*/
584 if(coalesce_t2(smb_buffer,
585 mid_entry->resp_buf)) {
586 mid_entry->multiRsp = 1;
587 break;
588 } else {
589 /* all parts received */
590 mid_entry->multiEnd = 1;
591 goto multi_t2_fnd;
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 {
599 /* Have first buffer */
600 mid_entry->resp_buf =
601 smb_buffer;
602 mid_entry->largeBuf = 1;
603 bigbuf = NULL;
606 break;
608 mid_entry->resp_buf = smb_buffer;
609 if(isLargeBuf)
610 mid_entry->largeBuf = 1;
611 else
612 mid_entry->largeBuf = 0;
613 multi_t2_fnd:
614 task_to_wake = mid_entry->tsk;
615 mid_entry->midState = MID_RESPONSE_RECEIVED;
616 #ifdef CONFIG_CIFS_STATS2
617 mid_entry->when_received = jiffies;
618 #endif
619 break;
622 spin_unlock(&GlobalMid_Lock);
623 if (task_to_wake) {
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;
632 wake_up_process(task_to_wake);
633 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
634 && (isMultiRsp == FALSE)) {
635 cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter));
636 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
637 sizeof(struct smb_hdr));
638 #ifdef CONFIG_CIFS_DEBUG2
639 cifs_dump_detail(smb_buffer);
640 cifs_dump_mids(server);
641 #endif /* CIFS_DEBUG2 */
644 } /* end while !EXITING */
646 spin_lock(&GlobalMid_Lock);
647 server->tcpStatus = CifsExiting;
648 server->tsk = NULL;
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 */
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
659 that may haven been blocked when more than 50 at time were on the wire
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 */
664 msleep(125);
666 if(server->ssocket) {
667 sock_release(csocket);
668 server->ssocket = NULL;
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);
676 read_lock(&GlobalSMBSeslock);
677 if (list_empty(&server->pending_mid_q)) {
678 /* loop through server session structures attached to this and
679 mark them dead */
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;
689 read_unlock(&GlobalSMBSeslock);
690 } else {
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;
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,
707 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
708 task_to_wake = mid_entry->tsk;
709 if(task_to_wake) {
710 wake_up_process(task_to_wake);
714 spin_unlock(&GlobalMid_Lock);
715 read_unlock(&GlobalSMBSeslock);
716 /* 1/8th of sec is more than enough time for them to exit */
717 msleep(125);
720 if (!list_empty(&server->pending_mid_q)) {
721 /* mpx threads have not exited yet give them
722 at least the smb send timeout time for long ops */
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 */
727 cFYI(1, ("Wait for exit from demultiplex thread"));
728 msleep(46000);
729 /* if threads still have not exited they are probably never
730 coming home not much else we can do but free the memory */
733 write_lock(&GlobalSMBSeslock);
734 atomic_dec(&tcpSesAllocCount);
735 length = tcpSesAllocCount.counter;
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;
748 write_unlock(&GlobalSMBSeslock);
750 kfree(server);
751 if(length > 0) {
752 mempool_resize(cifs_req_poolp,
753 length + cifs_min_rcv,
754 GFP_KERNEL);
757 complete_and_exit(&cifsd_complete, 0);
758 return 0;
761 static int
762 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
764 char *value;
765 char *data;
766 unsigned int temp_len, i, j;
767 char separator[2];
769 separator[0] = ',';
770 separator[1] = 0;
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 */
777 vol->source_rfc1001_name[i] =
778 toupper(system_utsname.nodename[i]);
780 vol->source_rfc1001_name[15] = 0;
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;
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);
790 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
791 vol->rw = TRUE;
792 vol->ntlm = TRUE;
793 /* default is always to request posix paths. */
794 vol->posix_paths = 1;
796 if (!options)
797 return 1;
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"));
808 while ((data = strsep(&options, separator)) != NULL) {
809 if (!*data)
810 continue;
811 if ((value = strchr(data, '=')) != NULL)
812 *value++ = '\0';
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; */
824 if (strnlen(value, 200) < 200) {
825 vol->username = value;
826 } else {
827 printk(KERN_WARNING "CIFS: username too long\n");
828 return 1;
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;
844 temp_len = strlen(value);
845 /* removed password length check, NTLM passwords
846 can be arbitrarily long */
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. */
855 /* NB: password legally can have multiple commas and
856 the only illegal character in a password is null */
858 if ((value[temp_len] == 0) &&
859 (value[temp_len+1] == separator[0])) {
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]) {
865 if (value[temp_len+1] ==
866 separator[0]) {
867 /* skip second comma */
868 temp_len++;
869 } else {
870 /* single comma indicating start
871 of next parm */
872 break;
875 temp_len++;
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;
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 */
887 vol->password = kzalloc(temp_len, GFP_KERNEL);
888 if(vol->password == NULL) {
889 printk("CIFS: no memory for pass\n");
890 return 1;
892 for(i=0,j=0;i<temp_len;i++,j++) {
893 vol->password[j] = value[i];
894 if(value[i] == separator[0]
895 && value[i+1] == separator[0]) {
896 /* skip second comma */
897 i++;
900 vol->password[j] = 0;
901 } else {
902 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
903 if(vol->password == NULL) {
904 printk("CIFS: no memory for pass\n");
905 return 1;
907 strcpy(vol->password, value);
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;
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;
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; */
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;
972 } else {
973 printk(KERN_WARNING "CIFS: UNC name too long\n");
974 return 1;
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; */
982 /* BB are there cases in which a comma can be valid in
983 a domain name and need special handling? */
984 if (strnlen(value, 256) < 256) {
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;
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; */
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;
1005 } else if (strnicmp(data, "uid", 3) == 0) {
1006 if (value && *value) {
1007 vol->linux_uid =
1008 simple_strtoul(value, &value, 0);
1010 } else if (strnicmp(data, "gid", 3) == 0) {
1011 if (value && *value) {
1012 vol->linux_gid =
1013 simple_strtoul(value, &value, 0);
1015 } else if (strnicmp(data, "file_mode", 4) == 0) {
1016 if (value && *value) {
1017 vol->file_mode =
1018 simple_strtoul(value, &value, 0);
1020 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1021 if (value && *value) {
1022 vol->dir_mode =
1023 simple_strtoul(value, &value, 0);
1025 } else if (strnicmp(data, "dirmode", 4) == 0) {
1026 if (value && *value) {
1027 vol->dir_mode =
1028 simple_strtoul(value, &value, 0);
1030 } else if (strnicmp(data, "port", 4) == 0) {
1031 if (value && *value) {
1032 vol->port =
1033 simple_strtoul(value, &value, 0);
1035 } else if (strnicmp(data, "rsize", 5) == 0) {
1036 if (value && *value) {
1037 vol->rsize =
1038 simple_strtoul(value, &value, 0);
1040 } else if (strnicmp(data, "wsize", 5) == 0) {
1041 if (value && *value) {
1042 vol->wsize =
1043 simple_strtoul(value, &value, 0);
1045 } else if (strnicmp(data, "sockopt", 5) == 0) {
1046 if (value && *value) {
1047 vol->sockopt =
1048 simple_strtoul(value, &value, 0);
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)? */
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];
1066 /* The string has 16th byte zero still from
1067 set at top of the function */
1068 if((i==15) && (value[i] != 0))
1069 printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
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);
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)? */
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];
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");
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;
1127 } else if (strnicmp(data, "mapchars", 8) == 0) {
1128 vol->remap = 1;
1129 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1130 vol->remap = 0;
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;
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;
1139 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1140 (strnicmp(data, "ignorecase", 10) == 0)) {
1141 vol->nocase = 1;
1142 } else if (strnicmp(data, "brl", 3) == 0) {
1143 vol->nobrl = 0;
1144 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1145 (strnicmp(data, "nolock", 6) == 0)) {
1146 vol->nobrl = 1;
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;
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;
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;
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;
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);
1194 if (vol->UNC == NULL) {
1195 if(devname == NULL) {
1196 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1197 return 1;
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;
1211 } else {
1212 printk(KERN_WARNING "CIFS: UNC name too long\n");
1213 return 1;
1216 if(vol->UNCip == NULL)
1217 vol->UNCip = &vol->UNC[2];
1219 return 0;
1222 static struct cifsSesInfo *
1223 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1224 struct in6_addr *target_ip6_addr,
1225 char *userName, struct TCP_Server_Info **psrvTcp)
1227 struct list_head *tmp;
1228 struct cifsSesInfo *ses;
1229 *psrvTcp = NULL;
1230 read_lock(&GlobalSMBSeslock);
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 */
1251 /* else tcp and smb sessions need reconnection */
1253 read_unlock(&GlobalSMBSeslock);
1254 return NULL;
1257 static struct cifsTconInfo *
1258 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1260 struct list_head *tmp;
1261 struct cifsTconInfo *tcon;
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)*/
1298 read_unlock(&GlobalSMBSeslock);
1299 return NULL;
1303 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1304 const char *old_path, const struct nls_table *nls_codepage,
1305 int remap)
1307 unsigned char *referrals = NULL;
1308 unsigned int num_referrals;
1309 int rc = 0;
1311 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1312 &num_referrals, &referrals, remap);
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 */
1318 kfree(referrals);
1320 return rc;
1324 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1325 const char *old_path, const struct nls_table *nls_codepage,
1326 unsigned int *pnum_referrals,
1327 unsigned char ** preferrals, int remap)
1329 char *temp_unc;
1330 int rc = 0;
1332 *pnum_referrals = 0;
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);
1350 if (rc == 0)
1351 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1352 pnum_referrals, nls_codepage, remap);
1354 return rc;
1357 /* See RFC1001 section 14 on representation of Netbios names */
1358 static void rfc1002mangle(char * target,char * source, unsigned int length)
1360 unsigned int i,j;
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;
1372 static int
1373 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1374 char * netbios_name, char * target_name)
1376 int rc = 0;
1377 int connected = 0;
1378 __be16 orig_port = 0;
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;
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;
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;
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);
1411 rc = (*csocket)->ops->connect(*csocket,
1412 (struct sockaddr *) psin_server,
1413 sizeof (struct sockaddr_in),0);
1414 if (rc >= 0)
1415 connected = 1;
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;
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;
1436 /* Eventually check for other socket options to change from
1437 the default. sock_setsockopt not used because it expects
1438 user space buffer */
1439 cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf,
1440 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1441 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
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;
1448 /* send RFC1001 sessinit */
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;
1455 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1456 if(ses_init_buf) {
1457 ses_init_buf->trailer.session_req.called_len = 32;
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);
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);
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);
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 */
1493 /* else the negprot may still work without this
1494 even though malloc failed */
1498 return rc;
1501 static int
1502 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1504 int rc = 0;
1505 int connected = 0;
1506 __be16 orig_port = 0;
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;
1521 psin_server->sin6_family = AF_INET6;
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;
1531 if(!connected) {
1532 /* save original port so we can retry user specified port
1533 later if fall back ports fail this time */
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);
1540 rc = (*csocket)->ops->connect(*csocket,
1541 (struct sockaddr *) psin_server,
1542 sizeof (struct sockaddr_in6),0);
1543 if (rc >= 0)
1544 connected = 1;
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;
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;
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;
1570 return rc;
1574 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1575 char *mount_data, const char *devname)
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;
1589 xid = GetXid();
1591 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1593 memset(&volume_info,0,sizeof(struct smb_vol));
1594 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1595 kfree(volume_info.UNC);
1596 kfree(volume_info.password);
1597 FreeXid(xid);
1598 return -EINVAL;
1601 if (volume_info.username) {
1602 /* BB fixme parse for domain name here */
1603 cFYI(1, ("Username: %s ", volume_info.username));
1605 } else {
1606 cifserror("No username specified");
1607 /* In userspace mount helper we can get user name from alternate
1608 locations such as env variables and files on disk */
1609 kfree(volume_info.UNC);
1610 kfree(volume_info.password);
1611 FreeXid(xid);
1612 return -EINVAL;
1615 if (volume_info.UNCip && volume_info.UNC) {
1616 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
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;
1627 if(rc <= 0) {
1628 /* we failed translating address */
1629 kfree(volume_info.UNC);
1630 kfree(volume_info.password);
1631 FreeXid(xid);
1632 return -EINVAL;
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"));
1641 kfree(volume_info.UNC);
1642 kfree(volume_info.password);
1643 FreeXid(xid);
1644 return -EINVAL;
1645 } else /* which servers DFS root would we conect to */ {
1646 cERROR(1,
1647 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
1648 kfree(volume_info.UNC);
1649 kfree(volume_info.password);
1650 FreeXid(xid);
1651 return -EINVAL;
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));
1662 kfree(volume_info.UNC);
1663 kfree(volume_info.password);
1664 FreeXid(xid);
1665 return -ELIBACC;
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 {
1678 kfree(volume_info.UNC);
1679 kfree(volume_info.password);
1680 FreeXid(xid);
1681 return -EINVAL;
1685 if (srvTcp) {
1686 cFYI(1, ("Existing tcp session with server found"));
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;
1692 rc = ipv4_connect(&sin_server,&csocket,
1693 volume_info.source_rfc1001_name,
1694 volume_info.target_rfc1001_name);
1695 if (rc < 0) {
1696 cERROR(1,
1697 ("Error connecting to IPv4 socket. Aborting operation"));
1698 if(csocket != NULL)
1699 sock_release(csocket);
1700 kfree(volume_info.UNC);
1701 kfree(volume_info.password);
1702 FreeXid(xid);
1703 return rc;
1706 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1707 if (srvTcp == NULL) {
1708 rc = -ENOMEM;
1709 sock_release(csocket);
1710 kfree(volume_info.UNC);
1711 kfree(volume_info.password);
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);
1734 kfree(volume_info.UNC);
1735 kfree(volume_info.password);
1736 FreeXid(xid);
1737 return rc;
1739 wait_for_completion(&cifsd_complete);
1740 rc = 0;
1741 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1742 memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
1743 srvTcp->sequence_number = 0;
1747 if (existingCifsSes) {
1748 pSesInfo = existingCifsSes;
1749 cFYI(1, ("Existing smb sess found"));
1750 kfree(volume_info.password);
1751 /* volume_info.UNC freed at end of function */
1752 } else if (!rc) {
1753 cFYI(1, ("Existing smb sess not found"));
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));
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);
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);
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
1785 kfree(volume_info.password);
1788 /* search for existing tcon to this server share */
1789 if (!rc) {
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))
1795 cifs_sb->rsize = volume_info.rsize;
1796 else /* default */
1797 cifs_sb->rsize = CIFSMaxBufSize;
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)
1804 cifs_sb->wsize = volume_info.wsize;
1805 else
1806 cifs_sb->wsize =
1807 min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
1808 127*1024);
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 */
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"));
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;
1825 cFYI(1,("file mode: 0x%x dir mode: 0x%x",
1826 cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
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;
1834 if(volume_info.remap)
1835 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1836 if(volume_info.no_xattr)
1837 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1838 if(volume_info.sfu_emul)
1839 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1840 if(volume_info.nobrl)
1841 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1842 if(volume_info.cifs_acl)
1843 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
1845 if(volume_info.direct_io) {
1846 cFYI(1,("mounting share using direct i/o"));
1847 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1850 tcon =
1851 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1852 volume_info.username);
1853 if (tcon) {
1854 cFYI(1, ("Found match on UNC path"));
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;
1860 tcon->nocase = volume_info.nocase;
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 */
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)) {
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);
1876 kfree(volume_info.UNC);
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));
1885 if (!rc) {
1886 atomic_inc(&pSesInfo->inUse);
1887 tcon->retry = volume_info.retry;
1888 tcon->nocase = volume_info.nocase;
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 */
1900 sb->s_time_gran = 100;
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);
1910 if(srvTcp->tsk) {
1911 send_sig(SIGKILL,srvTcp->tsk,1);
1912 wait_for_completion(&cifsd_complete);
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) &&
1926 (pSesInfo->server->tsk)) {
1927 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1928 wait_for_completion(&cifsd_complete);
1930 } else
1931 cFYI(1, ("No session or bad tcon"));
1932 sesInfoFree(pSesInfo);
1933 /* pSesInfo = NULL; */
1936 } else {
1937 atomic_inc(&tcon->useCount);
1938 cifs_sb->tcon = tcon;
1939 tcon->ses = pSesInfo;
1941 /* do not care if following two calls succeed - informational */
1942 CIFSSMBQFSDeviceInfo(xid, tcon);
1943 CIFSSMBQFSAttributeInfo(xid, tcon);
1945 if (tcon->ses->capabilities & CAP_UNIX) {
1946 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
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;
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;
1965 cFYI(1,("Negotiate caps 0x%x",(int)cap));
1967 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1968 cFYI(1,("setting capabilities failed"));
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));
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));
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) */
1986 kfree(volume_info.UNC);
1987 FreeXid(xid);
1988 return rc;
1991 static int
1992 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1993 char session_key[CIFS_SESSION_KEY_SIZE],
1994 const struct nls_table *nls_codepage)
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;
2010 cFYI(1, ("In sesssetup"));
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;
2019 smb_buffer_response = smb_buffer;
2020 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2022 /* send SMBsessionSetup here */
2023 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2024 NULL /* no tCon exists yet */ , 13 /* wct */ );
2026 smb_buffer->Mid = GetNextMid(ses->server);
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);
2031 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2032 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
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;
2040 if (ses->capabilities & CAP_STATUS32) {
2041 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2042 capabilities |= CAP_STATUS32;
2044 if (ses->capabilities & CAP_DFS) {
2045 smb_buffer->Flags2 |= SMBFLG2_DFS;
2046 capabilities |= CAP_DFS;
2048 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2050 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2051 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
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;
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++;
2066 if(user == NULL)
2067 bytes_returned = 0; /* skip null user */
2068 else
2069 bytes_returned =
2070 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
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 =
2077 cifs_strtoUCS((__le16 *) bcc_ptr,
2078 "CIFS_LINUX_DOM", 32, nls_codepage);
2079 else
2080 bytes_returned =
2081 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2082 nls_codepage);
2083 bcc_ptr += 2 * bytes_returned;
2084 bcc_ptr += 2;
2085 bytes_returned =
2086 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2087 32, nls_codepage);
2088 bcc_ptr += 2 * bytes_returned;
2089 bytes_returned =
2090 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
2091 32, nls_codepage);
2092 bcc_ptr += 2 * bytes_returned;
2093 bcc_ptr += 2;
2094 bytes_returned =
2095 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
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);
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++;
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;
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);
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;
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;
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 */
2161 if(ses->serverOS)
2162 kfree(ses->serverOS);
2163 ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
2164 if(ses->serverOS == NULL)
2165 goto sesssetup_nomem;
2166 cifs_strfromUCS_le(ses->serverOS,
2167 (__le16 *)bcc_ptr, len,nls_codepage);
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);
2175 if(ses->serverNOS)
2176 kfree(ses->serverNOS);
2177 ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
2178 if(ses->serverNOS == NULL)
2179 goto sesssetup_nomem;
2180 cifs_strfromUCS_le(ses->serverNOS,
2181 (__le16 *)bcc_ptr,len,nls_codepage);
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;
2190 remaining_words -= len + 1;
2191 if (remaining_words > 0) {
2192 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2193 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2194 if(ses->serverDomain)
2195 kfree(ses->serverDomain);
2196 ses->serverDomain =
2197 kzalloc(2*(len+1),GFP_KERNEL);
2198 if(ses->serverDomain == NULL)
2199 goto sesssetup_nomem;
2200 cifs_strfromUCS_le(ses->serverDomain,
2201 (__le16 *)bcc_ptr,len,nls_codepage);
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 */
2206 else {
2207 if(ses->serverDomain)
2208 kfree(ses->serverDomain);
2209 ses->serverDomain =
2210 kzalloc(2, GFP_KERNEL);
2212 } else { /* no room so create dummy domain and NOS string */
2213 /* if these kcallocs fail not much we
2214 can do, but better to not fail the
2215 sesssetup itself */
2216 if(ses->serverDomain)
2217 kfree(ses->serverDomain);
2218 ses->serverDomain =
2219 kzalloc(2, GFP_KERNEL);
2220 if(ses->serverNOS)
2221 kfree(ses->serverNOS);
2222 ses->serverNOS =
2223 kzalloc(2, GFP_KERNEL);
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)) {
2230 if(ses->serverOS)
2231 kfree(ses->serverOS);
2232 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
2233 if(ses->serverOS == NULL)
2234 goto sesssetup_nomem;
2235 strncpy(ses->serverOS,bcc_ptr, len);
2237 bcc_ptr += len;
2238 bcc_ptr[0] = 0; /* null terminate the string */
2239 bcc_ptr++;
2241 len = strnlen(bcc_ptr, 1024);
2242 if(ses->serverNOS)
2243 kfree(ses->serverNOS);
2244 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2245 if(ses->serverNOS == NULL)
2246 goto sesssetup_nomem;
2247 strncpy(ses->serverNOS, bcc_ptr, len);
2248 bcc_ptr += len;
2249 bcc_ptr[0] = 0;
2250 bcc_ptr++;
2252 len = strnlen(bcc_ptr, 1024);
2253 if(ses->serverDomain)
2254 kfree(ses->serverDomain);
2255 ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
2256 if(ses->serverDomain == NULL)
2257 goto sesssetup_nomem;
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));
2267 } else {
2268 cERROR(1,
2269 (" Security Blob Length extends beyond end of SMB"));
2271 } else {
2272 cERROR(1,
2273 (" Invalid Word count %d: ",
2274 smb_buffer_response->WordCount));
2275 rc = -EIO;
2277 sesssetup_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 */
2280 if (smb_buffer)
2281 cifs_buf_release(smb_buffer);
2283 return rc;
2286 static int
2287 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2288 char *SecurityBlob,int SecurityBlobLength,
2289 const struct nls_table *nls_codepage)
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;
2305 cFYI(1, ("In spnego sesssetup "));
2306 if(ses == NULL)
2307 return -EINVAL;
2308 user = ses->userName;
2309 domain = ses->domainName;
2311 smb_buffer = cifs_buf_get();
2312 if (smb_buffer == NULL) {
2313 return -ENOMEM;
2315 smb_buffer_response = smb_buffer;
2316 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2318 /* send SMBsessionSetup here */
2319 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2320 NULL /* no tCon exists yet */ , 12 /* wct */ );
2322 smb_buffer->Mid = GetNextMid(ses->server);
2323 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2324 pSMB->req.AndXCommand = 0xFF;
2325 if(ses->server->maxBuf > 64*1024)
2326 ses->server->maxBuf = (64*1023);
2327 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2328 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2330 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2331 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
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;
2339 if (ses->capabilities & CAP_STATUS32) {
2340 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2341 capabilities |= CAP_STATUS32;
2343 if (ses->capabilities & CAP_DFS) {
2344 smb_buffer->Flags2 |= SMBFLG2_DFS;
2345 capabilities |= CAP_DFS;
2347 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2349 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2350 bcc_ptr = pByteArea(smb_buffer);
2351 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2352 bcc_ptr += SecurityBlobLength;
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++;
2359 bytes_returned =
2360 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage);
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 =
2365 cifs_strtoUCS((__le16 *) bcc_ptr,
2366 "CIFS_LINUX_DOM", 32, nls_codepage);
2367 else
2368 bytes_returned =
2369 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2370 nls_codepage);
2371 bcc_ptr += 2 * bytes_returned;
2372 bcc_ptr += 2;
2373 bytes_returned =
2374 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2375 32, nls_codepage);
2376 bcc_ptr += 2 * bytes_returned;
2377 bytes_returned =
2378 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2379 nls_codepage);
2380 bcc_ptr += 2 * bytes_returned;
2381 bcc_ptr += 2;
2382 bytes_returned =
2383 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
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++;
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;
2408 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2409 smb_buffer->smb_buf_length += count;
2410 pSMB->req.ByteCount = cpu_to_le16(count);
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 */
2428 /* BB Fix below to make endian neutral !! */
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));
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 =
2451 (smb_buffer_response) / 2;
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 */
2459 if(ses->serverOS)
2460 kfree(ses->serverOS);
2461 ses->serverOS =
2462 kzalloc(2 * (len + 1), GFP_KERNEL);
2463 cifs_strfromUCS_le(ses->serverOS,
2464 (__le16 *)
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);
2475 if(ses->serverNOS)
2476 kfree(ses->serverNOS);
2477 ses->serverNOS =
2478 kzalloc(2 * (len + 1),
2479 GFP_KERNEL);
2480 cifs_strfromUCS_le(ses->serverNOS,
2481 (__le16 *)bcc_ptr,
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);
2490 /* last string not null terminated (e.g.Windows XP/2000) */
2491 if(ses->serverDomain)
2492 kfree(ses->serverDomain);
2493 ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
2494 cifs_strfromUCS_le(ses->serverDomain,
2495 (__le16 *)bcc_ptr,
2496 len, nls_codepage);
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 */
2501 else {
2502 if(ses->serverDomain)
2503 kfree(ses->serverDomain);
2504 ses->serverDomain =
2505 kzalloc(2,GFP_KERNEL);
2507 } else {/* no room use dummy domain&NOS */
2508 if(ses->serverDomain)
2509 kfree(ses->serverDomain);
2510 ses->serverDomain = kzalloc(2, GFP_KERNEL);
2511 if(ses->serverNOS)
2512 kfree(ses->serverNOS);
2513 ses->serverNOS = kzalloc(2, GFP_KERNEL);
2515 } else { /* ASCII */
2517 len = strnlen(bcc_ptr, 1024);
2518 if (((long) bcc_ptr + len) - (long)
2519 pByteArea(smb_buffer_response)
2520 <= BCC(smb_buffer_response)) {
2521 if(ses->serverOS)
2522 kfree(ses->serverOS);
2523 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
2524 strncpy(ses->serverOS, bcc_ptr, len);
2526 bcc_ptr += len;
2527 bcc_ptr[0] = 0; /* null terminate the string */
2528 bcc_ptr++;
2530 len = strnlen(bcc_ptr, 1024);
2531 if(ses->serverNOS)
2532 kfree(ses->serverNOS);
2533 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2534 strncpy(ses->serverNOS, bcc_ptr, len);
2535 bcc_ptr += len;
2536 bcc_ptr[0] = 0;
2537 bcc_ptr++;
2539 len = strnlen(bcc_ptr, 1024);
2540 if(ses->serverDomain)
2541 kfree(ses->serverDomain);
2542 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
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));
2552 } else {
2553 cERROR(1,
2554 (" Security Blob Length extends beyond end of SMB"));
2556 } else {
2557 cERROR(1, ("No session structure passed in."));
2559 } else {
2560 cERROR(1,
2561 (" Invalid Word count %d: ",
2562 smb_buffer_response->WordCount));
2563 rc = -EIO;
2566 if (smb_buffer)
2567 cifs_buf_release(smb_buffer);
2569 return rc;
2572 static int
2573 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2574 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2575 const struct nls_table *nls_codepage)
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;
2593 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
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;
2602 smb_buffer_response = smb_buffer;
2603 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2604 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2606 /* send SMBsessionSetup here */
2607 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2608 NULL /* no tCon exists yet */ , 12 /* wct */ );
2610 smb_buffer->Mid = GetNextMid(ses->server);
2611 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2612 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
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);
2618 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2619 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
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;
2627 if (ses->capabilities & CAP_STATUS32) {
2628 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2629 capabilities |= CAP_STATUS32;
2631 if (ses->capabilities & CAP_DFS) {
2632 smb_buffer->Flags2 |= SMBFLG2_DFS;
2633 capabilities |= CAP_DFS;
2635 pSMB->req.Capabilities = cpu_to_le32(capabilities);
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 |
2643 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2644 NTLMSSP_NEGOTIATE_56 |
2645 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2646 if(sign_CIFS_PDUs)
2647 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2648 /* if(ntlmv2_support)
2649 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2650 /* setup pointers to domain name and workstation name */
2651 bcc_ptr += SecurityBlobLength;
2653 SecurityBlob->WorkstationName.Buffer = 0;
2654 SecurityBlob->WorkstationName.Length = 0;
2655 SecurityBlob->WorkstationName.MaximumLength = 0;
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;
2662 if (ses->capabilities & CAP_UNICODE) {
2663 if ((long) bcc_ptr % 2) {
2664 *bcc_ptr = 0;
2665 bcc_ptr++;
2668 bytes_returned =
2669 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2670 32, nls_codepage);
2671 bcc_ptr += 2 * bytes_returned;
2672 bytes_returned =
2673 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2674 nls_codepage);
2675 bcc_ptr += 2 * bytes_returned;
2676 bcc_ptr += 2; /* null terminate Linux version */
2677 bytes_returned =
2678 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
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;
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);
2703 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2704 &bytes_returned, 1);
2706 if (smb_buffer_response->Status.CifsError ==
2707 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2708 rc = 0;
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);
2717 if (action & GUEST_LOGIN)
2718 cFYI(1, (" Guest login"));
2719 /* Do we want to set anything in SesInfo struct when guest login? */
2721 bcc_ptr = pByteArea(smb_buffer_response);
2722 /* response can have either 3 or 4 word count - Samba sends 3 */
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 */
2731 cFYI(1, ("UID = %d", ses->Suid));
2732 if ((pSMBr->resp.hdr.WordCount == 3)
2733 || ((pSMBr->resp.hdr.WordCount == 4)
2734 && (blob_len <
2735 pSMBr->resp.ByteCount))) {
2737 if (pSMBr->resp.hdr.WordCount == 4) {
2738 bcc_ptr += blob_len;
2739 cFYI(1, ("Security Blob Length %d",
2740 blob_len));
2743 cFYI(1, ("NTLMSSP Challenge rcvd"));
2745 memcpy(ses->server->cryptKey,
2746 SecurityBlob2->Challenge,
2747 CIFS_CRYPTO_KEY_SIZE);
2748 if(SecurityBlob2->NegotiateFlags &
2749 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2750 *pNTLMv2_flag = TRUE;
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;
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 =
2771 (smb_buffer_response) / 2;
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 */
2779 if(ses->serverOS)
2780 kfree(ses->serverOS);
2781 ses->serverOS =
2782 kzalloc(2 * (len + 1), GFP_KERNEL);
2783 cifs_strfromUCS_le(ses->serverOS,
2784 (__le16 *)
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);
2796 if(ses->serverNOS)
2797 kfree(ses->serverNOS);
2798 ses->serverNOS =
2799 kzalloc(2 * (len + 1),
2800 GFP_KERNEL);
2801 cifs_strfromUCS_le(ses->
2802 serverNOS,
2803 (__le16 *)
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) */
2815 if(ses->serverDomain)
2816 kfree(ses->serverDomain);
2817 ses->serverDomain =
2818 kzalloc(2 *
2819 (len +
2821 GFP_KERNEL);
2822 cifs_strfromUCS_le
2823 (ses->serverDomain,
2824 (__le16 *)bcc_ptr,
2825 len, nls_codepage);
2826 bcc_ptr +=
2827 2 * (len + 1);
2828 ses->serverDomain[2*len]
2829 = 0;
2830 ses->serverDomain
2831 [1 + (2 * len)]
2832 = 0;
2833 } /* else no more room so create dummy domain string */
2834 else {
2835 if(ses->serverDomain)
2836 kfree(ses->serverDomain);
2837 ses->serverDomain =
2838 kzalloc(2,
2839 GFP_KERNEL);
2841 } else { /* no room so create dummy domain and NOS string */
2842 if(ses->serverDomain);
2843 kfree(ses->serverDomain);
2844 ses->serverDomain =
2845 kzalloc(2, GFP_KERNEL);
2846 if(ses->serverNOS)
2847 kfree(ses->serverNOS);
2848 ses->serverNOS =
2849 kzalloc(2, GFP_KERNEL);
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)) {
2856 if(ses->serverOS)
2857 kfree(ses->serverOS);
2858 ses->serverOS =
2859 kzalloc(len + 1,
2860 GFP_KERNEL);
2861 strncpy(ses->serverOS,
2862 bcc_ptr, len);
2864 bcc_ptr += len;
2865 bcc_ptr[0] = 0; /* null terminate string */
2866 bcc_ptr++;
2868 len = strnlen(bcc_ptr, 1024);
2869 if(ses->serverNOS)
2870 kfree(ses->serverNOS);
2871 ses->serverNOS =
2872 kzalloc(len + 1,
2873 GFP_KERNEL);
2874 strncpy(ses->serverNOS, bcc_ptr, len);
2875 bcc_ptr += len;
2876 bcc_ptr[0] = 0;
2877 bcc_ptr++;
2879 len = strnlen(bcc_ptr, 1024);
2880 if(ses->serverDomain)
2881 kfree(ses->serverDomain);
2882 ses->serverDomain =
2883 kzalloc(len + 1,
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,
2891 ("Variable field of length %d extends beyond end of smb",
2892 len));
2894 } else {
2895 cERROR(1,
2896 (" Security Blob Length extends beyond end of SMB"));
2898 } else {
2899 cERROR(1, ("No session structure passed in."));
2901 } else {
2902 cERROR(1,
2903 (" Invalid Word count %d:",
2904 smb_buffer_response->WordCount));
2905 rc = -EIO;
2908 if (smb_buffer)
2909 cifs_buf_release(smb_buffer);
2911 return rc;
2913 static int
2914 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2915 char *ntlm_session_key, int ntlmv2_flag,
2916 const struct nls_table *nls_codepage)
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;
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;
2943 smb_buffer_response = smb_buffer;
2944 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2945 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2947 /* send SMBsessionSetup here */
2948 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2949 NULL /* no tCon exists yet */ , 12 /* wct */ );
2951 smb_buffer->Mid = GetNextMid(ses->server);
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);
2958 pSMB->req.hdr.Uid = ses->Suid;
2960 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2961 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
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;
2969 if (ses->capabilities & CAP_STATUS32) {
2970 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2971 capabilities |= CAP_STATUS32;
2973 if (ses->capabilities & CAP_DFS) {
2974 smb_buffer->Flags2 |= SMBFLG2_DFS;
2975 capabilities |= CAP_DFS;
2977 pSMB->req.Capabilities = cpu_to_le32(capabilities);
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;
2993 /* setup pointers to domain name and workstation name */
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;
3002 SecurityBlob->LmChallengeResponse.Length = 0;
3003 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
3004 SecurityBlob->LmChallengeResponse.Buffer = 0;
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;
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 =
3023 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
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);
3035 if (user == NULL) {
3036 SecurityBlob->UserName.Buffer = 0;
3037 SecurityBlob->UserName.Length = 0;
3038 SecurityBlob->UserName.MaximumLength = 0;
3039 } else {
3040 __u16 len =
3041 cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
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);
3054 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
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); */
3062 if ((long) bcc_ptr % 2) {
3063 *bcc_ptr = 0;
3064 bcc_ptr++;
3066 bytes_returned =
3067 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
3068 32, nls_codepage);
3069 bcc_ptr += 2 * bytes_returned;
3070 bytes_returned =
3071 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
3072 nls_codepage);
3073 bcc_ptr += 2 * bytes_returned;
3074 bcc_ptr += 2; /* null term version string */
3075 bytes_returned =
3076 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
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);
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);
3119 /* BB fill in our workstation name if known BB */
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;
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);
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));
3169 cFYI(1,
3170 ("NTLMSSP response to Authenticate "));
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;
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 */
3186 if(ses->serverOS)
3187 kfree(ses->serverOS);
3188 ses->serverOS =
3189 kzalloc(2 * (len + 1), GFP_KERNEL);
3190 cifs_strfromUCS_le(ses->serverOS,
3191 (__le16 *)
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);
3203 if(ses->serverNOS)
3204 kfree(ses->serverNOS);
3205 ses->serverNOS =
3206 kzalloc(2 * (len + 1),
3207 GFP_KERNEL);
3208 cifs_strfromUCS_le(ses->
3209 serverNOS,
3210 (__le16 *)
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) */
3221 if(ses->serverDomain)
3222 kfree(ses->serverDomain);
3223 ses->serverDomain =
3224 kzalloc(2 *
3225 (len +
3227 GFP_KERNEL);
3228 cifs_strfromUCS_le
3229 (ses->
3230 serverDomain,
3231 (__le16 *)
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
3245 len)]
3246 = 0;
3247 } /* else no more room so create dummy domain string */
3248 else {
3249 if(ses->serverDomain)
3250 kfree(ses->serverDomain);
3251 ses->serverDomain = kzalloc(2,GFP_KERNEL);
3253 } else { /* no room so create dummy domain and NOS string */
3254 if(ses->serverDomain)
3255 kfree(ses->serverDomain);
3256 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3257 if(ses->serverNOS)
3258 kfree(ses->serverNOS);
3259 ses->serverNOS = kzalloc(2, GFP_KERNEL);
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)) {
3266 if(ses->serverOS)
3267 kfree(ses->serverOS);
3268 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
3269 strncpy(ses->serverOS,bcc_ptr, len);
3271 bcc_ptr += len;
3272 bcc_ptr[0] = 0; /* null terminate the string */
3273 bcc_ptr++;
3275 len = strnlen(bcc_ptr, 1024);
3276 if(ses->serverNOS)
3277 kfree(ses->serverNOS);
3278 ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
3279 strncpy(ses->serverNOS, bcc_ptr, len);
3280 bcc_ptr += len;
3281 bcc_ptr[0] = 0;
3282 bcc_ptr++;
3284 len = strnlen(bcc_ptr, 1024);
3285 if(ses->serverDomain)
3286 kfree(ses->serverDomain);
3287 ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
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));
3297 } else {
3298 cERROR(1,
3299 (" Security Blob Length extends beyond end of SMB"));
3301 } else {
3302 cERROR(1, ("No session structure passed in."));
3304 } else {
3305 cERROR(1,
3306 (" Invalid Word count %d: ",
3307 smb_buffer_response->WordCount));
3308 rc = -EIO;
3311 if (smb_buffer)
3312 cifs_buf_release(smb_buffer);
3314 return rc;
3318 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3319 const char *tree, struct cifsTconInfo *tcon,
3320 const struct nls_table *nls_codepage)
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;
3331 if (ses == NULL)
3332 return -EIO;
3334 smb_buffer = cifs_buf_get();
3335 if (smb_buffer == NULL) {
3336 return -ENOMEM;
3338 smb_buffer_response = smb_buffer;
3340 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3341 NULL /*no tid */ , 4 /*wct */ );
3343 smb_buffer->Mid = GetNextMid(ses->server);
3344 smb_buffer->Uid = ses->Suid;
3345 pSMB = (TCONX_REQ *) smb_buffer;
3346 pSMBr = (TCONX_RSP *) smb_buffer_response;
3348 pSMB->AndXCommand = 0xFF;
3349 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3350 bcc_ptr = &pSMB->Password[0];
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);
3366 bcc_ptr += CIFS_SESSION_KEY_SIZE;
3367 *bcc_ptr = 0;
3368 bcc_ptr++; /* align */
3371 if(ses->server->secMode &
3372 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3373 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3375 if (ses->capabilities & CAP_STATUS32) {
3376 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3378 if (ses->capabilities & CAP_DFS) {
3379 smb_buffer->Flags2 |= SMBFLG2_DFS;
3381 if (ses->capabilities & CAP_UNICODE) {
3382 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3383 length =
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 */
3388 bcc_ptr += 2; /* skip trailing null */
3389 } else { /* ASCII */
3390 strcpy(bcc_ptr, tree);
3391 bcc_ptr += strlen(tree) + 1;
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);
3400 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
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)) {
3417 kfree(tcon->nativeFileSystem);
3418 tcon->nativeFileSystem =
3419 kzalloc(length + 2, GFP_KERNEL);
3420 cifs_strfromUCS_le(tcon->nativeFileSystem,
3421 (__le16 *) bcc_ptr,
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;
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)) {
3434 kfree(tcon->nativeFileSystem);
3435 tcon->nativeFileSystem =
3436 kzalloc(length + 1, GFP_KERNEL);
3437 strncpy(tcon->nativeFileSystem, bcc_ptr,
3438 length);
3440 /* else do not bother copying these informational fields */
3442 if(smb_buffer_response->WordCount == 3)
3443 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3444 else
3445 tcon->Flags = 0;
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;
3452 if (smb_buffer)
3453 cifs_buf_release(smb_buffer);
3454 return rc;
3458 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3460 int rc = 0;
3461 int xid;
3462 struct cifsSesInfo *ses = NULL;
3463 struct task_struct *cifsd_task;
3465 xid = GetXid();
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;
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"));
3485 if(cifsd_task) {
3486 send_sig(SIGKILL,cifsd_task,1);
3487 wait_for_completion(&cifsd_complete);
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"));
3496 cifs_sb->tcon = NULL;
3497 if (ses)
3498 schedule_timeout_interruptible(msecs_to_jiffies(500));
3499 if (ses)
3500 sesInfoFree(ses);
3502 FreeXid(xid);
3503 return rc; /* BB check if we should always return zero here */
3506 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3507 struct nls_table * nls_info)
3509 int rc = 0;
3510 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3511 int ntlmv2_flag = FALSE;
3512 int first_time = 0;
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;
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);
3531 first_time = 1;
3533 if (!rc) {
3534 pSesInfo->capabilities = pSesInfo->server->capabilities;
3535 if(linuxExtEnabled == 0)
3536 pSesInfo->capabilities &= (~CAP_UNIX);
3537 /* pSesInfo->sequence_number = 0;*/
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));
3542 #ifdef CONFIG_CIFS_EXPERIMENTAL
3543 if(experimEnabled > 1)
3544 rc = CIFS_SessSetup(xid, pSesInfo,
3545 first_time, nls_info);
3546 else
3547 #endif
3548 if (extended_security
3549 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3550 && (pSesInfo->server->secType == NTLMSSP)) {
3551 cFYI(1, ("New style sesssetup"));
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)) {
3559 cFYI(1, ("NTLMSSP sesssetup"));
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);
3576 /* if(first_time)
3577 cifs_calculate_ntlmv2_mac_key(
3578 pSesInfo->server->mac_signing_key,
3579 response, ntlm_session_key, */
3580 kfree(v2_response);
3581 /* BB Put dummy sig in SessSetup PDU? */
3582 } else {
3583 rc = -ENOMEM;
3584 goto ss_err_exit;
3587 } else {
3588 SMBNTencrypt(pSesInfo->password,
3589 pSesInfo->server->cryptKey,
3590 ntlm_session_key);
3592 if(first_time)
3593 cifs_calculate_mac_key(
3594 pSesInfo->server->mac_signing_key,
3595 ntlm_session_key,
3596 pSesInfo->password);
3598 /* for better security the weaker lanman hash not sent
3599 in AuthSessSetup so we no longer calculate it */
3601 rc = CIFSNTLMSSPAuthSessSetup(xid,
3602 pSesInfo,
3603 ntlm_session_key,
3604 ntlmv2_flag,
3605 nls_info);
3607 } else { /* old style NTLM 0.12 session setup */
3608 SMBNTencrypt(pSesInfo->password,
3609 pSesInfo->server->cryptKey,
3610 ntlm_session_key);
3612 if(first_time)
3613 cifs_calculate_mac_key(
3614 pSesInfo->server->mac_signing_key,
3615 ntlm_session_key, pSesInfo->password);
3617 rc = CIFSSessSetup(xid, pSesInfo,
3618 ntlm_session_key, nls_info);
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;
3627 ss_err_exit:
3628 return rc;