4 * Copyright (C) International Business Machines Corp., 2002,2004
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
22 #include <linux/net.h>
23 #include <linux/string.h>
24 #include <linux/list.h>
25 #include <linux/wait.h>
26 #include <linux/version.h>
27 #include <linux/ipv6.h>
28 #include <linux/pagemap.h>
29 #include <linux/ctype.h>
30 #include <linux/utsname.h>
31 #include <linux/mempool.h>
32 #include <asm/uaccess.h>
33 #include <asm/processor.h>
36 #include "cifsproto.h"
37 #include "cifs_unicode.h"
38 #include "cifs_debug.h"
39 #include "cifs_fs_sb.h"
42 #include "rfc1002pdu.h"
45 #define RFC1001_PORT 139
47 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
49 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
51 extern int cifs_inet_pton(int, const char *, void *dst);
53 extern mempool_t *cifs_req_poolp;
61 char *iocharset; /* local code page for mapping to and from Unicode */
62 char source_rfc1001_name[16]; /* netbios name of client */
75 unsigned short int port;
78 static int ipv4_connect(struct sockaddr_in *psin_server,
79 struct socket **csocket,
81 static int ipv6_connect(struct sockaddr_in6 *psin_server,
82 struct socket **csocket);
86 * cifs tcp session reconnection
88 * mark tcp session as reconnecting so temporarily locked
89 * mark all smb sessions as reconnecting for tcp session
90 * reconnect tcp session
91 * wake up waiters on reconnection? - (not needed currently)
95 cifs_reconnect(struct TCP_Server_Info *server)
98 struct list_head *tmp;
99 struct cifsSesInfo *ses;
100 struct cifsTconInfo *tcon;
101 struct mid_q_entry * mid_entry;
103 spin_lock(&GlobalMid_Lock);
104 if(server->tcpStatus == CifsExiting) {
105 /* the demux thread will exit normally
106 next time through the loop */
107 spin_unlock(&GlobalMid_Lock);
110 server->tcpStatus = CifsNeedReconnect;
111 spin_unlock(&GlobalMid_Lock);
114 cFYI(1, ("Reconnecting tcp session "));
116 /* before reconnecting the tcp session, mark the smb session (uid)
117 and the tid bad so they are not used until reconnected */
118 read_lock(&GlobalSMBSeslock);
119 list_for_each(tmp, &GlobalSMBSessionList) {
120 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
122 if (ses->server == server) {
123 ses->status = CifsNeedReconnect;
127 /* else tcp and smb sessions need reconnection */
129 list_for_each(tmp, &GlobalTreeConnectionList) {
130 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
131 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
132 tcon->tidStatus = CifsNeedReconnect;
135 read_unlock(&GlobalSMBSeslock);
136 /* do not want to be sending data on a socket we are freeing */
137 down(&server->tcpSem);
138 if(server->ssocket) {
139 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
140 server->ssocket->flags));
141 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
142 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
143 server->ssocket->flags));
144 sock_release(server->ssocket);
145 server->ssocket = NULL;
148 spin_lock(&GlobalMid_Lock);
149 list_for_each(tmp, &server->pending_mid_q) {
150 mid_entry = list_entry(tmp, struct
154 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
155 /* Mark other intransit requests as needing retry so
156 we do not immediately mark the session bad again
157 (ie after we reconnect below) as they timeout too */
158 mid_entry->midState = MID_RETRY_NEEDED;
162 spin_unlock(&GlobalMid_Lock);
165 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
167 if(server->protocolType == IPV6) {
168 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
170 rc = ipv4_connect(&server->addr.sockAddr,
172 server->workstation_RFC1001_name);
175 set_current_state(TASK_INTERRUPTIBLE);
176 schedule_timeout(3 * HZ);
178 atomic_inc(&tcpSesReconnectCount);
179 spin_lock(&GlobalMid_Lock);
180 if(server->tcpStatus != CifsExiting)
181 server->tcpStatus = CifsGood;
182 spin_unlock(&GlobalMid_Lock);
183 /* atomic_set(&server->inFlight,0);*/
184 wake_up(&server->response_q);
191 cifs_demultiplex_thread(struct TCP_Server_Info *server)
194 unsigned int pdu_length, total_read;
195 struct smb_hdr *smb_buffer = NULL;
196 struct msghdr smb_msg;
198 struct socket *csocket = server->ssocket;
199 struct list_head *tmp;
200 struct cifsSesInfo *ses;
201 struct task_struct *task_to_wake = NULL;
202 struct mid_q_entry *mid_entry;
206 allow_signal(SIGKILL);
207 current->flags |= PF_MEMALLOC;
208 server->tsk = current; /* save process info to wake at shutdown */
209 cFYI(1, ("Demultiplex PID: %d", current->pid));
210 write_lock(&GlobalSMBSeslock);
211 atomic_inc(&tcpSesAllocCount);
212 length = tcpSesAllocCount.counter;
213 write_unlock(&GlobalSMBSeslock);
215 mempool_resize(cifs_req_poolp,
216 length + CIFS_MIN_RCV_POOL,
220 while (server->tcpStatus != CifsExiting) {
221 if (smb_buffer == NULL)
222 smb_buffer = cifs_buf_get();
224 memset(smb_buffer, 0, sizeof (struct smb_hdr));
226 if (smb_buffer == NULL) {
227 cERROR(1,("Can not get memory for SMB response"));
228 set_current_state(TASK_INTERRUPTIBLE);
229 schedule_timeout(HZ * 3); /* give system time to free memory */
232 iov.iov_base = smb_buffer;
233 iov.iov_len = sizeof (struct smb_hdr) - 1;
234 /* 1 byte less above since wct is not always returned in error cases */
235 smb_msg.msg_control = NULL;
236 smb_msg.msg_controllen = 0;
239 kernel_recvmsg(csocket, &smb_msg,
241 sizeof (struct smb_hdr) -
242 1 /* RFC1001 header and SMB header */ ,
243 MSG_PEEK /* flags see socket.h */ );
245 if(server->tcpStatus == CifsExiting) {
247 } else if (server->tcpStatus == CifsNeedReconnect) {
248 cFYI(1,("Reconnecting after server stopped responding"));
249 cifs_reconnect(server);
250 cFYI(1,("call to reconnect done"));
251 csocket = server->ssocket;
253 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
254 set_current_state(TASK_INTERRUPTIBLE);
255 schedule_timeout(1); /* minimum sleep to prevent looping
256 allowing socket to clear and app threads to set
257 tcpStatus CifsNeedReconnect if server hung */
259 } else if (length <= 0) {
260 if(server->tcpStatus == CifsNew) {
261 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
262 /* some servers kill tcp session rather than returning
263 smb negprot error in which case reconnecting here is
264 not going to help - return error to mount */
267 if(length == -EINTR) {
268 cFYI(1,("cifsd thread killed"));
271 cFYI(1,("Reconnecting after unexpected peek error %d",length));
272 cifs_reconnect(server);
273 csocket = server->ssocket;
274 wake_up(&server->response_q);
278 pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
279 /* Ony read pdu_length after below checks for too short (due
280 to e.g. int overflow) and too long ie beyond end of buf */
281 cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
283 temp = (char *) smb_buffer;
285 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
286 iov.iov_base = smb_buffer;
288 length = kernel_recvmsg(csocket, &smb_msg,
290 cFYI(0,("Received 4 byte keep alive packet"));
291 } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
292 iov.iov_base = smb_buffer;
294 length = kernel_recvmsg(csocket, &smb_msg,
296 cFYI(1,("Good RFC 1002 session rsp"));
297 } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
299 /* we get this from Windows 98 instead of error on SMB negprot response */
300 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
301 if(server->tcpStatus == CifsNew) {
302 /* if nack on negprot (rather than
303 ret of smb negprot error) reconnecting
304 not going to help, ret error to mount */
307 /* give server a second to
308 clean up before reconnect attempt */
309 set_current_state(TASK_INTERRUPTIBLE);
310 schedule_timeout(HZ);
311 /* always try 445 first on reconnect
312 since we get NACK on some if we ever
313 connected to port 139 (the NACK is
314 since we do not begin with RFC1001
315 session initialize frame) */
316 server->addr.sockAddr.sin_port = htons(CIFS_PORT);
317 cifs_reconnect(server);
318 csocket = server->ssocket;
319 wake_up(&server->response_q);
322 } else if (temp[0] != (char) 0) {
323 cERROR(1,("Unknown RFC 1002 frame"));
324 cifs_dump_mem(" Received Data: ", temp, length);
325 cifs_reconnect(server);
326 csocket = server->ssocket;
329 if ((length != sizeof (struct smb_hdr) - 1)
331 CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
333 sizeof (struct smb_hdr) - 1)
336 (smb_buffer, smb_buffer->Mid))) {
338 ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
339 length, pdu_length));
340 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
341 /* could we fix this network corruption by finding next
342 smb header (instead of killing the session) and
343 restart reading from next valid SMB found? */
344 cifs_reconnect(server);
345 csocket = server->ssocket;
347 } else { /* length ok */
350 iov.iov_base = smb_buffer;
351 iov.iov_len = pdu_length;
353 total_read < pdu_length;
354 total_read += length) {
355 length = kernel_recvmsg(csocket, &smb_msg,
357 pdu_length - total_read, 0);
360 ("Zero length receive when expecting %d ",
361 pdu_length - total_read));
362 cifs_reconnect(server);
363 csocket = server->ssocket;
369 dump_smb(smb_buffer, length);
371 (smb_buffer, smb_buffer->Mid, total_read)) {
372 cERROR(1, ("Bad SMB Received "));
377 spin_lock(&GlobalMid_Lock);
378 list_for_each(tmp, &server->pending_mid_q) {
379 mid_entry = list_entry(tmp, struct
383 if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
385 (" Mid 0x%x matched - waking up ",mid_entry->mid));
386 task_to_wake = mid_entry->tsk;
387 mid_entry->resp_buf =
389 mid_entry->midState =
390 MID_RESPONSE_RECEIVED;
393 spin_unlock(&GlobalMid_Lock);
395 smb_buffer = NULL; /* will be freed by users thread after he is done */
396 wake_up_process(task_to_wake);
397 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
398 cERROR(1, ("No task to wake, unknown frame rcvd!"));
399 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
404 ("Frame less than four bytes received %d bytes long.",
407 length = kernel_recvmsg(csocket, &smb_msg,
409 length, 0); /* throw away junk frame */
411 (" with junk 0x%x in it ",
412 *(__u32 *) smb_buffer));
416 spin_lock(&GlobalMid_Lock);
417 server->tcpStatus = CifsExiting;
419 atomic_set(&server->inFlight, 0);
420 spin_unlock(&GlobalMid_Lock);
421 /* Although there should not be any requests blocked on
422 this queue it can not hurt to be paranoid and try to wake up requests
423 that may haven been blocked when more than 50 at time were on the wire
424 to the same server - they now will see the session is in exit state
425 and get out of SendReceive. */
426 wake_up_all(&server->request_q);
427 /* give those requests time to exit */
428 set_current_state(TASK_INTERRUPTIBLE);
429 schedule_timeout(HZ/8);
431 if(server->ssocket) {
432 sock_release(csocket);
433 server->ssocket = NULL;
435 if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
436 cifs_buf_release(smb_buffer);
438 read_lock(&GlobalSMBSeslock);
439 if (list_empty(&server->pending_mid_q)) {
440 /* loop through server session structures attached to this and mark them dead */
441 list_for_each(tmp, &GlobalSMBSessionList) {
443 list_entry(tmp, struct cifsSesInfo,
445 if (ses->server == server) {
446 ses->status = CifsExiting;
450 read_unlock(&GlobalSMBSeslock);
452 spin_lock(&GlobalMid_Lock);
453 list_for_each(tmp, &server->pending_mid_q) {
454 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
455 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
457 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
458 task_to_wake = mid_entry->tsk;
460 wake_up_process(task_to_wake);
464 spin_unlock(&GlobalMid_Lock);
465 read_unlock(&GlobalSMBSeslock);
466 set_current_state(TASK_INTERRUPTIBLE);
467 /* 1/8th of sec is more than enough time for them to exit */
468 schedule_timeout(HZ/8);
471 if (list_empty(&server->pending_mid_q)) {
472 /* mpx threads have not exited yet give them
473 at least the smb send timeout time for long ops */
474 cFYI(1, ("Wait for exit from demultiplex thread"));
475 set_current_state(TASK_INTERRUPTIBLE);
476 schedule_timeout(46 * HZ);
477 /* if threads still have not exited they are probably never
478 coming home not much else we can do but free the memory */
482 write_lock(&GlobalSMBSeslock);
483 atomic_dec(&tcpSesAllocCount);
484 length = tcpSesAllocCount.counter;
485 write_unlock(&GlobalSMBSeslock);
487 mempool_resize(cifs_req_poolp,
488 length + CIFS_MIN_RCV_POOL,
492 set_current_state(TASK_INTERRUPTIBLE);
493 schedule_timeout(HZ/4);
498 cifs_kcalloc(size_t size, int type)
501 addr = kmalloc(size, type);
503 memset(addr, 0, size);
508 cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
512 unsigned int temp_len, i, j;
518 memset(vol->source_rfc1001_name,0x20,15);
519 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
520 /* does not have to be a perfect mapping since the field is
521 informational, only used for servers that do not support
522 port 445 and it can be overridden at mount time */
523 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
525 vol->source_rfc1001_name[15] = 0;
527 vol->linux_uid = current->uid; /* current->euid instead? */
528 vol->linux_gid = current->gid;
529 vol->dir_mode = S_IRWXUGO;
530 /* 2767 perms indicate mandatory locking support */
531 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
533 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
539 if(strncmp(options,"sep=",4) == 0) {
540 if(options[4] != 0) {
541 separator[0] = options[4];
544 cFYI(1,("Null separator not allowed"));
548 while ((data = strsep(&options, separator)) != NULL) {
551 if ((value = strchr(data, '=')) != NULL)
553 if (strnicmp(data, "user", 4) == 0) {
554 if (!value || !*value) {
556 "CIFS: invalid or missing username\n");
557 return 1; /* needs_arg; */
559 if (strnlen(value, 200) < 200) {
560 vol->username = value;
562 printk(KERN_WARNING "CIFS: username too long\n");
565 } else if (strnicmp(data, "pass", 4) == 0) {
566 if (!value || !*value) {
567 vol->password = NULL;
570 temp_len = strlen(value);
571 /* removed password length check, NTLM passwords
572 can be arbitrarily long */
574 /* if comma in password, the string will be
575 prematurely null terminated. Commas in password are
576 specified across the cifs mount interface by a double
577 comma ie ,, and a comma used as in other cases ie ','
578 as a parameter delimiter/separator is single and due
579 to the strsep above is temporarily zeroed. */
581 /* NB: password legally can have multiple commas and
582 the only illegal character in a password is null */
584 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
586 value[temp_len] = separator[0];
587 temp_len+=2; /* move after the second comma */
588 while(value[temp_len] != 0) {
589 if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
590 /* single comma indicating start of next parm */
595 if(value[temp_len] == 0) {
599 /* move options to point to start of next parm */
600 options = value + temp_len + 1;
602 /* go from value to (value + temp_len) condensing double commas to singles */
603 vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
604 for(i=0,j=0;i<temp_len;i++,j++) {
605 vol->password[j] = value[i];
606 if(value[i] == separator[0] && value[i+1] == separator[0]) {
607 /* skip second comma */
611 /* value[temp_len] is zeroed above so
612 vol->password[temp_len] guaranteed to be null */
614 vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
615 strcpy(vol->password, value);
617 } else if (strnicmp(data, "ip", 2) == 0) {
618 if (!value || !*value) {
620 } else if (strnlen(value, 35) < 35) {
623 printk(KERN_WARNING "CIFS: ip address too long\n");
626 } else if ((strnicmp(data, "unc", 3) == 0)
627 || (strnicmp(data, "target", 6) == 0)
628 || (strnicmp(data, "path", 4) == 0)) {
629 if (!value || !*value) {
631 "CIFS: invalid path to network resource\n");
632 return 1; /* needs_arg; */
634 if ((temp_len = strnlen(value, 300)) < 300) {
635 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
638 strcpy(vol->UNC,value);
639 if (strncmp(vol->UNC, "//", 2) == 0) {
642 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
644 "CIFS: UNC Path does not begin with // or \\\\ \n");
648 printk(KERN_WARNING "CIFS: UNC name too long\n");
651 } else if ((strnicmp(data, "domain", 3) == 0)
652 || (strnicmp(data, "workgroup", 5) == 0)) {
653 if (!value || !*value) {
654 printk(KERN_WARNING "CIFS: invalid domain name\n");
655 return 1; /* needs_arg; */
657 /* BB are there cases in which a comma can be valid in
658 a domain name and need special handling? */
659 if (strnlen(value, 65) < 65) {
660 vol->domainname = value;
661 cFYI(1, ("Domain name set"));
663 printk(KERN_WARNING "CIFS: domain name too long\n");
666 } else if (strnicmp(data, "iocharset", 9) == 0) {
667 if (!value || !*value) {
668 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
669 return 1; /* needs_arg; */
671 if (strnlen(value, 65) < 65) {
672 if(strnicmp(value,"default",7))
673 vol->iocharset = value;
674 /* if iocharset not set load_nls_default used by caller */
675 cFYI(1, ("iocharset set to %s",value));
677 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
680 } else if (strnicmp(data, "uid", 3) == 0) {
681 if (value && *value) {
683 simple_strtoul(value, &value, 0);
685 } else if (strnicmp(data, "gid", 3) == 0) {
686 if (value && *value) {
688 simple_strtoul(value, &value, 0);
690 } else if (strnicmp(data, "file_mode", 4) == 0) {
691 if (value && *value) {
693 simple_strtoul(value, &value, 0);
695 } else if (strnicmp(data, "dir_mode", 3) == 0) {
696 if (value && *value) {
698 simple_strtoul(value, &value, 0);
700 } else if (strnicmp(data, "port", 4) == 0) {
701 if (value && *value) {
703 simple_strtoul(value, &value, 0);
705 } else if (strnicmp(data, "rsize", 5) == 0) {
706 if (value && *value) {
708 simple_strtoul(value, &value, 0);
710 } else if (strnicmp(data, "wsize", 5) == 0) {
711 if (value && *value) {
713 simple_strtoul(value, &value, 0);
715 } else if (strnicmp(data, "sockopt", 5) == 0) {
716 if (value && *value) {
718 simple_strtoul(value, &value, 0);
720 } else if (strnicmp(data, "netbiosname", 4) == 0) {
721 if (!value || !*value || (*value == ' ')) {
722 cFYI(1,("invalid (empty) netbiosname specified"));
724 memset(vol->source_rfc1001_name,0x20,15);
726 /* BB are there cases in which a comma can be
727 valid in this workstation netbios name (and need
728 special handling)? */
730 /* We do not uppercase netbiosname for user */
734 vol->source_rfc1001_name[i] = value[i];
736 /* The string has 16th byte zero still from
737 set at top of the function */
738 if((i==15) && (value[i] != 0))
739 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
741 } else if (strnicmp(data, "credentials", 4) == 0) {
743 } else if (strnicmp(data, "version", 3) == 0) {
745 } else if (strnicmp(data, "rw", 2) == 0) {
747 } else if ((strnicmp(data, "suid", 4) == 0) ||
748 (strnicmp(data, "nosuid", 6) == 0) ||
749 (strnicmp(data, "exec", 4) == 0) ||
750 (strnicmp(data, "noexec", 6) == 0) ||
751 (strnicmp(data, "nodev", 5) == 0) ||
752 (strnicmp(data, "noauto", 6) == 0) ||
753 (strnicmp(data, "dev", 3) == 0)) {
754 /* The mount tool or mount.cifs helper (if present)
755 uses these opts to set flags, and the flags are read
756 by the kernel vfs layer before we get here (ie
757 before read super) so there is no point trying to
758 parse these options again and set anything and it
759 is ok to just ignore them */
761 } else if (strnicmp(data, "ro", 2) == 0) {
763 } else if (strnicmp(data, "hard", 4) == 0) {
765 } else if (strnicmp(data, "soft", 4) == 0) {
767 } else if (strnicmp(data, "perm", 4) == 0) {
769 } else if (strnicmp(data, "noperm", 6) == 0) {
771 } else if (strnicmp(data, "setuids", 7) == 0) {
773 } else if (strnicmp(data, "nosetuids", 9) == 0) {
775 } else if (strnicmp(data, "nohard", 6) == 0) {
777 } else if (strnicmp(data, "nosoft", 6) == 0) {
779 } else if (strnicmp(data, "nointr", 6) == 0) {
781 } else if (strnicmp(data, "intr", 4) == 0) {
783 } else if (strnicmp(data, "noac", 4) == 0) {
784 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
786 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
788 if (vol->UNC == NULL) {
789 if(devname == NULL) {
790 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
793 if ((temp_len = strnlen(devname, 300)) < 300) {
794 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
797 strcpy(vol->UNC,devname);
798 if (strncmp(vol->UNC, "//", 2) == 0) {
801 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
802 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
806 printk(KERN_WARNING "CIFS: UNC name too long\n");
811 vol->UNCip = &vol->UNC[2];
816 static struct cifsSesInfo *
817 cifs_find_tcp_session(struct in_addr * target_ip_addr,
818 struct in6_addr *target_ip6_addr,
819 char *userName, struct TCP_Server_Info **psrvTcp)
821 struct list_head *tmp;
822 struct cifsSesInfo *ses;
824 read_lock(&GlobalSMBSeslock);
826 list_for_each(tmp, &GlobalSMBSessionList) {
827 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
829 if((target_ip_addr &&
830 (ses->server->addr.sockAddr.sin_addr.s_addr
831 == target_ip_addr->s_addr)) || (target_ip6_addr
832 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
833 target_ip6_addr,sizeof(*target_ip6_addr)))){
834 /* BB lock server and tcp session and increment use count here?? */
835 *psrvTcp = ses->server; /* found a match on the TCP session */
836 /* BB check if reconnection needed */
838 (ses->userName, userName,
839 MAX_USERNAME_SIZE) == 0){
840 read_unlock(&GlobalSMBSeslock);
841 return ses; /* found exact match on both tcp and SMB sessions */
845 /* else tcp and smb sessions need reconnection */
847 read_unlock(&GlobalSMBSeslock);
851 static struct cifsTconInfo *
852 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
854 struct list_head *tmp;
855 struct cifsTconInfo *tcon;
857 read_lock(&GlobalSMBSeslock);
858 list_for_each(tmp, &GlobalTreeConnectionList) {
859 cFYI(1, ("Next tcon - "));
860 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
862 if (tcon->ses->server) {
864 (" old ip addr: %x == new ip %x ?",
865 tcon->ses->server->addr.sockAddr.sin_addr.
866 s_addr, new_target_ip_addr));
867 if (tcon->ses->server->addr.sockAddr.sin_addr.
868 s_addr == new_target_ip_addr) {
869 /* BB lock tcon and server and tcp session and increment use count here? */
870 /* found a match on the TCP session */
871 /* BB check if reconnection needed */
872 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
873 tcon->treeName, uncName));
875 (tcon->treeName, uncName,
876 MAX_TREE_SIZE) == 0) {
878 ("Matched UNC, old user: %s == new: %s ?",
879 tcon->treeName, uncName));
881 (tcon->ses->userName,
883 MAX_USERNAME_SIZE) == 0) {
884 read_unlock(&GlobalSMBSeslock);
885 return tcon;/* also matched user (smb session)*/
892 read_unlock(&GlobalSMBSeslock);
897 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
898 const char *old_path, const struct nls_table *nls_codepage)
900 unsigned char *referrals = NULL;
901 unsigned int num_referrals;
904 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
905 &num_referrals, &referrals);
907 /* BB Add in code to: if valid refrl, if not ip address contact
908 the helper that resolves tcp names, mount to it, try to
909 tcon to it unmount it if fail */
918 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
919 const char *old_path, const struct nls_table *nls_codepage,
920 unsigned int *pnum_referrals, unsigned char ** preferrals)
927 if (pSesInfo->ipc_tid == 0) {
928 temp_unc = kmalloc(2 /* for slashes */ +
929 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
930 + 1 + 4 /* slash IPC$ */ + 2,
932 if (temp_unc == NULL)
936 strcpy(temp_unc + 2, pSesInfo->serverName);
937 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
938 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
940 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
944 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
945 pnum_referrals, nls_codepage);
950 /* See RFC1001 section 14 on representation of Netbios names */
951 static void rfc1002mangle(char * target,char * source, unsigned int length)
955 for(i=0,j=0;i<(length);i++) {
956 /* mask a nibble at a time and encode */
957 target[j] = 'A' + (0x0F & (source[i] >> 4));
958 target[j+1] = 'A' + (0x0F & source[i]);
966 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
971 __be16 orig_port = 0;
973 if(*csocket == NULL) {
974 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
976 cERROR(1, ("Error %d creating socket",rc));
980 /* BB other socket options to set KEEPALIVE, NODELAY? */
981 cFYI(1,("Socket created"));
982 (*csocket)->sk->sk_allocation = GFP_NOFS;
986 psin_server->sin_family = AF_INET;
987 if(psin_server->sin_port) { /* user overrode default port */
988 rc = (*csocket)->ops->connect(*csocket,
989 (struct sockaddr *) psin_server,
990 sizeof (struct sockaddr_in),0);
996 /* save original port so we can retry user specified port
997 later if fall back ports fail this time */
998 orig_port = psin_server->sin_port;
1000 /* do not retry on the same port we just failed on */
1001 if(psin_server->sin_port != htons(CIFS_PORT)) {
1002 psin_server->sin_port = htons(CIFS_PORT);
1004 rc = (*csocket)->ops->connect(*csocket,
1005 (struct sockaddr *) psin_server,
1006 sizeof (struct sockaddr_in),0);
1012 psin_server->sin_port = htons(RFC1001_PORT);
1013 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1014 psin_server, sizeof (struct sockaddr_in),0);
1019 /* give up here - unless we want to retry on different
1020 protocol families some day */
1023 psin_server->sin_port = orig_port;
1024 cFYI(1,("Error %d connecting to server via ipv4",rc));
1025 sock_release(*csocket);
1029 /* Eventually check for other socket options to change from
1030 the default. sock_setsockopt not used because it expects
1031 user space buffer */
1032 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1034 /* send RFC1001 sessinit */
1036 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1037 /* some servers require RFC1001 sessinit before sending
1038 negprot - BB check reconnection in case where second
1039 sessinit is sent but no second negprot */
1040 struct rfc1002_session_packet * ses_init_buf;
1041 struct smb_hdr * smb_buf;
1042 ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1044 ses_init_buf->trailer.session_req.called_len = 32;
1045 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1046 DEFAULT_CIFS_CALLED_NAME,16);
1047 ses_init_buf->trailer.session_req.calling_len = 32;
1048 /* calling name ends in null (byte 16) from old smb
1050 if(netbios_name && (netbios_name[0] !=0)) {
1051 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1054 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1055 "LINUX_CIFS_CLNT",16);
1057 ses_init_buf->trailer.session_req.scope1 = 0;
1058 ses_init_buf->trailer.session_req.scope2 = 0;
1059 smb_buf = (struct smb_hdr *)ses_init_buf;
1060 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1061 smb_buf->smb_buf_length = 0x81000044;
1062 rc = smb_send(*csocket, smb_buf, 0x44,
1063 (struct sockaddr *)psin_server);
1064 kfree(ses_init_buf);
1066 /* else the negprot may still work without this
1067 even though malloc failed */
1075 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1079 __be16 orig_port = 0;
1081 if(*csocket == NULL) {
1082 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1084 cERROR(1, ("Error %d creating ipv6 socket",rc));
1088 /* BB other socket options to set KEEPALIVE, NODELAY? */
1089 cFYI(1,("ipv6 Socket created"));
1090 (*csocket)->sk->sk_allocation = GFP_NOFS;
1094 psin_server->sin6_family = AF_INET6;
1096 if(psin_server->sin6_port) { /* user overrode default port */
1097 rc = (*csocket)->ops->connect(*csocket,
1098 (struct sockaddr *) psin_server,
1099 sizeof (struct sockaddr_in6),0);
1105 /* save original port so we can retry user specified port
1106 later if fall back ports fail this time */
1108 orig_port = psin_server->sin6_port;
1109 /* do not retry on the same port we just failed on */
1110 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1111 psin_server->sin6_port = htons(CIFS_PORT);
1113 rc = (*csocket)->ops->connect(*csocket,
1114 (struct sockaddr *) psin_server,
1115 sizeof (struct sockaddr_in6),0);
1121 psin_server->sin6_port = htons(RFC1001_PORT);
1122 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1123 psin_server, sizeof (struct sockaddr_in6),0);
1128 /* give up here - unless we want to retry on different
1129 protocol families some day */
1132 psin_server->sin6_port = orig_port;
1133 cFYI(1,("Error %d connecting to server via ipv6",rc));
1134 sock_release(*csocket);
1138 /* Eventually check for other socket options to change from
1139 the default. sock_setsockopt not used because it expects
1140 user space buffer */
1141 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1147 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1148 char *mount_data, const char *devname)
1152 int address_type = AF_INET;
1153 struct socket *csocket = NULL;
1154 struct sockaddr_in sin_server;
1155 struct sockaddr_in6 sin_server6;
1156 struct smb_vol volume_info;
1157 struct cifsSesInfo *pSesInfo = NULL;
1158 struct cifsSesInfo *existingCifsSes = NULL;
1159 struct cifsTconInfo *tcon = NULL;
1160 struct TCP_Server_Info *srvTcp = NULL;
1164 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1166 memset(&volume_info,0,sizeof(struct smb_vol));
1167 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1169 kfree(volume_info.UNC);
1170 if(volume_info.password)
1171 kfree(volume_info.password);
1176 if (volume_info.username) {
1177 cFYI(1, ("Username: %s ", volume_info.username));
1180 cifserror("No username specified ");
1181 /* In userspace mount helper we can get user name from alternate
1182 locations such as env variables and files on disk */
1184 kfree(volume_info.UNC);
1185 if(volume_info.password)
1186 kfree(volume_info.password);
1191 if (volume_info.UNCip && volume_info.UNC) {
1192 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1195 /* not ipv4 address, try ipv6 */
1196 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1198 address_type = AF_INET6;
1200 address_type = AF_INET;
1204 /* we failed translating address */
1206 kfree(volume_info.UNC);
1207 if(volume_info.password)
1208 kfree(volume_info.password);
1213 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1216 } else if (volume_info.UNCip){
1217 /* BB using ip addr as server name connect to the DFS root below */
1218 cERROR(1,("Connecting to DFS root not implemented yet"));
1220 kfree(volume_info.UNC);
1221 if(volume_info.password)
1222 kfree(volume_info.password);
1225 } else /* which servers DFS root would we conect to */ {
1227 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1229 kfree(volume_info.UNC);
1230 if(volume_info.password)
1231 kfree(volume_info.password);
1236 /* this is needed for ASCII cp to Unicode converts */
1237 if(volume_info.iocharset == NULL) {
1238 cifs_sb->local_nls = load_nls_default();
1239 /* load_nls_default can not return null */
1241 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1242 if(cifs_sb->local_nls == NULL) {
1243 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1245 kfree(volume_info.UNC);
1246 if(volume_info.password)
1247 kfree(volume_info.password);
1253 if(address_type == AF_INET)
1254 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1255 NULL /* no ipv6 addr */,
1256 volume_info.username, &srvTcp);
1257 else if(address_type == AF_INET6)
1258 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1259 &sin_server6.sin6_addr,
1260 volume_info.username, &srvTcp);
1263 kfree(volume_info.UNC);
1264 if(volume_info.password)
1265 kfree(volume_info.password);
1272 cFYI(1, ("Existing tcp session with server found "));
1273 } else { /* create socket */
1274 if(volume_info.port)
1275 sin_server.sin_port = htons(volume_info.port);
1277 sin_server.sin_port = 0;
1278 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1281 ("Error connecting to IPv4 socket. Aborting operation"));
1283 sock_release(csocket);
1285 kfree(volume_info.UNC);
1286 if(volume_info.password)
1287 kfree(volume_info.password);
1292 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1293 if (srvTcp == NULL) {
1295 sock_release(csocket);
1297 kfree(volume_info.UNC);
1298 if(volume_info.password)
1299 kfree(volume_info.password);
1303 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1304 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1305 atomic_set(&srvTcp->inFlight,0);
1306 /* BB Add code for ipv6 case too */
1307 srvTcp->ssocket = csocket;
1308 srvTcp->protocolType = IPV4;
1309 init_waitqueue_head(&srvTcp->response_q);
1310 init_waitqueue_head(&srvTcp->request_q);
1311 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1312 /* at this point we are the only ones with the pointer
1313 to the struct since the kernel thread not created yet
1314 so no need to spinlock this init of tcpStatus */
1315 srvTcp->tcpStatus = CifsNew;
1316 init_MUTEX(&srvTcp->tcpSem);
1317 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1318 CLONE_FS | CLONE_FILES | CLONE_VM);
1321 sock_release(csocket);
1323 kfree(volume_info.UNC);
1324 if(volume_info.password)
1325 kfree(volume_info.password);
1330 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1334 if (existingCifsSes) {
1335 pSesInfo = existingCifsSes;
1336 cFYI(1, ("Existing smb sess found "));
1337 if(volume_info.password)
1338 kfree(volume_info.password);
1339 /* volume_info.UNC freed at end of function */
1341 cFYI(1, ("Existing smb sess not found "));
1342 pSesInfo = sesInfoAlloc();
1343 if (pSesInfo == NULL)
1346 pSesInfo->server = srvTcp;
1347 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1348 NIPQUAD(sin_server.sin_addr.s_addr));
1352 /* volume_info.password freed at unmount */
1353 if (volume_info.password)
1354 pSesInfo->password = volume_info.password;
1355 if (volume_info.username)
1356 strncpy(pSesInfo->userName,
1357 volume_info.username,MAX_USERNAME_SIZE);
1358 if (volume_info.domainname)
1359 strncpy(pSesInfo->domainName,
1360 volume_info.domainname,MAX_USERNAME_SIZE);
1361 pSesInfo->linux_uid = volume_info.linux_uid;
1362 down(&pSesInfo->sesSem);
1363 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1364 up(&pSesInfo->sesSem);
1366 atomic_inc(&srvTcp->socketUseCount);
1368 if(volume_info.password)
1369 kfree(volume_info.password);
1372 /* search for existing tcon to this server share */
1374 if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
1375 cifs_sb->rsize = volume_info.rsize;
1377 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1378 if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
1379 cifs_sb->wsize = volume_info.wsize;
1381 cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1382 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1383 cifs_sb->rsize = PAGE_CACHE_SIZE;
1384 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1386 cifs_sb->mnt_uid = volume_info.linux_uid;
1387 cifs_sb->mnt_gid = volume_info.linux_gid;
1388 cifs_sb->mnt_file_mode = volume_info.file_mode;
1389 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1390 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1392 if(volume_info.noperm)
1393 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1394 if(volume_info.setuids)
1395 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1398 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1399 volume_info.username);
1401 cFYI(1, ("Found match on UNC path "));
1402 /* we can have only one retry value for a connection
1403 to a share so for resources mounted more than once
1404 to the same server share the last value passed in
1405 for the retry flag is used */
1406 tcon->retry = volume_info.retry;
1408 tcon = tconInfoAlloc();
1412 /* check for null share name ie connect to dfs root */
1414 /* BB check if this works for exactly length three strings */
1415 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1416 && (strchr(volume_info.UNC + 3, '/') ==
1418 rc = connect_to_dfs_path(xid,
1424 kfree(volume_info.UNC);
1428 rc = CIFSTCon(xid, pSesInfo,
1430 tcon, cifs_sb->local_nls);
1431 cFYI(1, ("CIFS Tcon rc = %d", rc));
1434 atomic_inc(&pSesInfo->inUse);
1435 tcon->retry = volume_info.retry;
1441 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1442 sb->s_maxbytes = (u64) 1 << 63;
1444 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1447 /* on error free sesinfo and tcon struct if needed */
1449 /* if session setup failed, use count is zero but
1450 we still need to free cifsd thread */
1451 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1452 spin_lock(&GlobalMid_Lock);
1453 srvTcp->tcpStatus = CifsExiting;
1454 spin_unlock(&GlobalMid_Lock);
1456 send_sig(SIGKILL,srvTcp->tsk,1);
1458 /* If find_unc succeeded then rc == 0 so we can not end */
1459 if (tcon) /* up accidently freeing someone elses tcon struct */
1461 if (existingCifsSes == 0) {
1463 if ((pSesInfo->server) &&
1464 (pSesInfo->status == CifsGood)) {
1466 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1467 /* if the socketUseCount is now zero */
1468 if((temp_rc == -ESHUTDOWN) &&
1469 (pSesInfo->server->tsk))
1470 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1472 cFYI(1, ("No session or bad tcon"));
1473 sesInfoFree(pSesInfo);
1474 /* pSesInfo = NULL; */
1478 atomic_inc(&tcon->useCount);
1479 cifs_sb->tcon = tcon;
1480 tcon->ses = pSesInfo;
1482 /* do not care if following two calls succeed - informational only */
1483 CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
1484 CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
1485 if (tcon->ses->capabilities & CAP_UNIX)
1486 CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
1489 /* volume_info.password is freed above when existing session found
1490 (in which case it is not needed anymore) but when new sesion is created
1491 the password ptr is put in the new session structure (in which case the
1492 password will be freed at unmount time) */
1494 kfree(volume_info.UNC);
1500 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1501 char session_key[CIFS_SESSION_KEY_SIZE],
1502 const struct nls_table *nls_codepage)
1504 struct smb_hdr *smb_buffer;
1505 struct smb_hdr *smb_buffer_response;
1506 SESSION_SETUP_ANDX *pSMB;
1507 SESSION_SETUP_ANDX *pSMBr;
1512 int remaining_words = 0;
1513 int bytes_returned = 0;
1518 cFYI(1, ("In sesssetup "));
1521 user = ses->userName;
1522 domain = ses->domainName;
1523 smb_buffer = cifs_buf_get();
1524 if (smb_buffer == 0) {
1527 smb_buffer_response = smb_buffer;
1528 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1530 /* send SMBsessionSetup here */
1531 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1532 NULL /* no tCon exists yet */ , 13 /* wct */ );
1534 pSMB->req_no_secext.AndXCommand = 0xFF;
1535 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1536 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1538 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1539 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1541 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
1542 if (ses->capabilities & CAP_UNICODE) {
1543 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1544 capabilities |= CAP_UNICODE;
1546 if (ses->capabilities & CAP_STATUS32) {
1547 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1548 capabilities |= CAP_STATUS32;
1550 if (ses->capabilities & CAP_DFS) {
1551 smb_buffer->Flags2 |= SMBFLG2_DFS;
1552 capabilities |= CAP_DFS;
1554 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1555 /* pSMB->req_no_secext.CaseInsensitivePasswordLength =
1556 CIFS_SESSION_KEY_SIZE; */
1557 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
1558 pSMB->req_no_secext.CaseSensitivePasswordLength =
1559 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1560 bcc_ptr = pByteArea(smb_buffer);
1561 /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
1562 bcc_ptr += CIFS_SESSION_KEY_SIZE; */
1563 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1564 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1566 if (ses->capabilities & CAP_UNICODE) {
1567 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1572 bytes_returned = 0; /* skill null user */
1575 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1577 bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
1578 bcc_ptr += 2; /* trailing null */
1581 cifs_strtoUCS((wchar_t *) bcc_ptr,
1582 "CIFS_LINUX_DOM", 32, nls_codepage);
1585 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1587 bcc_ptr += 2 * bytes_returned;
1590 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1592 bcc_ptr += 2 * bytes_returned;
1594 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
1596 bcc_ptr += 2 * bytes_returned;
1599 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1601 bcc_ptr += 2 * bytes_returned;
1605 strncpy(bcc_ptr, user, 200);
1606 bcc_ptr += strnlen(user, 200);
1610 if (domain == NULL) {
1611 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1612 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1614 strncpy(bcc_ptr, domain, 64);
1615 bcc_ptr += strnlen(domain, 64);
1619 strcpy(bcc_ptr, "Linux version ");
1620 bcc_ptr += strlen("Linux version ");
1621 strcpy(bcc_ptr, UTS_RELEASE);
1622 bcc_ptr += strlen(UTS_RELEASE) + 1;
1623 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1624 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1626 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1627 smb_buffer->smb_buf_length += count;
1628 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1630 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1631 &bytes_returned, 1);
1633 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1634 } else if ((smb_buffer_response->WordCount == 3)
1635 || (smb_buffer_response->WordCount == 4)) {
1636 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1637 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1638 if (action & GUEST_LOGIN)
1639 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1640 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1641 cFYI(1, ("UID = %d ", ses->Suid));
1642 /* response can have either 3 or 4 word count - Samba sends 3 */
1643 bcc_ptr = pByteArea(smb_buffer_response);
1644 if ((pSMBr->resp.hdr.WordCount == 3)
1645 || ((pSMBr->resp.hdr.WordCount == 4)
1646 && (blob_len < pSMBr->resp.ByteCount))) {
1647 if (pSMBr->resp.hdr.WordCount == 4)
1648 bcc_ptr += blob_len;
1650 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1651 if ((long) (bcc_ptr) % 2) {
1653 (BCC(smb_buffer_response) - 1) /2;
1654 bcc_ptr++; /* Unicode strings must be word aligned */
1657 BCC(smb_buffer_response) / 2;
1660 UniStrnlen((wchar_t *) bcc_ptr,
1661 remaining_words - 1);
1662 /* We look for obvious messed up bcc or strings in response so we do not go off
1663 the end since (at least) WIN2K and Windows XP have a major bug in not null
1664 terminating last Unicode string in response */
1665 ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1666 cifs_strfromUCS_le(ses->serverOS,
1667 (wchar_t *)bcc_ptr, len,nls_codepage);
1668 bcc_ptr += 2 * (len + 1);
1669 remaining_words -= len + 1;
1670 ses->serverOS[2 * len] = 0;
1671 ses->serverOS[1 + (2 * len)] = 0;
1672 if (remaining_words > 0) {
1673 len = UniStrnlen((wchar_t *)bcc_ptr,
1675 ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
1676 cifs_strfromUCS_le(ses->serverNOS,
1677 (wchar_t *)bcc_ptr,len,nls_codepage);
1678 bcc_ptr += 2 * (len + 1);
1679 ses->serverNOS[2 * len] = 0;
1680 ses->serverNOS[1 + (2 * len)] = 0;
1681 remaining_words -= len + 1;
1682 if (remaining_words > 0) {
1683 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1684 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1686 cifs_kcalloc(2*(len+1),GFP_KERNEL);
1687 cifs_strfromUCS_le(ses->serverDomain,
1688 (wchar_t *)bcc_ptr,len,nls_codepage);
1689 bcc_ptr += 2 * (len + 1);
1690 ses->serverDomain[2*len] = 0;
1691 ses->serverDomain[1+(2*len)] = 0;
1692 } /* else no more room so create dummy domain string */
1697 } else { /* no room so create dummy domain and NOS string */
1699 cifs_kcalloc(2, GFP_KERNEL);
1701 cifs_kcalloc(2, GFP_KERNEL);
1703 } else { /* ASCII */
1704 len = strnlen(bcc_ptr, 1024);
1705 if (((long) bcc_ptr + len) - (long)
1706 pByteArea(smb_buffer_response)
1707 <= BCC(smb_buffer_response)) {
1708 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1709 strncpy(ses->serverOS,bcc_ptr, len);
1712 bcc_ptr[0] = 0; /* null terminate the string */
1715 len = strnlen(bcc_ptr, 1024);
1716 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1717 strncpy(ses->serverNOS, bcc_ptr, len);
1722 len = strnlen(bcc_ptr, 1024);
1723 ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
1724 strncpy(ses->serverDomain, bcc_ptr, len);
1730 ("Variable field of length %d extends beyond end of smb ",
1735 (" Security Blob Length extends beyond end of SMB"));
1739 (" Invalid Word count %d: ",
1740 smb_buffer_response->WordCount));
1745 cifs_buf_release(smb_buffer);
1751 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1752 char *SecurityBlob,int SecurityBlobLength,
1753 const struct nls_table *nls_codepage)
1755 struct smb_hdr *smb_buffer;
1756 struct smb_hdr *smb_buffer_response;
1757 SESSION_SETUP_ANDX *pSMB;
1758 SESSION_SETUP_ANDX *pSMBr;
1763 int remaining_words = 0;
1764 int bytes_returned = 0;
1769 cFYI(1, ("In spnego sesssetup "));
1772 user = ses->userName;
1773 domain = ses->domainName;
1775 smb_buffer = cifs_buf_get();
1776 if (smb_buffer == 0) {
1779 smb_buffer_response = smb_buffer;
1780 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1782 /* send SMBsessionSetup here */
1783 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1784 NULL /* no tCon exists yet */ , 12 /* wct */ );
1785 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1786 pSMB->req.AndXCommand = 0xFF;
1787 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1788 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1790 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1791 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1793 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1794 CAP_EXTENDED_SECURITY;
1795 if (ses->capabilities & CAP_UNICODE) {
1796 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1797 capabilities |= CAP_UNICODE;
1799 if (ses->capabilities & CAP_STATUS32) {
1800 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1801 capabilities |= CAP_STATUS32;
1803 if (ses->capabilities & CAP_DFS) {
1804 smb_buffer->Flags2 |= SMBFLG2_DFS;
1805 capabilities |= CAP_DFS;
1807 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1809 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1810 bcc_ptr = pByteArea(smb_buffer);
1811 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1812 bcc_ptr += SecurityBlobLength;
1814 if (ses->capabilities & CAP_UNICODE) {
1815 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1820 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1821 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1822 bcc_ptr += 2; /* trailing null */
1825 cifs_strtoUCS((wchar_t *) bcc_ptr,
1826 "CIFS_LINUX_DOM", 32, nls_codepage);
1829 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1831 bcc_ptr += 2 * bytes_returned;
1834 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1836 bcc_ptr += 2 * bytes_returned;
1838 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
1840 bcc_ptr += 2 * bytes_returned;
1843 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1845 bcc_ptr += 2 * bytes_returned;
1848 strncpy(bcc_ptr, user, 200);
1849 bcc_ptr += strnlen(user, 200);
1852 if (domain == NULL) {
1853 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1854 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1856 strncpy(bcc_ptr, domain, 64);
1857 bcc_ptr += strnlen(domain, 64);
1861 strcpy(bcc_ptr, "Linux version ");
1862 bcc_ptr += strlen("Linux version ");
1863 strcpy(bcc_ptr, UTS_RELEASE);
1864 bcc_ptr += strlen(UTS_RELEASE) + 1;
1865 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1866 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1868 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1869 smb_buffer->smb_buf_length += count;
1870 pSMB->req.ByteCount = cpu_to_le16(count);
1872 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1873 &bytes_returned, 1);
1875 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1876 } else if ((smb_buffer_response->WordCount == 3)
1877 || (smb_buffer_response->WordCount == 4)) {
1878 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1880 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1881 if (action & GUEST_LOGIN)
1882 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1884 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1885 cFYI(1, ("UID = %d ", ses->Suid));
1886 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
1888 /* BB Fix below to make endian neutral !! */
1890 if ((pSMBr->resp.hdr.WordCount == 3)
1891 || ((pSMBr->resp.hdr.WordCount == 4)
1893 pSMBr->resp.ByteCount))) {
1894 if (pSMBr->resp.hdr.WordCount == 4) {
1898 ("Security Blob Length %d ",
1902 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1903 if ((long) (bcc_ptr) % 2) {
1905 (BCC(smb_buffer_response)
1907 bcc_ptr++; /* Unicode strings must be word aligned */
1911 (smb_buffer_response) / 2;
1914 UniStrnlen((wchar_t *) bcc_ptr,
1915 remaining_words - 1);
1916 /* We look for obvious messed up bcc or strings in response so we do not go off
1917 the end since (at least) WIN2K and Windows XP have a major bug in not null
1918 terminating last Unicode string in response */
1920 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1921 cifs_strfromUCS_le(ses->serverOS,
1925 bcc_ptr += 2 * (len + 1);
1926 remaining_words -= len + 1;
1927 ses->serverOS[2 * len] = 0;
1928 ses->serverOS[1 + (2 * len)] = 0;
1929 if (remaining_words > 0) {
1930 len = UniStrnlen((wchar_t *)bcc_ptr,
1934 cifs_kcalloc(2 * (len + 1),
1936 cifs_strfromUCS_le(ses->serverNOS,
1940 bcc_ptr += 2 * (len + 1);
1941 ses->serverNOS[2 * len] = 0;
1942 ses->serverNOS[1 + (2 * len)] = 0;
1943 remaining_words -= len + 1;
1944 if (remaining_words > 0) {
1945 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1946 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1947 ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
1948 cifs_strfromUCS_le(ses->serverDomain,
1952 bcc_ptr += 2*(len+1);
1953 ses->serverDomain[2*len] = 0;
1954 ses->serverDomain[1+(2*len)] = 0;
1955 } /* else no more room so create dummy domain string */
1958 cifs_kcalloc(2,GFP_KERNEL);
1959 } else { /* no room so create dummy domain and NOS string */
1960 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
1961 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
1963 } else { /* ASCII */
1965 len = strnlen(bcc_ptr, 1024);
1966 if (((long) bcc_ptr + len) - (long)
1967 pByteArea(smb_buffer_response)
1968 <= BCC(smb_buffer_response)) {
1969 ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
1970 strncpy(ses->serverOS, bcc_ptr, len);
1973 bcc_ptr[0] = 0; /* null terminate the string */
1976 len = strnlen(bcc_ptr, 1024);
1977 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1978 strncpy(ses->serverNOS, bcc_ptr, len);
1983 len = strnlen(bcc_ptr, 1024);
1984 ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
1985 strncpy(ses->serverDomain, bcc_ptr, len);
1991 ("Variable field of length %d extends beyond end of smb ",
1996 (" Security Blob Length extends beyond end of SMB"));
1999 cERROR(1, ("No session structure passed in."));
2003 (" Invalid Word count %d: ",
2004 smb_buffer_response->WordCount));
2009 cifs_buf_release(smb_buffer);
2015 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2016 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2017 const struct nls_table *nls_codepage)
2019 struct smb_hdr *smb_buffer;
2020 struct smb_hdr *smb_buffer_response;
2021 SESSION_SETUP_ANDX *pSMB;
2022 SESSION_SETUP_ANDX *pSMBr;
2026 int remaining_words = 0;
2027 int bytes_returned = 0;
2029 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2030 PNEGOTIATE_MESSAGE SecurityBlob;
2031 PCHALLENGE_MESSAGE SecurityBlob2;
2032 __u32 negotiate_flags, capabilities;
2035 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2038 domain = ses->domainName;
2039 *pNTLMv2_flag = FALSE;
2040 smb_buffer = cifs_buf_get();
2041 if (smb_buffer == 0) {
2044 smb_buffer_response = smb_buffer;
2045 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2046 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2048 /* send SMBsessionSetup here */
2049 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2050 NULL /* no tCon exists yet */ , 12 /* wct */ );
2051 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2052 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2054 pSMB->req.AndXCommand = 0xFF;
2055 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2056 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2058 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2059 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2061 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2062 CAP_EXTENDED_SECURITY;
2063 if (ses->capabilities & CAP_UNICODE) {
2064 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2065 capabilities |= CAP_UNICODE;
2067 if (ses->capabilities & CAP_STATUS32) {
2068 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2069 capabilities |= CAP_STATUS32;
2071 if (ses->capabilities & CAP_DFS) {
2072 smb_buffer->Flags2 |= SMBFLG2_DFS;
2073 capabilities |= CAP_DFS;
2075 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2077 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2078 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2079 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2080 SecurityBlob->MessageType = NtLmNegotiate;
2082 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2083 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2084 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2086 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2088 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2089 /* setup pointers to domain name and workstation name */
2090 bcc_ptr += SecurityBlobLength;
2092 SecurityBlob->WorkstationName.Buffer = 0;
2093 SecurityBlob->WorkstationName.Length = 0;
2094 SecurityBlob->WorkstationName.MaximumLength = 0;
2096 if (domain == NULL) {
2097 SecurityBlob->DomainName.Buffer = 0;
2098 SecurityBlob->DomainName.Length = 0;
2099 SecurityBlob->DomainName.MaximumLength = 0;
2102 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2103 strncpy(bcc_ptr, domain, 63);
2104 len = strnlen(domain, 64);
2105 SecurityBlob->DomainName.MaximumLength =
2107 SecurityBlob->DomainName.Buffer =
2108 cpu_to_le32((long) &SecurityBlob->
2110 (long) &SecurityBlob->Signature);
2112 SecurityBlobLength += len;
2113 SecurityBlob->DomainName.Length =
2116 if (ses->capabilities & CAP_UNICODE) {
2117 if ((long) bcc_ptr % 2) {
2123 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2125 bcc_ptr += 2 * bytes_returned;
2127 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
2129 bcc_ptr += 2 * bytes_returned;
2130 bcc_ptr += 2; /* null terminate Linux version */
2132 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2134 bcc_ptr += 2 * bytes_returned;
2137 bcc_ptr += 2; /* null terminate network opsys string */
2140 bcc_ptr += 2; /* null domain */
2141 } else { /* ASCII */
2142 strcpy(bcc_ptr, "Linux version ");
2143 bcc_ptr += strlen("Linux version ");
2144 strcpy(bcc_ptr, UTS_RELEASE);
2145 bcc_ptr += strlen(UTS_RELEASE) + 1;
2146 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2147 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2148 bcc_ptr++; /* empty domain field */
2151 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2152 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2153 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2154 smb_buffer->smb_buf_length += count;
2155 pSMB->req.ByteCount = cpu_to_le16(count);
2157 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2158 &bytes_returned, 1);
2160 if (smb_buffer_response->Status.CifsError ==
2161 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2165 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2166 } else if ((smb_buffer_response->WordCount == 3)
2167 || (smb_buffer_response->WordCount == 4)) {
2168 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2169 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2171 if (action & GUEST_LOGIN)
2172 cFYI(1, (" Guest login"));
2173 /* Do we want to set anything in SesInfo struct when guest login? */
2175 bcc_ptr = pByteArea(smb_buffer_response);
2176 /* response can have either 3 or 4 word count - Samba sends 3 */
2178 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2179 if (SecurityBlob2->MessageType != NtLmChallenge) {
2181 ("Unexpected NTLMSSP message type received %d",
2182 SecurityBlob2->MessageType));
2184 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2185 cFYI(1, ("UID = %d ", ses->Suid));
2186 if ((pSMBr->resp.hdr.WordCount == 3)
2187 || ((pSMBr->resp.hdr.WordCount == 4)
2189 pSMBr->resp.ByteCount))) {
2191 if (pSMBr->resp.hdr.WordCount == 4) {
2192 bcc_ptr += blob_len;
2194 ("Security Blob Length %d ",
2198 cFYI(1, ("NTLMSSP Challenge rcvd "));
2200 memcpy(ses->server->cryptKey,
2201 SecurityBlob2->Challenge,
2202 CIFS_CRYPTO_KEY_SIZE);
2203 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2204 *pNTLMv2_flag = TRUE;
2206 if((SecurityBlob2->NegotiateFlags &
2207 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2208 || (sign_CIFS_PDUs > 1))
2209 ses->server->secMode |=
2210 SECMODE_SIGN_REQUIRED;
2211 if ((SecurityBlob2->NegotiateFlags &
2212 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2213 ses->server->secMode |=
2214 SECMODE_SIGN_ENABLED;
2216 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2217 if ((long) (bcc_ptr) % 2) {
2219 (BCC(smb_buffer_response)
2221 bcc_ptr++; /* Unicode strings must be word aligned */
2225 (smb_buffer_response) / 2;
2228 UniStrnlen((wchar_t *) bcc_ptr,
2229 remaining_words - 1);
2230 /* We look for obvious messed up bcc or strings in response so we do not go off
2231 the end since (at least) WIN2K and Windows XP have a major bug in not null
2232 terminating last Unicode string in response */
2234 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2235 cifs_strfromUCS_le(ses->serverOS,
2239 bcc_ptr += 2 * (len + 1);
2240 remaining_words -= len + 1;
2241 ses->serverOS[2 * len] = 0;
2242 ses->serverOS[1 + (2 * len)] = 0;
2243 if (remaining_words > 0) {
2244 len = UniStrnlen((wchar_t *)
2249 cifs_kcalloc(2 * (len + 1),
2251 cifs_strfromUCS_le(ses->
2257 bcc_ptr += 2 * (len + 1);
2258 ses->serverNOS[2 * len] = 0;
2261 remaining_words -= len + 1;
2262 if (remaining_words > 0) {
2263 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2264 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2289 } /* else no more room so create dummy domain string */
2294 } else { /* no room so create dummy domain and NOS string */
2296 cifs_kcalloc(2, GFP_KERNEL);
2298 cifs_kcalloc(2, GFP_KERNEL);
2300 } else { /* ASCII */
2301 len = strnlen(bcc_ptr, 1024);
2302 if (((long) bcc_ptr + len) - (long)
2303 pByteArea(smb_buffer_response)
2304 <= BCC(smb_buffer_response)) {
2306 cifs_kcalloc(len + 1,
2308 strncpy(ses->serverOS,
2312 bcc_ptr[0] = 0; /* null terminate string */
2315 len = strnlen(bcc_ptr, 1024);
2317 cifs_kcalloc(len + 1,
2319 strncpy(ses->serverNOS, bcc_ptr, len);
2324 len = strnlen(bcc_ptr, 1024);
2326 cifs_kcalloc(len + 1,
2328 strncpy(ses->serverDomain, bcc_ptr, len);
2334 ("Variable field of length %d extends beyond end of smb ",
2339 (" Security Blob Length extends beyond end of SMB"));
2342 cERROR(1, ("No session structure passed in."));
2346 (" Invalid Word count %d: ",
2347 smb_buffer_response->WordCount));
2352 cifs_buf_release(smb_buffer);
2357 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2358 char *ntlm_session_key, int ntlmv2_flag,
2359 const struct nls_table *nls_codepage)
2361 struct smb_hdr *smb_buffer;
2362 struct smb_hdr *smb_buffer_response;
2363 SESSION_SETUP_ANDX *pSMB;
2364 SESSION_SETUP_ANDX *pSMBr;
2369 int remaining_words = 0;
2370 int bytes_returned = 0;
2372 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2373 PAUTHENTICATE_MESSAGE SecurityBlob;
2374 __u32 negotiate_flags, capabilities;
2377 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2380 user = ses->userName;
2381 domain = ses->domainName;
2382 smb_buffer = cifs_buf_get();
2383 if (smb_buffer == 0) {
2386 smb_buffer_response = smb_buffer;
2387 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2388 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2390 /* send SMBsessionSetup here */
2391 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2392 NULL /* no tCon exists yet */ , 12 /* wct */ );
2393 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2394 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2395 pSMB->req.AndXCommand = 0xFF;
2396 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2397 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2399 pSMB->req.hdr.Uid = ses->Suid;
2401 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2402 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2404 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2405 CAP_EXTENDED_SECURITY;
2406 if (ses->capabilities & CAP_UNICODE) {
2407 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2408 capabilities |= CAP_UNICODE;
2410 if (ses->capabilities & CAP_STATUS32) {
2411 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2412 capabilities |= CAP_STATUS32;
2414 if (ses->capabilities & CAP_DFS) {
2415 smb_buffer->Flags2 |= SMBFLG2_DFS;
2416 capabilities |= CAP_DFS;
2418 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2420 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2421 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2422 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2423 SecurityBlob->MessageType = NtLmAuthenticate;
2424 bcc_ptr += SecurityBlobLength;
2426 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2427 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2428 0x80000000 | NTLMSSP_NEGOTIATE_128;
2430 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2432 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2434 /* setup pointers to domain name and workstation name */
2436 SecurityBlob->WorkstationName.Buffer = 0;
2437 SecurityBlob->WorkstationName.Length = 0;
2438 SecurityBlob->WorkstationName.MaximumLength = 0;
2439 SecurityBlob->SessionKey.Length = 0;
2440 SecurityBlob->SessionKey.MaximumLength = 0;
2441 SecurityBlob->SessionKey.Buffer = 0;
2443 SecurityBlob->LmChallengeResponse.Length = 0;
2444 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2445 SecurityBlob->LmChallengeResponse.Buffer = 0;
2447 SecurityBlob->NtChallengeResponse.Length =
2448 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2449 SecurityBlob->NtChallengeResponse.MaximumLength =
2450 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2451 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2452 SecurityBlob->NtChallengeResponse.Buffer =
2453 cpu_to_le32(SecurityBlobLength);
2454 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2455 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2457 if (ses->capabilities & CAP_UNICODE) {
2458 if (domain == NULL) {
2459 SecurityBlob->DomainName.Buffer = 0;
2460 SecurityBlob->DomainName.Length = 0;
2461 SecurityBlob->DomainName.MaximumLength = 0;
2464 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2467 SecurityBlob->DomainName.MaximumLength =
2469 SecurityBlob->DomainName.Buffer =
2470 cpu_to_le32(SecurityBlobLength);
2472 SecurityBlobLength += len;
2473 SecurityBlob->DomainName.Length =
2477 SecurityBlob->UserName.Buffer = 0;
2478 SecurityBlob->UserName.Length = 0;
2479 SecurityBlob->UserName.MaximumLength = 0;
2482 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2485 SecurityBlob->UserName.MaximumLength =
2487 SecurityBlob->UserName.Buffer =
2488 cpu_to_le32(SecurityBlobLength);
2490 SecurityBlobLength += len;
2491 SecurityBlob->UserName.Length =
2495 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2496 SecurityBlob->WorkstationName.Length *= 2;
2497 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2498 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2499 bcc_ptr += SecurityBlob->WorkstationName.Length;
2500 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2501 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2503 if ((long) bcc_ptr % 2) {
2508 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2510 bcc_ptr += 2 * bytes_returned;
2512 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
2514 bcc_ptr += 2 * bytes_returned;
2515 bcc_ptr += 2; /* null term version string */
2517 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2519 bcc_ptr += 2 * bytes_returned;
2522 bcc_ptr += 2; /* null terminate network opsys string */
2525 bcc_ptr += 2; /* null domain */
2526 } else { /* ASCII */
2527 if (domain == NULL) {
2528 SecurityBlob->DomainName.Buffer = 0;
2529 SecurityBlob->DomainName.Length = 0;
2530 SecurityBlob->DomainName.MaximumLength = 0;
2533 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2534 strncpy(bcc_ptr, domain, 63);
2535 len = strnlen(domain, 64);
2536 SecurityBlob->DomainName.MaximumLength =
2538 SecurityBlob->DomainName.Buffer =
2539 cpu_to_le32(SecurityBlobLength);
2541 SecurityBlobLength += len;
2542 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2545 SecurityBlob->UserName.Buffer = 0;
2546 SecurityBlob->UserName.Length = 0;
2547 SecurityBlob->UserName.MaximumLength = 0;
2550 strncpy(bcc_ptr, user, 63);
2551 len = strnlen(user, 64);
2552 SecurityBlob->UserName.MaximumLength =
2554 SecurityBlob->UserName.Buffer =
2555 cpu_to_le32(SecurityBlobLength);
2557 SecurityBlobLength += len;
2558 SecurityBlob->UserName.Length = cpu_to_le16(len);
2560 /* BB fill in our workstation name if known BB */
2562 strcpy(bcc_ptr, "Linux version ");
2563 bcc_ptr += strlen("Linux version ");
2564 strcpy(bcc_ptr, UTS_RELEASE);
2565 bcc_ptr += strlen(UTS_RELEASE) + 1;
2566 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2567 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2568 bcc_ptr++; /* null domain */
2571 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2572 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2573 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2574 smb_buffer->smb_buf_length += count;
2575 pSMB->req.ByteCount = cpu_to_le16(count);
2577 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2578 &bytes_returned, 1);
2580 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2581 } else if ((smb_buffer_response->WordCount == 3)
2582 || (smb_buffer_response->WordCount == 4)) {
2583 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2585 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2586 if (action & GUEST_LOGIN)
2587 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2588 /* if(SecurityBlob2->MessageType != NtLm??){
2589 cFYI("Unexpected message type on auth response is %d "));
2593 ("Does UID on challenge %d match auth response UID %d ",
2594 ses->Suid, smb_buffer_response->Uid));
2595 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2596 bcc_ptr = pByteArea(smb_buffer_response);
2597 /* response can have either 3 or 4 word count - Samba sends 3 */
2598 if ((pSMBr->resp.hdr.WordCount == 3)
2599 || ((pSMBr->resp.hdr.WordCount == 4)
2601 pSMBr->resp.ByteCount))) {
2602 if (pSMBr->resp.hdr.WordCount == 4) {
2606 ("Security Blob Length %d ",
2611 ("NTLMSSP response to Authenticate "));
2613 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2614 if ((long) (bcc_ptr) % 2) {
2616 (BCC(smb_buffer_response)
2618 bcc_ptr++; /* Unicode strings must be word aligned */
2620 remaining_words = BCC(smb_buffer_response) / 2;
2623 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2624 /* We look for obvious messed up bcc or strings in response so we do not go off
2625 the end since (at least) WIN2K and Windows XP have a major bug in not null
2626 terminating last Unicode string in response */
2628 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2629 cifs_strfromUCS_le(ses->serverOS,
2633 bcc_ptr += 2 * (len + 1);
2634 remaining_words -= len + 1;
2635 ses->serverOS[2 * len] = 0;
2636 ses->serverOS[1 + (2 * len)] = 0;
2637 if (remaining_words > 0) {
2638 len = UniStrnlen((wchar_t *)
2643 cifs_kcalloc(2 * (len + 1),
2645 cifs_strfromUCS_le(ses->
2651 bcc_ptr += 2 * (len + 1);
2652 ses->serverNOS[2 * len] = 0;
2653 ses->serverNOS[1+(2*len)] = 0;
2654 remaining_words -= len + 1;
2655 if (remaining_words > 0) {
2656 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2657 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2682 } /* else no more room so create dummy domain string */
2684 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
2685 } else { /* no room so create dummy domain and NOS string */
2686 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2687 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2689 } else { /* ASCII */
2690 len = strnlen(bcc_ptr, 1024);
2691 if (((long) bcc_ptr + len) -
2692 (long) pByteArea(smb_buffer_response)
2693 <= BCC(smb_buffer_response)) {
2694 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2695 strncpy(ses->serverOS,bcc_ptr, len);
2698 bcc_ptr[0] = 0; /* null terminate the string */
2701 len = strnlen(bcc_ptr, 1024);
2702 ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
2703 strncpy(ses->serverNOS, bcc_ptr, len);
2708 len = strnlen(bcc_ptr, 1024);
2709 ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
2710 strncpy(ses->serverDomain, bcc_ptr, len);
2716 ("Variable field of length %d extends beyond end of smb ",
2721 (" Security Blob Length extends beyond end of SMB"));
2724 cERROR(1, ("No session structure passed in."));
2728 (" Invalid Word count %d: ",
2729 smb_buffer_response->WordCount));
2734 cifs_buf_release(smb_buffer);
2740 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2741 const char *tree, struct cifsTconInfo *tcon,
2742 const struct nls_table *nls_codepage)
2744 struct smb_hdr *smb_buffer;
2745 struct smb_hdr *smb_buffer_response;
2748 unsigned char *bcc_ptr;
2756 smb_buffer = cifs_buf_get();
2757 if (smb_buffer == 0) {
2760 smb_buffer_response = smb_buffer;
2762 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2763 NULL /*no tid */ , 4 /*wct */ );
2764 smb_buffer->Uid = ses->Suid;
2765 pSMB = (TCONX_REQ *) smb_buffer;
2766 pSMBr = (TCONX_RSP *) smb_buffer_response;
2768 pSMB->AndXCommand = 0xFF;
2769 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2770 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2771 bcc_ptr = &pSMB->Password[0];
2772 bcc_ptr++; /* skip password */
2774 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2775 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2777 if (ses->capabilities & CAP_STATUS32) {
2778 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2780 if (ses->capabilities & CAP_DFS) {
2781 smb_buffer->Flags2 |= SMBFLG2_DFS;
2783 if (ses->capabilities & CAP_UNICODE) {
2784 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2786 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2787 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2788 bcc_ptr += 2; /* skip trailing null */
2789 } else { /* ASCII */
2791 strcpy(bcc_ptr, tree);
2792 bcc_ptr += strlen(tree) + 1;
2794 strcpy(bcc_ptr, "?????");
2795 bcc_ptr += strlen("?????");
2797 count = bcc_ptr - &pSMB->Password[0];
2798 pSMB->hdr.smb_buf_length += count;
2799 pSMB->ByteCount = cpu_to_le16(count);
2801 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2803 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2804 /* above now done in SendReceive */
2805 if ((rc == 0) && (tcon != NULL)) {
2806 tcon->tidStatus = CifsGood;
2807 tcon->tid = smb_buffer_response->Tid;
2808 bcc_ptr = pByteArea(smb_buffer_response);
2809 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2810 /* skip service field (NB: this field is always ASCII) */
2811 bcc_ptr += length + 1;
2812 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2813 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2814 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2815 if ((bcc_ptr + (2 * length)) -
2816 pByteArea(smb_buffer_response) <=
2817 BCC(smb_buffer_response)) {
2818 if(tcon->nativeFileSystem)
2819 kfree(tcon->nativeFileSystem);
2820 tcon->nativeFileSystem =
2821 cifs_kcalloc(length + 2, GFP_KERNEL);
2822 cifs_strfromUCS_le(tcon->nativeFileSystem,
2823 (wchar_t *) bcc_ptr,
2824 length, nls_codepage);
2825 bcc_ptr += 2 * length;
2826 bcc_ptr[0] = 0; /* null terminate the string */
2830 /* else do not bother copying these informational fields */
2832 length = strnlen(bcc_ptr, 1024);
2833 if ((bcc_ptr + length) -
2834 pByteArea(smb_buffer_response) <=
2835 BCC(smb_buffer_response)) {
2836 if(tcon->nativeFileSystem)
2837 kfree(tcon->nativeFileSystem);
2838 tcon->nativeFileSystem =
2839 cifs_kcalloc(length + 1, GFP_KERNEL);
2840 strncpy(tcon->nativeFileSystem, bcc_ptr,
2843 /* else do not bother copying these informational fields */
2845 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2846 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2847 } else if ((rc == 0) && tcon == NULL) {
2848 /* all we need to save for IPC$ connection */
2849 ses->ipc_tid = smb_buffer_response->Tid;
2853 cifs_buf_release(smb_buffer);
2858 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
2862 struct cifsSesInfo *ses = NULL;
2863 struct task_struct *cifsd_task;
2867 if (cifs_sb->tcon) {
2868 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
2869 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
2874 tconInfoFree(cifs_sb->tcon);
2875 if ((ses) && (ses->server)) {
2876 /* save off task so we do not refer to ses later */
2877 cifsd_task = ses->server->tsk;
2878 cFYI(1, ("About to do SMBLogoff "));
2879 rc = CIFSSMBLogoff(xid, ses);
2883 } else if (rc == -ESHUTDOWN) {
2884 cFYI(1,("Waking up socket by sending it signal"));
2885 send_sig(SIGKILL,cifsd_task,1);
2887 } /* else - we have an smb session
2888 left on this socket do not kill cifsd */
2890 cFYI(1, ("No session or bad tcon"));
2893 cifs_sb->tcon = NULL;
2895 set_current_state(TASK_INTERRUPTIBLE);
2896 schedule_timeout(HZ / 2);
2902 return rc; /* BB check if we should always return zero here */
2905 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2906 struct nls_table * nls_info)
2909 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
2910 int ntlmv2_flag = FALSE;
2912 /* what if server changes its buffer size after dropping the session? */
2913 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
2914 rc = CIFSSMBNegotiate(xid, pSesInfo);
2915 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
2916 rc = CIFSSMBNegotiate(xid, pSesInfo);
2921 spin_lock(&GlobalMid_Lock);
2922 if(pSesInfo->server->tcpStatus != CifsExiting)
2923 pSesInfo->server->tcpStatus = CifsGood;
2926 spin_unlock(&GlobalMid_Lock);
2931 pSesInfo->capabilities = pSesInfo->server->capabilities;
2932 if(linuxExtEnabled == 0)
2933 pSesInfo->capabilities &= (~CAP_UNIX);
2934 pSesInfo->sequence_number = 0;
2935 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2936 pSesInfo->server->secMode,
2937 pSesInfo->server->capabilities,
2938 pSesInfo->server->timeZone));
2939 if (extended_security
2940 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
2941 && (pSesInfo->server->secType == NTLMSSP)) {
2942 cFYI(1, ("New style sesssetup "));
2943 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
2944 NULL /* security blob */,
2945 0 /* blob length */,
2947 } else if (extended_security
2948 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
2949 && (pSesInfo->server->secType == RawNTLMSSP)) {
2950 cFYI(1, ("NTLMSSP sesssetup "));
2951 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
2958 cFYI(1,("Can use more secure NTLM version 2 password hash"));
2959 CalcNTLMv2_partial_mac_key(pSesInfo,
2961 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
2963 CalcNTLMv2_response(pSesInfo,v2_response);
2964 /* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
2966 /* BB Put dummy sig in SessSetup PDU? */
2971 SMBNTencrypt(pSesInfo->password,
2972 pSesInfo->server->cryptKey,
2975 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
2977 pSesInfo->password);
2979 /* for better security the weaker lanman hash not sent
2980 in AuthSessSetup so we no longer calculate it */
2982 rc = CIFSNTLMSSPAuthSessSetup(xid,
2988 } else { /* old style NTLM 0.12 session setup */
2989 SMBNTencrypt(pSesInfo->password,
2990 pSesInfo->server->cryptKey,
2993 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
2994 ntlm_session_key, pSesInfo->password);
2995 rc = CIFSSessSetup(xid, pSesInfo,
2996 ntlm_session_key, nls_info);
2999 cERROR(1,("Send error in SessSetup = %d",rc));
3001 cFYI(1,("CIFS Session Established successfully"));
3002 pSesInfo->status = CifsGood;