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 <asm/uaccess.h>
32 #include <asm/processor.h>
35 #include "cifsproto.h"
36 #include "cifs_unicode.h"
37 #include "cifs_debug.h"
38 #include "cifs_fs_sb.h"
41 #include "rfc1002pdu.h"
44 #define RFC1001_PORT 139
46 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
48 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
50 extern int cifs_inet_pton(int, const char *, void *dst);
58 char *iocharset; /* local code page for mapping to and from Unicode */
59 char source_rfc1001_name[16]; /* netbios name of client */
70 unsigned short int port;
73 static int ipv4_connect(struct sockaddr_in *psin_server,
74 struct socket **csocket,
76 static int ipv6_connect(struct sockaddr_in6 *psin_server,
77 struct socket **csocket);
81 * cifs tcp session reconnection
83 * mark tcp session as reconnecting so temporarily locked
84 * mark all smb sessions as reconnecting for tcp session
85 * reconnect tcp session
86 * wake up waiters on reconnection? - (not needed currently)
90 cifs_reconnect(struct TCP_Server_Info *server)
93 struct list_head *tmp;
94 struct cifsSesInfo *ses;
95 struct cifsTconInfo *tcon;
96 struct mid_q_entry * mid_entry;
98 spin_lock(&GlobalMid_Lock);
99 if(server->tcpStatus == CifsExiting) {
100 /* the demux thread will exit normally
101 next time through the loop */
102 spin_unlock(&GlobalMid_Lock);
105 server->tcpStatus = CifsNeedReconnect;
106 spin_unlock(&GlobalMid_Lock);
109 cFYI(1, ("Reconnecting tcp session "));
111 /* before reconnecting the tcp session, mark the smb session (uid)
112 and the tid bad so they are not used until reconnected */
113 read_lock(&GlobalSMBSeslock);
114 list_for_each(tmp, &GlobalSMBSessionList) {
115 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
117 if (ses->server == server) {
118 ses->status = CifsNeedReconnect;
122 /* else tcp and smb sessions need reconnection */
124 list_for_each(tmp, &GlobalTreeConnectionList) {
125 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
126 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
127 tcon->tidStatus = CifsNeedReconnect;
130 read_unlock(&GlobalSMBSeslock);
131 /* do not want to be sending data on a socket we are freeing */
132 down(&server->tcpSem);
133 if(server->ssocket) {
134 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
135 server->ssocket->flags));
136 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
137 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
138 server->ssocket->flags));
139 sock_release(server->ssocket);
140 server->ssocket = NULL;
143 spin_lock(&GlobalMid_Lock);
144 list_for_each(tmp, &server->pending_mid_q) {
145 mid_entry = list_entry(tmp, struct
149 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
150 /* Mark other intransit requests as needing retry so
151 we do not immediately mark the session bad again
152 (ie after we reconnect below) as they timeout too */
153 mid_entry->midState = MID_RETRY_NEEDED;
157 spin_unlock(&GlobalMid_Lock);
160 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
162 if(server->protocolType == IPV6) {
163 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
165 rc = ipv4_connect(&server->addr.sockAddr,
167 server->workstation_RFC1001_name);
170 set_current_state(TASK_INTERRUPTIBLE);
171 schedule_timeout(3 * HZ);
173 atomic_inc(&tcpSesReconnectCount);
174 spin_lock(&GlobalMid_Lock);
175 if(server->tcpStatus != CifsExiting)
176 server->tcpStatus = CifsGood;
177 spin_unlock(&GlobalMid_Lock);
178 /* atomic_set(&server->inFlight,0);*/
179 wake_up(&server->response_q);
186 cifs_demultiplex_thread(struct TCP_Server_Info *server)
189 unsigned int pdu_length, total_read;
190 struct smb_hdr *smb_buffer = NULL;
191 struct msghdr smb_msg;
192 mm_segment_t temp_fs;
194 struct socket *csocket = server->ssocket;
195 struct list_head *tmp;
196 struct cifsSesInfo *ses;
197 struct task_struct *task_to_wake = NULL;
198 struct mid_q_entry *mid_entry;
202 allow_signal(SIGKILL);
203 current->flags |= PF_MEMALLOC;
204 server->tsk = current; /* save process info to wake at shutdown */
205 cFYI(1, ("Demultiplex PID: %d", current->pid));
207 temp_fs = get_fs(); /* we must turn off socket api parm checking */
210 while (server->tcpStatus != CifsExiting) {
211 if (smb_buffer == NULL)
212 smb_buffer = cifs_buf_get();
214 memset(smb_buffer, 0, sizeof (struct smb_hdr));
216 if (smb_buffer == NULL) {
217 cERROR(1,("Can not get memory for SMB response"));
218 set_current_state(TASK_INTERRUPTIBLE);
219 schedule_timeout(HZ * 3); /* give system time to free memory */
222 iov.iov_base = smb_buffer;
223 iov.iov_len = sizeof (struct smb_hdr) - 1;
224 /* 1 byte less above since wct is not always returned in error cases */
225 smb_msg.msg_iov = &iov;
226 smb_msg.msg_iovlen = 1;
227 smb_msg.msg_control = NULL;
228 smb_msg.msg_controllen = 0;
231 sock_recvmsg(csocket, &smb_msg,
232 sizeof (struct smb_hdr) -
233 1 /* RFC1001 header and SMB header */ ,
234 MSG_PEEK /* flags see socket.h */ );
236 if(server->tcpStatus == CifsExiting) {
238 } else if (server->tcpStatus == CifsNeedReconnect) {
239 cFYI(1,("Reconnecting after server stopped responding"));
240 cifs_reconnect(server);
241 cFYI(1,("call to reconnect done"));
242 csocket = server->ssocket;
244 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
245 set_current_state(TASK_INTERRUPTIBLE);
246 schedule_timeout(1); /* minimum sleep to prevent looping
247 allowing socket to clear and app threads to set
248 tcpStatus CifsNeedReconnect if server hung */
250 } else if (length <= 0) {
251 if(server->tcpStatus == CifsNew) {
252 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
253 /* some servers kill tcp session rather than returning
254 smb negprot error in which case reconnecting here is
255 not going to help - return error to mount */
258 if(length == -EINTR) {
259 cFYI(1,("cifsd thread killed"));
262 cFYI(1,("Reconnecting after unexpected peek error %d",length));
263 cifs_reconnect(server);
264 csocket = server->ssocket;
265 wake_up(&server->response_q);
269 pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
270 /* Ony read pdu_length after below checks for too short (due
271 to e.g. int overflow) and too long ie beyond end of buf */
272 cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
274 temp = (char *) smb_buffer;
276 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
277 iov.iov_base = smb_buffer;
279 length = sock_recvmsg(csocket, &smb_msg, 4, 0);
280 cFYI(0,("Received 4 byte keep alive packet"));
281 } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
282 iov.iov_base = smb_buffer;
284 length = sock_recvmsg(csocket, &smb_msg, 4, 0);
285 cFYI(1,("Good RFC 1002 session rsp"));
286 } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
288 /* we get this from Windows 98 instead of error on SMB negprot response */
289 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
290 if(server->tcpStatus == CifsNew) {
291 /* if nack on negprot (rather than
292 ret of smb negprot error) reconnecting
293 not going to help, ret error to mount */
296 /* give server a second to
297 clean up before reconnect attempt */
298 set_current_state(TASK_INTERRUPTIBLE);
299 schedule_timeout(HZ);
300 /* always try 445 first on reconnect
301 since we get NACK on some if we ever
302 connected to port 139 (the NACK is
303 since we do not begin with RFC1001
304 session initialize frame) */
305 server->addr.sockAddr.sin_port = CIFS_PORT;
306 cifs_reconnect(server);
307 csocket = server->ssocket;
308 wake_up(&server->response_q);
311 } else if (temp[0] != (char) 0) {
312 cERROR(1,("Unknown RFC 1002 frame"));
313 cifs_dump_mem(" Received Data: ", temp, length);
314 cifs_reconnect(server);
315 csocket = server->ssocket;
318 if ((length != sizeof (struct smb_hdr) - 1)
320 CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
322 sizeof (struct smb_hdr) - 1)
325 (smb_buffer, smb_buffer->Mid))) {
327 ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
328 length, pdu_length));
329 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
330 /* could we fix this network corruption by finding next
331 smb header (instead of killing the session) and
332 restart reading from next valid SMB found? */
333 cifs_reconnect(server);
334 csocket = server->ssocket;
336 } else { /* length ok */
339 iov.iov_base = smb_buffer;
340 iov.iov_len = pdu_length;
342 total_read < pdu_length;
343 total_read += length) {
344 length = sock_recvmsg(csocket, &smb_msg,
345 pdu_length - total_read, 0);
348 ("Zero length receive when expecting %d ",
349 pdu_length - total_read));
350 cifs_reconnect(server);
351 csocket = server->ssocket;
357 dump_smb(smb_buffer, length);
359 (smb_buffer, smb_buffer->Mid, total_read)) {
360 cERROR(1, ("Bad SMB Received "));
365 spin_lock(&GlobalMid_Lock);
366 list_for_each(tmp, &server->pending_mid_q) {
367 mid_entry = list_entry(tmp, struct
371 if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
373 (" Mid 0x%x matched - waking up ",mid_entry->mid));
374 task_to_wake = mid_entry->tsk;
375 mid_entry->resp_buf =
377 mid_entry->midState =
378 MID_RESPONSE_RECEIVED;
381 spin_unlock(&GlobalMid_Lock);
383 smb_buffer = NULL; /* will be freed by users thread after he is done */
384 wake_up_process(task_to_wake);
385 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
386 cERROR(1, ("No task to wake, unknown frame rcvd!"));
387 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
392 ("Frame less than four bytes received %d bytes long.",
395 length = sock_recvmsg(csocket, &smb_msg, length, 0); /* throw away junk frame */
397 (" with junk 0x%x in it ",
398 *(__u32 *) smb_buffer));
402 spin_lock(&GlobalMid_Lock);
403 server->tcpStatus = CifsExiting;
405 atomic_set(&server->inFlight, 0);
406 spin_unlock(&GlobalMid_Lock);
407 /* Although there should not be any requests blocked on
408 this queue it can not hurt to be paranoid and try to wake up requests
409 that may haven been blocked when more than 50 at time were on the wire
410 to the same server - they now will see the session is in exit state
411 and get out of SendReceive. */
412 wake_up_all(&server->request_q);
413 /* give those requests time to exit */
414 set_current_state(TASK_INTERRUPTIBLE);
415 schedule_timeout(HZ/8);
417 if(server->ssocket) {
418 sock_release(csocket);
419 server->ssocket = NULL;
422 if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
423 cifs_buf_release(smb_buffer);
425 read_lock(&GlobalSMBSeslock);
426 if (list_empty(&server->pending_mid_q)) {
427 /* loop through server session structures attached to this and mark them dead */
428 list_for_each(tmp, &GlobalSMBSessionList) {
430 list_entry(tmp, struct cifsSesInfo,
432 if (ses->server == server) {
433 ses->status = CifsExiting;
437 read_unlock(&GlobalSMBSeslock);
439 spin_lock(&GlobalMid_Lock);
440 list_for_each(tmp, &server->pending_mid_q) {
441 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
442 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
444 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
445 task_to_wake = mid_entry->tsk;
447 wake_up_process(task_to_wake);
451 spin_unlock(&GlobalMid_Lock);
452 read_unlock(&GlobalSMBSeslock);
453 set_current_state(TASK_INTERRUPTIBLE);
454 /* 1/8th of sec is more than enough time for them to exit */
455 schedule_timeout(HZ/8);
458 if (list_empty(&server->pending_mid_q)) {
459 /* mpx threads have not exited yet give them
460 at least the smb send timeout time for long ops */
461 cFYI(1, ("Wait for exit from demultiplex thread"));
462 set_current_state(TASK_INTERRUPTIBLE);
463 schedule_timeout(46 * HZ);
464 /* if threads still have not exited they are probably never
465 coming home not much else we can do but free the memory */
469 set_current_state(TASK_INTERRUPTIBLE);
470 schedule_timeout(HZ/4);
475 cifs_kcalloc(size_t size, int type)
478 addr = kmalloc(size, type);
480 memset(addr, 0, size);
485 cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
489 unsigned int temp_len, i, j;
495 memset(vol->source_rfc1001_name,0x20,15);
496 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
497 /* does not have to be a perfect mapping since the field is
498 informational, only used for servers that do not support
499 port 445 and it can be overridden at mount time */
500 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
502 vol->source_rfc1001_name[15] = 0;
504 vol->linux_uid = current->uid; /* current->euid instead? */
505 vol->linux_gid = current->gid;
506 vol->dir_mode = S_IRWXUGO;
507 /* 2767 perms indicate mandatory locking support */
508 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
510 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
516 if(strncmp(options,"sep=",4) == 0) {
517 if(options[4] != 0) {
518 separator[0] = options[4];
521 cFYI(1,("Null separator not allowed"));
525 while ((data = strsep(&options, separator)) != NULL) {
528 if ((value = strchr(data, '=')) != NULL)
530 if (strnicmp(data, "user", 4) == 0) {
531 if (!value || !*value) {
533 "CIFS: invalid or missing username\n");
534 return 1; /* needs_arg; */
536 if (strnlen(value, 200) < 200) {
537 vol->username = value;
539 printk(KERN_WARNING "CIFS: username too long\n");
542 } else if (strnicmp(data, "pass", 4) == 0) {
543 if (!value || !*value) {
544 vol->password = NULL;
547 temp_len = strlen(value);
548 /* removed password length check, NTLM passwords
549 can be arbitrarily long */
551 /* if comma in password, the string will be
552 prematurely null terminated. Commas in password are
553 specified across the cifs mount interface by a double
554 comma ie ,, and a comma used as in other cases ie ','
555 as a parameter delimiter/separator is single and due
556 to the strsep above is temporarily zeroed. */
558 /* NB: password legally can have multiple commas and
559 the only illegal character in a password is null */
561 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
563 value[temp_len] = separator[0];
564 temp_len+=2; /* move after the second comma */
565 while(value[temp_len] != 0) {
566 if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
567 /* single comma indicating start of next parm */
572 if(value[temp_len] == 0) {
576 /* move options to point to start of next parm */
577 options = value + temp_len + 1;
579 /* go from value to (value + temp_len) condensing double commas to singles */
580 vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
581 for(i=0,j=0;i<temp_len;i++,j++) {
582 vol->password[j] = value[i];
583 if(value[i] == separator[0] && value[i+1] == separator[0]) {
584 /* skip second comma */
588 /* value[temp_len] is zeroed above so
589 vol->password[temp_len] guaranteed to be null */
591 vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
592 strcpy(vol->password, value);
594 } else if (strnicmp(data, "ip", 2) == 0) {
595 if (!value || !*value) {
597 } else if (strnlen(value, 35) < 35) {
600 printk(KERN_WARNING "CIFS: ip address too long\n");
603 } else if ((strnicmp(data, "unc", 3) == 0)
604 || (strnicmp(data, "target", 6) == 0)
605 || (strnicmp(data, "path", 4) == 0)) {
606 if (!value || !*value) {
608 "CIFS: invalid path to network resource\n");
609 return 1; /* needs_arg; */
611 if ((temp_len = strnlen(value, 300)) < 300) {
612 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
615 strcpy(vol->UNC,value);
616 if (strncmp(vol->UNC, "//", 2) == 0) {
619 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
621 "CIFS: UNC Path does not begin with // or \\\\ \n");
625 printk(KERN_WARNING "CIFS: UNC name too long\n");
628 } else if ((strnicmp(data, "domain", 3) == 0)
629 || (strnicmp(data, "workgroup", 5) == 0)) {
630 if (!value || !*value) {
631 printk(KERN_WARNING "CIFS: invalid domain name\n");
632 return 1; /* needs_arg; */
634 /* BB are there cases in which a comma can be valid in
635 a domain name and need special handling? */
636 if (strnlen(value, 65) < 65) {
637 vol->domainname = value;
638 cFYI(1, ("Domain name set"));
640 printk(KERN_WARNING "CIFS: domain name too long\n");
643 } else if (strnicmp(data, "iocharset", 9) == 0) {
644 if (!value || !*value) {
645 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
646 return 1; /* needs_arg; */
648 if (strnlen(value, 65) < 65) {
649 if(strnicmp(value,"default",7))
650 vol->iocharset = value;
651 /* if iocharset not set load_nls_default used by caller */
652 cFYI(1, ("iocharset set to %s",value));
654 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
657 } else if (strnicmp(data, "uid", 3) == 0) {
658 if (value && *value) {
660 simple_strtoul(value, &value, 0);
662 } else if (strnicmp(data, "gid", 3) == 0) {
663 if (value && *value) {
665 simple_strtoul(value, &value, 0);
667 } else if (strnicmp(data, "file_mode", 4) == 0) {
668 if (value && *value) {
670 simple_strtoul(value, &value, 0);
672 } else if (strnicmp(data, "dir_mode", 3) == 0) {
673 if (value && *value) {
675 simple_strtoul(value, &value, 0);
677 } else if (strnicmp(data, "port", 4) == 0) {
678 if (value && *value) {
680 simple_strtoul(value, &value, 0);
682 } else if (strnicmp(data, "rsize", 5) == 0) {
683 if (value && *value) {
685 simple_strtoul(value, &value, 0);
687 } else if (strnicmp(data, "wsize", 5) == 0) {
688 if (value && *value) {
690 simple_strtoul(value, &value, 0);
692 } else if (strnicmp(data, "sockopt", 5) == 0) {
693 if (value && *value) {
695 simple_strtoul(value, &value, 0);
697 } else if (strnicmp(data, "netbiosname", 4) == 0) {
698 if (!value || !*value || (*value == ' ')) {
699 cFYI(1,("invalid (empty) netbiosname specified"));
701 memset(vol->source_rfc1001_name,0x20,15);
703 /* BB are there cases in which a comma can be
704 valid in this workstation netbios name (and need
705 special handling)? */
707 /* We do not uppercase netbiosname for user */
711 vol->source_rfc1001_name[i] = value[i];
713 /* The string has 16th byte zero still from
714 set at top of the function */
715 if((i==15) && (value[i] != 0))
716 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
718 } else if (strnicmp(data, "credentials", 4) == 0) {
720 } else if (strnicmp(data, "version", 3) == 0) {
722 } else if (strnicmp(data, "rw", 2) == 0) {
724 } else if ((strnicmp(data, "suid", 4) == 0) ||
725 (strnicmp(data, "nosuid", 6) == 0) ||
726 (strnicmp(data, "exec", 4) == 0) ||
727 (strnicmp(data, "noexec", 6) == 0) ||
728 (strnicmp(data, "nodev", 5) == 0) ||
729 (strnicmp(data, "noauto", 6) == 0) ||
730 (strnicmp(data, "dev", 3) == 0)) {
731 /* The mount tool or mount.cifs helper (if present)
732 uses these opts to set flags, and the flags are read
733 by the kernel vfs layer before we get here (ie
734 before read super) so there is no point trying to
735 parse these options again and set anything and it
736 is ok to just ignore them */
738 } else if (strnicmp(data, "ro", 2) == 0) {
740 } else if (strnicmp(data, "hard", 4) == 0) {
742 } else if (strnicmp(data, "soft", 4) == 0) {
744 } else if (strnicmp(data, "nohard", 6) == 0) {
746 } else if (strnicmp(data, "nosoft", 6) == 0) {
748 } else if (strnicmp(data, "nointr", 6) == 0) {
750 } else if (strnicmp(data, "intr", 4) == 0) {
752 } else if (strnicmp(data, "noac", 4) == 0) {
753 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
755 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
757 if (vol->UNC == NULL) {
758 if(devname == NULL) {
759 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
762 if ((temp_len = strnlen(devname, 300)) < 300) {
763 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
766 strcpy(vol->UNC,devname);
767 if (strncmp(vol->UNC, "//", 2) == 0) {
770 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
771 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
775 printk(KERN_WARNING "CIFS: UNC name too long\n");
780 vol->UNCip = &vol->UNC[2];
785 static struct cifsSesInfo *
786 cifs_find_tcp_session(__u32 new_target_ip_addr,
787 char *userName, struct TCP_Server_Info **psrvTcp)
789 struct list_head *tmp;
790 struct cifsSesInfo *ses;
793 read_lock(&GlobalSMBSeslock);
794 list_for_each(tmp, &GlobalSMBSessionList) {
795 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
797 if (ses->server->addr.sockAddr.sin_addr.s_addr ==
798 new_target_ip_addr) {
799 /* BB lock server and tcp session and increment use count here?? */
800 *psrvTcp = ses->server; /* found a match on the TCP session */
801 /* BB check if reconnection needed */
803 (ses->userName, userName,
804 MAX_USERNAME_SIZE) == 0){
805 read_unlock(&GlobalSMBSeslock);
806 return ses; /* found exact match on both tcp and SMB sessions */
810 /* else tcp and smb sessions need reconnection */
812 read_unlock(&GlobalSMBSeslock);
816 static struct cifsTconInfo *
817 find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
819 struct list_head *tmp;
820 struct cifsTconInfo *tcon;
822 read_lock(&GlobalSMBSeslock);
823 list_for_each(tmp, &GlobalTreeConnectionList) {
824 cFYI(1, ("Next tcon - "));
825 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
827 if (tcon->ses->server) {
829 (" old ip addr: %x == new ip %x ?",
830 tcon->ses->server->addr.sockAddr.sin_addr.
831 s_addr, new_target_ip_addr));
832 if (tcon->ses->server->addr.sockAddr.sin_addr.
833 s_addr == new_target_ip_addr) {
834 /* BB lock tcon and server and tcp session and increment use count here? */
835 /* found a match on the TCP session */
836 /* BB check if reconnection needed */
837 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
838 tcon->treeName, uncName));
840 (tcon->treeName, uncName,
841 MAX_TREE_SIZE) == 0) {
843 ("Matched UNC, old user: %s == new: %s ?",
844 tcon->treeName, uncName));
846 (tcon->ses->userName,
848 MAX_USERNAME_SIZE) == 0) {
849 read_unlock(&GlobalSMBSeslock);
850 return tcon;/* also matched user (smb session)*/
857 read_unlock(&GlobalSMBSeslock);
862 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
863 const char *old_path, const struct nls_table *nls_codepage)
865 unsigned char *referrals = NULL;
866 unsigned int num_referrals;
869 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
870 &num_referrals, &referrals);
872 /* BB Add in code to: if valid refrl, if not ip address contact
873 the helper that resolves tcp names, mount to it, try to
874 tcon to it unmount it if fail */
883 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
884 const char *old_path, const struct nls_table *nls_codepage,
885 unsigned int *pnum_referrals, unsigned char ** preferrals)
892 if (pSesInfo->ipc_tid == 0) {
893 temp_unc = kmalloc(2 /* for slashes */ +
894 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
895 + 1 + 4 /* slash IPC$ */ + 2,
897 if (temp_unc == NULL)
901 strcpy(temp_unc + 2, pSesInfo->serverName);
902 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
903 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
905 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
909 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
910 pnum_referrals, nls_codepage);
915 /* See RFC1001 section 14 on representation of Netbios names */
916 static void rfc1002mangle(char * target,char * source, unsigned int length)
920 for(i=0,j=0;i<(length);i++) {
921 /* mask a nibble at a time and encode */
922 target[j] = 'A' + (0x0F & (source[i] >> 4));
923 target[j+1] = 'A' + (0x0F & source[i]);
931 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
936 unsigned short int orig_port = 0;
938 if(*csocket == NULL) {
939 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
941 cERROR(1, ("Error %d creating socket",rc));
945 /* BB other socket options to set KEEPALIVE, NODELAY? */
946 cFYI(1,("Socket created"));
947 (*csocket)->sk->sk_allocation = GFP_NOFS;
951 psin_server->sin_family = AF_INET;
952 if(psin_server->sin_port) { /* user overrode default port */
953 rc = (*csocket)->ops->connect(*csocket,
954 (struct sockaddr *) psin_server,
955 sizeof (struct sockaddr_in),0);
961 /* save original port so we can retry user specified port
962 later if fall back ports fail this time */
963 orig_port = psin_server->sin_port;
965 /* do not retry on the same port we just failed on */
966 if(psin_server->sin_port != htons(CIFS_PORT)) {
967 psin_server->sin_port = htons(CIFS_PORT);
969 rc = (*csocket)->ops->connect(*csocket,
970 (struct sockaddr *) psin_server,
971 sizeof (struct sockaddr_in),0);
977 psin_server->sin_port = htons(RFC1001_PORT);
978 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
979 psin_server, sizeof (struct sockaddr_in),0);
984 /* give up here - unless we want to retry on different
985 protocol families some day */
988 psin_server->sin_port = orig_port;
989 cFYI(1,("Error %d connecting to server via ipv4",rc));
990 sock_release(*csocket);
994 /* Eventually check for other socket options to change from
995 the default. sock_setsockopt not used because it expects
997 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
999 /* send RFC1001 sessinit */
1001 if(psin_server->sin_port == htons(139)) {
1002 /* some servers require RFC1001 sessinit before sending
1003 negprot - BB check reconnection in case where second
1004 sessinit is sent but no second negprot */
1005 struct rfc1002_session_packet * ses_init_buf;
1006 struct smb_hdr * smb_buf;
1007 ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1009 ses_init_buf->trailer.session_req.called_len = 32;
1010 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1011 DEFAULT_CIFS_CALLED_NAME,16);
1012 ses_init_buf->trailer.session_req.calling_len = 32;
1013 /* calling name ends in null (byte 16) from old smb
1015 if(netbios_name && (netbios_name[0] !=0)) {
1016 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1019 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1020 "LINUX_CIFS_CLNT",16);
1022 ses_init_buf->trailer.session_req.scope1 = 0;
1023 ses_init_buf->trailer.session_req.scope2 = 0;
1024 smb_buf = (struct smb_hdr *)ses_init_buf;
1025 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1026 smb_buf->smb_buf_length = 0x81000044;
1027 rc = smb_send(*csocket, smb_buf, 0x44,
1028 (struct sockaddr *)psin_server);
1029 kfree(ses_init_buf);
1031 /* else the negprot may still work without this
1032 even though malloc failed */
1040 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1045 if(*csocket == NULL) {
1046 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1048 cERROR(1, ("Error %d creating ipv6 socket",rc));
1052 /* BB other socket options to set KEEPALIVE, NODELAY? */
1053 cFYI(1,("ipv6 Socket created"));
1054 (*csocket)->sk->sk_allocation = GFP_NOFS;
1058 psin_server->sin6_family = AF_INET6;
1060 if(psin_server->sin6_port) { /* user overrode default port */
1061 rc = (*csocket)->ops->connect(*csocket,
1062 (struct sockaddr *) psin_server,
1063 sizeof (struct sockaddr_in6),0);
1069 /* do not retry on the same port we just failed on */
1070 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1071 psin_server->sin6_port = htons(CIFS_PORT);
1073 rc = (*csocket)->ops->connect(*csocket,
1074 (struct sockaddr *) psin_server,
1075 sizeof (struct sockaddr_in6),0);
1081 psin_server->sin6_port = htons(RFC1001_PORT);
1082 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1083 psin_server, sizeof (struct sockaddr_in6),0);
1088 /* give up here - unless we want to retry on different
1089 protocol families some day */
1091 cFYI(1,("Error %d connecting to server via ipv6",rc));
1092 sock_release(*csocket);
1096 /* Eventually check for other socket options to change from
1097 the default. sock_setsockopt not used because it expects
1098 user space buffer */
1099 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1105 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1106 char *mount_data, const char *devname)
1110 struct socket *csocket = NULL;
1111 struct sockaddr_in sin_server;
1112 struct sockaddr_in6 sin_server6;
1113 struct smb_vol volume_info;
1114 struct cifsSesInfo *pSesInfo = NULL;
1115 struct cifsSesInfo *existingCifsSes = NULL;
1116 struct cifsTconInfo *tcon = NULL;
1117 struct TCP_Server_Info *srvTcp = NULL;
1121 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1123 memset(&volume_info,0,sizeof(struct smb_vol));
1124 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1126 kfree(volume_info.UNC);
1127 if(volume_info.password)
1128 kfree(volume_info.password);
1133 if (volume_info.username) {
1134 cFYI(1, ("Username: %s ", volume_info.username));
1137 cifserror("No username specified ");
1138 /* In userspace mount helper we can get user name from alternate
1139 locations such as env variables and files on disk */
1141 kfree(volume_info.UNC);
1142 if(volume_info.password)
1143 kfree(volume_info.password);
1148 if (volume_info.UNCip && volume_info.UNC) {
1149 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1152 /* not ipv4 address, try ipv6 */
1153 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1157 /* we failed translating address */
1159 kfree(volume_info.UNC);
1160 if(volume_info.password)
1161 kfree(volume_info.password);
1166 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1169 } else if (volume_info.UNCip){
1170 /* BB using ip addr as server name connect to the DFS root below */
1171 cERROR(1,("Connecting to DFS root not implemented yet"));
1173 kfree(volume_info.UNC);
1174 if(volume_info.password)
1175 kfree(volume_info.password);
1178 } else /* which servers DFS root would we conect to */ {
1180 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1182 kfree(volume_info.UNC);
1183 if(volume_info.password)
1184 kfree(volume_info.password);
1189 /* this is needed for ASCII cp to Unicode converts */
1190 if(volume_info.iocharset == NULL) {
1191 cifs_sb->local_nls = load_nls_default();
1192 /* load_nls_default can not return null */
1194 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1195 if(cifs_sb->local_nls == NULL) {
1196 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1198 kfree(volume_info.UNC);
1199 if(volume_info.password)
1200 kfree(volume_info.password);
1207 cifs_find_tcp_session(sin_server.sin_addr.s_addr,
1208 volume_info.username, &srvTcp);
1210 cFYI(1, ("Existing tcp session with server found "));
1211 } else { /* create socket */
1212 if(volume_info.port)
1213 sin_server.sin_port = htons(volume_info.port);
1215 sin_server.sin_port = 0;
1216 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1219 ("Error connecting to IPv4 socket. Aborting operation"));
1221 sock_release(csocket);
1223 kfree(volume_info.UNC);
1224 if(volume_info.password)
1225 kfree(volume_info.password);
1230 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1231 if (srvTcp == NULL) {
1233 sock_release(csocket);
1235 kfree(volume_info.UNC);
1236 if(volume_info.password)
1237 kfree(volume_info.password);
1241 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1242 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1243 atomic_set(&srvTcp->inFlight,0);
1244 /* BB Add code for ipv6 case too */
1245 srvTcp->ssocket = csocket;
1246 srvTcp->protocolType = IPV4;
1247 init_waitqueue_head(&srvTcp->response_q);
1248 init_waitqueue_head(&srvTcp->request_q);
1249 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1250 /* at this point we are the only ones with the pointer
1251 to the struct since the kernel thread not created yet
1252 so no need to spinlock this init of tcpStatus */
1253 srvTcp->tcpStatus = CifsNew;
1254 init_MUTEX(&srvTcp->tcpSem);
1255 kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1256 CLONE_FS | CLONE_FILES | CLONE_VM);
1257 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1261 if (existingCifsSes) {
1262 pSesInfo = existingCifsSes;
1263 cFYI(1, ("Existing smb sess found "));
1264 if(volume_info.password)
1265 kfree(volume_info.password);
1266 /* volume_info.UNC freed at end of function */
1268 cFYI(1, ("Existing smb sess not found "));
1269 pSesInfo = sesInfoAlloc();
1270 if (pSesInfo == NULL)
1273 pSesInfo->server = srvTcp;
1274 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1275 NIPQUAD(sin_server.sin_addr.s_addr));
1279 /* volume_info.password freed at unmount */
1280 if (volume_info.password)
1281 pSesInfo->password = volume_info.password;
1282 if (volume_info.username)
1283 strncpy(pSesInfo->userName,
1284 volume_info.username,MAX_USERNAME_SIZE);
1285 if (volume_info.domainname)
1286 strncpy(pSesInfo->domainName,
1287 volume_info.domainname,MAX_USERNAME_SIZE);
1288 pSesInfo->linux_uid = volume_info.linux_uid;
1289 down(&pSesInfo->sesSem);
1290 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1291 up(&pSesInfo->sesSem);
1293 atomic_inc(&srvTcp->socketUseCount);
1295 if(volume_info.password)
1296 kfree(volume_info.password);
1299 /* search for existing tcon to this server share */
1301 if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
1302 cifs_sb->rsize = volume_info.rsize;
1304 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1305 if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
1306 cifs_sb->wsize = volume_info.wsize;
1308 cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1309 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1310 cifs_sb->rsize = PAGE_CACHE_SIZE;
1311 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1313 cifs_sb->mnt_uid = volume_info.linux_uid;
1314 cifs_sb->mnt_gid = volume_info.linux_gid;
1315 cifs_sb->mnt_file_mode = volume_info.file_mode;
1316 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1317 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1319 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1320 volume_info.username);
1322 cFYI(1, ("Found match on UNC path "));
1323 /* we can have only one retry value for a connection
1324 to a share so for resources mounted more than once
1325 to the same server share the last value passed in
1326 for the retry flag is used */
1327 tcon->retry = volume_info.retry;
1329 tcon = tconInfoAlloc();
1333 /* check for null share name ie connect to dfs root */
1335 /* BB check if this works for exactly length three strings */
1336 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1337 && (strchr(volume_info.UNC + 3, '/') ==
1339 rc = connect_to_dfs_path(xid,
1345 kfree(volume_info.UNC);
1349 rc = CIFSTCon(xid, pSesInfo,
1351 tcon, cifs_sb->local_nls);
1352 cFYI(1, ("CIFS Tcon rc = %d", rc));
1355 atomic_inc(&pSesInfo->inUse);
1356 tcon->retry = volume_info.retry;
1362 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1363 sb->s_maxbytes = (u64) 1 << 63;
1365 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1368 /* on error free sesinfo and tcon struct if needed */
1370 /* if session setup failed, use count is zero but
1371 we still need to free cifsd thread */
1372 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1373 spin_lock(&GlobalMid_Lock);
1374 srvTcp->tcpStatus = CifsExiting;
1375 spin_unlock(&GlobalMid_Lock);
1377 send_sig(SIGKILL,srvTcp->tsk,1);
1379 /* If find_unc succeeded then rc == 0 so we can not end */
1380 if (tcon) /* up accidently freeing someone elses tcon struct */
1382 if (existingCifsSes == 0) {
1384 if ((pSesInfo->server) &&
1385 (pSesInfo->status == CifsGood)) {
1387 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1388 /* if the socketUseCount is now zero */
1389 if((temp_rc == -ESHUTDOWN) &&
1390 (pSesInfo->server->tsk))
1391 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1393 cFYI(1, ("No session or bad tcon"));
1394 sesInfoFree(pSesInfo);
1395 /* pSesInfo = NULL; */
1399 atomic_inc(&tcon->useCount);
1400 cifs_sb->tcon = tcon;
1401 tcon->ses = pSesInfo;
1403 /* do not care if following two calls succeed - informational only */
1404 CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
1405 CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
1406 if (tcon->ses->capabilities & CAP_UNIX)
1407 CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
1410 /* volume_info.password is freed above when existing session found
1411 (in which case it is not needed anymore) but when new sesion is created
1412 the password ptr is put in the new session structure (in which case the
1413 password will be freed at unmount time) */
1415 kfree(volume_info.UNC);
1421 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1422 char session_key[CIFS_SESSION_KEY_SIZE],
1423 const struct nls_table *nls_codepage)
1425 struct smb_hdr *smb_buffer;
1426 struct smb_hdr *smb_buffer_response;
1427 SESSION_SETUP_ANDX *pSMB;
1428 SESSION_SETUP_ANDX *pSMBr;
1430 char *user = ses->userName;
1431 char *domain = ses->domainName;
1433 int remaining_words = 0;
1434 int bytes_returned = 0;
1437 cFYI(1, ("In sesssetup "));
1439 smb_buffer = cifs_buf_get();
1440 if (smb_buffer == 0) {
1443 smb_buffer_response = smb_buffer;
1444 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1446 /* send SMBsessionSetup here */
1447 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1448 NULL /* no tCon exists yet */ , 13 /* wct */ );
1450 pSMB->req_no_secext.AndXCommand = 0xFF;
1451 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1452 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1454 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1455 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1457 pSMB->req_no_secext.Capabilities =
1458 CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
1459 if (ses->capabilities & CAP_UNICODE) {
1460 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1461 pSMB->req_no_secext.Capabilities |= CAP_UNICODE;
1463 if (ses->capabilities & CAP_STATUS32) {
1464 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1465 pSMB->req_no_secext.Capabilities |= CAP_STATUS32;
1467 if (ses->capabilities & CAP_DFS) {
1468 smb_buffer->Flags2 |= SMBFLG2_DFS;
1469 pSMB->req_no_secext.Capabilities |= CAP_DFS;
1471 pSMB->req_no_secext.Capabilities =
1472 cpu_to_le32(pSMB->req_no_secext.Capabilities);
1473 /* pSMB->req_no_secext.CaseInsensitivePasswordLength =
1474 CIFS_SESSION_KEY_SIZE; */
1475 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
1476 pSMB->req_no_secext.CaseSensitivePasswordLength =
1477 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1478 bcc_ptr = pByteArea(smb_buffer);
1479 /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
1480 bcc_ptr += CIFS_SESSION_KEY_SIZE; */
1481 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1482 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1484 if (ses->capabilities & CAP_UNICODE) {
1485 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1490 bytes_returned = 0; /* skill null user */
1493 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1495 bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
1496 bcc_ptr += 2; /* trailing null */
1499 cifs_strtoUCS((wchar_t *) bcc_ptr,
1500 "CIFS_LINUX_DOM", 32, nls_codepage);
1503 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1505 bcc_ptr += 2 * bytes_returned;
1508 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1510 bcc_ptr += 2 * bytes_returned;
1512 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
1514 bcc_ptr += 2 * bytes_returned;
1517 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1519 bcc_ptr += 2 * bytes_returned;
1523 strncpy(bcc_ptr, user, 200);
1524 bcc_ptr += strnlen(user, 200);
1528 if (domain == NULL) {
1529 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1530 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1532 strncpy(bcc_ptr, domain, 64);
1533 bcc_ptr += strnlen(domain, 64);
1537 strcpy(bcc_ptr, "Linux version ");
1538 bcc_ptr += strlen("Linux version ");
1539 strcpy(bcc_ptr, UTS_RELEASE);
1540 bcc_ptr += strlen(UTS_RELEASE) + 1;
1541 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1542 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1544 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1545 smb_buffer->smb_buf_length += BCC(smb_buffer);
1546 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
1548 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1549 &bytes_returned, 1);
1551 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1552 } else if ((smb_buffer_response->WordCount == 3)
1553 || (smb_buffer_response->WordCount == 4)) {
1554 pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
1555 if (pSMBr->resp.Action & GUEST_LOGIN)
1556 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1558 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1559 cFYI(1, ("UID = %d ", ses->Suid));
1560 /* response can have either 3 or 4 word count - Samba sends 3 */
1561 bcc_ptr = pByteArea(smb_buffer_response);
1562 if ((pSMBr->resp.hdr.WordCount == 3)
1563 || ((pSMBr->resp.hdr.WordCount == 4)
1564 && (pSMBr->resp.SecurityBlobLength <
1565 pSMBr->resp.ByteCount))) {
1566 if (pSMBr->resp.hdr.WordCount == 4)
1568 pSMBr->resp.SecurityBlobLength;
1570 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1571 if ((long) (bcc_ptr) % 2) {
1573 (BCC(smb_buffer_response)
1575 bcc_ptr++; /* Unicode strings must be word aligned */
1579 (smb_buffer_response) / 2;
1582 UniStrnlen((wchar_t *) bcc_ptr,
1583 remaining_words - 1);
1584 /* We look for obvious messed up bcc or strings in response so we do not go off
1585 the end since (at least) WIN2K and Windows XP have a major bug in not null
1586 terminating last Unicode string in response */
1587 ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1588 cifs_strfromUCS_le(ses->serverOS,
1589 (wchar_t *)bcc_ptr, len,nls_codepage);
1590 bcc_ptr += 2 * (len + 1);
1591 remaining_words -= len + 1;
1592 ses->serverOS[2 * len] = 0;
1593 ses->serverOS[1 + (2 * len)] = 0;
1594 if (remaining_words > 0) {
1595 len = UniStrnlen((wchar_t *)bcc_ptr,
1598 ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
1599 cifs_strfromUCS_le(ses->serverNOS,
1600 (wchar_t *)bcc_ptr,len,nls_codepage);
1601 bcc_ptr += 2 * (len + 1);
1602 ses->serverNOS[2 * len] = 0;
1603 ses->serverNOS[1 + (2 * len)] = 0;
1604 remaining_words -= len + 1;
1605 if (remaining_words > 0) {
1606 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1607 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1609 cifs_kcalloc(2*(len+1),GFP_KERNEL);
1610 cifs_strfromUCS_le(ses->serverDomain,
1611 (wchar_t *)bcc_ptr,len,nls_codepage);
1612 bcc_ptr += 2 * (len + 1);
1613 ses->serverDomain[2*len] = 0;
1614 ses->serverDomain[1+(2*len)] = 0;
1615 } /* else no more room so create dummy domain string */
1620 } else { /* no room so create dummy domain and NOS string */
1622 cifs_kcalloc(2, GFP_KERNEL);
1624 cifs_kcalloc(2, GFP_KERNEL);
1626 } else { /* ASCII */
1627 len = strnlen(bcc_ptr, 1024);
1628 if (((long) bcc_ptr + len) - (long)
1629 pByteArea(smb_buffer_response)
1630 <= BCC(smb_buffer_response)) {
1631 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1632 strncpy(ses->serverOS,bcc_ptr, len);
1635 bcc_ptr[0] = 0; /* null terminate the string */
1638 len = strnlen(bcc_ptr, 1024);
1639 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1640 strncpy(ses->serverNOS, bcc_ptr, len);
1645 len = strnlen(bcc_ptr, 1024);
1646 ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
1647 strncpy(ses->serverDomain, bcc_ptr, len);
1653 ("Variable field of length %d extends beyond end of smb ",
1658 (" Security Blob Length extends beyond end of SMB"));
1661 cERROR(1, ("No session structure passed in."));
1665 (" Invalid Word count %d: ",
1666 smb_buffer_response->WordCount));
1671 cifs_buf_release(smb_buffer);
1677 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1678 char *SecurityBlob,int SecurityBlobLength,
1679 const struct nls_table *nls_codepage)
1681 struct smb_hdr *smb_buffer;
1682 struct smb_hdr *smb_buffer_response;
1683 SESSION_SETUP_ANDX *pSMB;
1684 SESSION_SETUP_ANDX *pSMBr;
1686 char *user = ses->userName;
1687 char *domain = ses->domainName;
1689 int remaining_words = 0;
1690 int bytes_returned = 0;
1693 cFYI(1, ("In spnego sesssetup "));
1695 smb_buffer = cifs_buf_get();
1696 if (smb_buffer == 0) {
1699 smb_buffer_response = smb_buffer;
1700 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1702 /* send SMBsessionSetup here */
1703 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1704 NULL /* no tCon exists yet */ , 12 /* wct */ );
1705 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1706 pSMB->req.AndXCommand = 0xFF;
1707 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1708 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1710 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1711 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1713 pSMB->req.Capabilities =
1714 CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1715 CAP_EXTENDED_SECURITY;
1716 if (ses->capabilities & CAP_UNICODE) {
1717 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1718 pSMB->req.Capabilities |= CAP_UNICODE;
1720 if (ses->capabilities & CAP_STATUS32) {
1721 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1722 pSMB->req.Capabilities |= CAP_STATUS32;
1724 if (ses->capabilities & CAP_DFS) {
1725 smb_buffer->Flags2 |= SMBFLG2_DFS;
1726 pSMB->req.Capabilities |= CAP_DFS;
1728 pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
1730 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1731 bcc_ptr = pByteArea(smb_buffer);
1732 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1733 bcc_ptr += SecurityBlobLength;
1735 if (ses->capabilities & CAP_UNICODE) {
1736 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1741 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1742 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1743 bcc_ptr += 2; /* trailing null */
1746 cifs_strtoUCS((wchar_t *) bcc_ptr,
1747 "CIFS_LINUX_DOM", 32, nls_codepage);
1750 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1752 bcc_ptr += 2 * bytes_returned;
1755 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1757 bcc_ptr += 2 * bytes_returned;
1759 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
1761 bcc_ptr += 2 * bytes_returned;
1764 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1766 bcc_ptr += 2 * bytes_returned;
1769 strncpy(bcc_ptr, user, 200);
1770 bcc_ptr += strnlen(user, 200);
1773 if (domain == NULL) {
1774 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1775 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1777 strncpy(bcc_ptr, domain, 64);
1778 bcc_ptr += strnlen(domain, 64);
1782 strcpy(bcc_ptr, "Linux version ");
1783 bcc_ptr += strlen("Linux version ");
1784 strcpy(bcc_ptr, UTS_RELEASE);
1785 bcc_ptr += strlen(UTS_RELEASE) + 1;
1786 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1787 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1789 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1790 smb_buffer->smb_buf_length += BCC(smb_buffer);
1791 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
1793 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1794 &bytes_returned, 1);
1796 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1797 } else if ((smb_buffer_response->WordCount == 3)
1798 || (smb_buffer_response->WordCount == 4)) {
1799 pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
1800 pSMBr->resp.SecurityBlobLength =
1801 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1802 if (pSMBr->resp.Action & GUEST_LOGIN)
1803 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1805 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1806 cFYI(1, ("UID = %d ", ses->Suid));
1807 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
1809 /* BB Fix below to make endian neutral !! */
1811 if ((pSMBr->resp.hdr.WordCount == 3)
1812 || ((pSMBr->resp.hdr.WordCount == 4)
1813 && (pSMBr->resp.SecurityBlobLength <
1814 pSMBr->resp.ByteCount))) {
1815 if (pSMBr->resp.hdr.WordCount == 4) {
1817 pSMBr->resp.SecurityBlobLength;
1819 ("Security Blob Length %d ",
1820 pSMBr->resp.SecurityBlobLength));
1823 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1824 if ((long) (bcc_ptr) % 2) {
1826 (BCC(smb_buffer_response)
1828 bcc_ptr++; /* Unicode strings must be word aligned */
1832 (smb_buffer_response) / 2;
1835 UniStrnlen((wchar_t *) bcc_ptr,
1836 remaining_words - 1);
1837 /* We look for obvious messed up bcc or strings in response so we do not go off
1838 the end since (at least) WIN2K and Windows XP have a major bug in not null
1839 terminating last Unicode string in response */
1841 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1842 cifs_strfromUCS_le(ses->serverOS,
1846 bcc_ptr += 2 * (len + 1);
1847 remaining_words -= len + 1;
1848 ses->serverOS[2 * len] = 0;
1849 ses->serverOS[1 + (2 * len)] = 0;
1850 if (remaining_words > 0) {
1851 len = UniStrnlen((wchar_t *)bcc_ptr,
1855 cifs_kcalloc(2 * (len + 1),
1857 cifs_strfromUCS_le(ses->serverNOS,
1861 bcc_ptr += 2 * (len + 1);
1862 ses->serverNOS[2 * len] = 0;
1863 ses->serverNOS[1 + (2 * len)] = 0;
1864 remaining_words -= len + 1;
1865 if (remaining_words > 0) {
1866 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1867 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1868 ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
1869 cifs_strfromUCS_le(ses->serverDomain,
1873 bcc_ptr += 2*(len+1);
1874 ses->serverDomain[2*len] = 0;
1875 ses->serverDomain[1+(2*len)] = 0;
1876 } /* else no more room so create dummy domain string */
1879 cifs_kcalloc(2,GFP_KERNEL);
1880 } else { /* no room so create dummy domain and NOS string */
1881 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
1882 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
1884 } else { /* ASCII */
1886 len = strnlen(bcc_ptr, 1024);
1887 if (((long) bcc_ptr + len) - (long)
1888 pByteArea(smb_buffer_response)
1889 <= BCC(smb_buffer_response)) {
1890 ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
1891 strncpy(ses->serverOS, bcc_ptr, len);
1894 bcc_ptr[0] = 0; /* null terminate the string */
1897 len = strnlen(bcc_ptr, 1024);
1898 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1899 strncpy(ses->serverNOS, bcc_ptr, len);
1904 len = strnlen(bcc_ptr, 1024);
1905 ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
1906 strncpy(ses->serverDomain, bcc_ptr, len);
1912 ("Variable field of length %d extends beyond end of smb ",
1917 (" Security Blob Length extends beyond end of SMB"));
1920 cERROR(1, ("No session structure passed in."));
1924 (" Invalid Word count %d: ",
1925 smb_buffer_response->WordCount));
1930 cifs_buf_release(smb_buffer);
1936 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
1937 struct cifsSesInfo *ses, int * pNTLMv2_flag,
1938 const struct nls_table *nls_codepage)
1940 struct smb_hdr *smb_buffer;
1941 struct smb_hdr *smb_buffer_response;
1942 SESSION_SETUP_ANDX *pSMB;
1943 SESSION_SETUP_ANDX *pSMBr;
1945 char *domain = ses->domainName;
1947 int remaining_words = 0;
1948 int bytes_returned = 0;
1950 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
1951 PNEGOTIATE_MESSAGE SecurityBlob;
1952 PCHALLENGE_MESSAGE SecurityBlob2;
1954 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
1955 *pNTLMv2_flag = FALSE;
1956 smb_buffer = cifs_buf_get();
1957 if (smb_buffer == 0) {
1960 smb_buffer_response = smb_buffer;
1961 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1962 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
1964 /* send SMBsessionSetup here */
1965 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1966 NULL /* no tCon exists yet */ , 12 /* wct */ );
1967 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1968 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
1970 pSMB->req.AndXCommand = 0xFF;
1971 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1972 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1974 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1975 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1977 pSMB->req.Capabilities =
1978 CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1979 CAP_EXTENDED_SECURITY;
1980 if (ses->capabilities & CAP_UNICODE) {
1981 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1982 pSMB->req.Capabilities |= CAP_UNICODE;
1984 if (ses->capabilities & CAP_STATUS32) {
1985 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1986 pSMB->req.Capabilities |= CAP_STATUS32;
1988 if (ses->capabilities & CAP_DFS) {
1989 smb_buffer->Flags2 |= SMBFLG2_DFS;
1990 pSMB->req.Capabilities |= CAP_DFS;
1992 pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
1994 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
1995 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
1996 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
1997 SecurityBlob->MessageType = NtLmNegotiate;
1998 SecurityBlob->NegotiateFlags =
1999 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2000 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2001 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2003 SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
2005 SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
2006 /* setup pointers to domain name and workstation name */
2007 bcc_ptr += SecurityBlobLength;
2009 SecurityBlob->WorkstationName.Buffer = 0;
2010 SecurityBlob->WorkstationName.Length = 0;
2011 SecurityBlob->WorkstationName.MaximumLength = 0;
2013 if (domain == NULL) {
2014 SecurityBlob->DomainName.Buffer = 0;
2015 SecurityBlob->DomainName.Length = 0;
2016 SecurityBlob->DomainName.MaximumLength = 0;
2018 SecurityBlob->NegotiateFlags |=
2019 NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2020 strncpy(bcc_ptr, domain, 63);
2021 SecurityBlob->DomainName.Length = strnlen(domain, 64);
2022 SecurityBlob->DomainName.MaximumLength =
2023 cpu_to_le16(SecurityBlob->DomainName.Length);
2024 SecurityBlob->DomainName.Buffer =
2025 cpu_to_le32((long) &SecurityBlob->
2027 (long) &SecurityBlob->Signature);
2028 bcc_ptr += SecurityBlob->DomainName.Length;
2029 SecurityBlobLength += SecurityBlob->DomainName.Length;
2030 SecurityBlob->DomainName.Length =
2031 cpu_to_le16(SecurityBlob->DomainName.Length);
2033 if (ses->capabilities & CAP_UNICODE) {
2034 if ((long) bcc_ptr % 2) {
2040 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2042 bcc_ptr += 2 * bytes_returned;
2044 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
2046 bcc_ptr += 2 * bytes_returned;
2047 bcc_ptr += 2; /* null terminate Linux version */
2049 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2051 bcc_ptr += 2 * bytes_returned;
2054 bcc_ptr += 2; /* null terminate network opsys string */
2057 bcc_ptr += 2; /* null domain */
2058 } else { /* ASCII */
2059 strcpy(bcc_ptr, "Linux version ");
2060 bcc_ptr += strlen("Linux version ");
2061 strcpy(bcc_ptr, UTS_RELEASE);
2062 bcc_ptr += strlen(UTS_RELEASE) + 1;
2063 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2064 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2065 bcc_ptr++; /* empty domain field */
2068 SecurityBlob->NegotiateFlags =
2069 cpu_to_le32(SecurityBlob->NegotiateFlags);
2070 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2071 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2072 smb_buffer->smb_buf_length += BCC(smb_buffer);
2073 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
2075 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2076 &bytes_returned, 1);
2078 if (smb_buffer_response->Status.CifsError ==
2079 (NT_STATUS_MORE_PROCESSING_REQUIRED))
2083 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2084 } else if ((smb_buffer_response->WordCount == 3)
2085 || (smb_buffer_response->WordCount == 4)) {
2086 pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
2087 pSMBr->resp.SecurityBlobLength =
2088 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2089 if (pSMBr->resp.Action & GUEST_LOGIN)
2090 cFYI(1, (" Guest login"));
2091 /* Do we want to set anything in SesInfo struct when guest login? */
2093 bcc_ptr = pByteArea(smb_buffer_response);
2094 /* response can have either 3 or 4 word count - Samba sends 3 */
2096 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2097 if (SecurityBlob2->MessageType != NtLmChallenge) {
2099 ("Unexpected NTLMSSP message type received %d",
2100 SecurityBlob2->MessageType));
2102 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2103 cFYI(1, ("UID = %d ", ses->Suid));
2104 if ((pSMBr->resp.hdr.WordCount == 3)
2105 || ((pSMBr->resp.hdr.WordCount == 4)
2106 && (pSMBr->resp.SecurityBlobLength <
2107 pSMBr->resp.ByteCount))) {
2108 if (pSMBr->resp.hdr.WordCount == 4) {
2110 pSMBr->resp.SecurityBlobLength;
2112 ("Security Blob Length %d ",
2113 pSMBr->resp.SecurityBlobLength));
2116 cFYI(1, ("NTLMSSP Challenge rcvd "));
2118 memcpy(ses->server->cryptKey,
2119 SecurityBlob2->Challenge,
2120 CIFS_CRYPTO_KEY_SIZE);
2121 if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
2122 *pNTLMv2_flag = TRUE;
2124 if((SecurityBlob2->NegotiateFlags &
2125 NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
2126 || (sign_CIFS_PDUs > 1))
2127 ses->server->secMode |=
2128 SECMODE_SIGN_REQUIRED;
2129 if ((SecurityBlob2->NegotiateFlags &
2130 NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
2131 ses->server->secMode |=
2132 SECMODE_SIGN_ENABLED;
2134 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2135 if ((long) (bcc_ptr) % 2) {
2137 (BCC(smb_buffer_response)
2139 bcc_ptr++; /* Unicode strings must be word aligned */
2143 (smb_buffer_response) / 2;
2146 UniStrnlen((wchar_t *) bcc_ptr,
2147 remaining_words - 1);
2148 /* We look for obvious messed up bcc or strings in response so we do not go off
2149 the end since (at least) WIN2K and Windows XP have a major bug in not null
2150 terminating last Unicode string in response */
2152 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2153 cifs_strfromUCS_le(ses->serverOS,
2157 bcc_ptr += 2 * (len + 1);
2158 remaining_words -= len + 1;
2159 ses->serverOS[2 * len] = 0;
2160 ses->serverOS[1 + (2 * len)] = 0;
2161 if (remaining_words > 0) {
2162 len = UniStrnlen((wchar_t *)
2167 cifs_kcalloc(2 * (len + 1),
2169 cifs_strfromUCS_le(ses->
2175 bcc_ptr += 2 * (len + 1);
2176 ses->serverNOS[2 * len] = 0;
2179 remaining_words -= len + 1;
2180 if (remaining_words > 0) {
2181 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2182 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2207 } /* else no more room so create dummy domain string */
2212 } else { /* no room so create dummy domain and NOS string */
2214 cifs_kcalloc(2, GFP_KERNEL);
2216 cifs_kcalloc(2, GFP_KERNEL);
2218 } else { /* ASCII */
2219 len = strnlen(bcc_ptr, 1024);
2220 if (((long) bcc_ptr + len) - (long)
2221 pByteArea(smb_buffer_response)
2222 <= BCC(smb_buffer_response)) {
2224 cifs_kcalloc(len + 1,
2226 strncpy(ses->serverOS,
2230 bcc_ptr[0] = 0; /* null terminate string */
2233 len = strnlen(bcc_ptr, 1024);
2235 cifs_kcalloc(len + 1,
2237 strncpy(ses->serverNOS, bcc_ptr, len);
2242 len = strnlen(bcc_ptr, 1024);
2244 cifs_kcalloc(len + 1,
2246 strncpy(ses->serverDomain, bcc_ptr, len);
2252 ("Variable field of length %d extends beyond end of smb ",
2257 (" Security Blob Length extends beyond end of SMB"));
2260 cERROR(1, ("No session structure passed in."));
2264 (" Invalid Word count %d: ",
2265 smb_buffer_response->WordCount));
2270 cifs_buf_release(smb_buffer);
2276 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2277 char *ntlm_session_key, int ntlmv2_flag,
2278 const struct nls_table *nls_codepage)
2280 struct smb_hdr *smb_buffer;
2281 struct smb_hdr *smb_buffer_response;
2282 SESSION_SETUP_ANDX *pSMB;
2283 SESSION_SETUP_ANDX *pSMBr;
2285 char *user = ses->userName;
2286 char *domain = ses->domainName;
2288 int remaining_words = 0;
2289 int bytes_returned = 0;
2291 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2292 PAUTHENTICATE_MESSAGE SecurityBlob;
2294 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2296 smb_buffer = cifs_buf_get();
2297 if (smb_buffer == 0) {
2300 smb_buffer_response = smb_buffer;
2301 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2302 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2304 /* send SMBsessionSetup here */
2305 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2306 NULL /* no tCon exists yet */ , 12 /* wct */ );
2307 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2308 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2309 pSMB->req.AndXCommand = 0xFF;
2310 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2311 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2313 pSMB->req.hdr.Uid = ses->Suid;
2315 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2316 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2318 pSMB->req.Capabilities =
2319 CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2320 CAP_EXTENDED_SECURITY;
2321 if (ses->capabilities & CAP_UNICODE) {
2322 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2323 pSMB->req.Capabilities |= CAP_UNICODE;
2325 if (ses->capabilities & CAP_STATUS32) {
2326 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2327 pSMB->req.Capabilities |= CAP_STATUS32;
2329 if (ses->capabilities & CAP_DFS) {
2330 smb_buffer->Flags2 |= SMBFLG2_DFS;
2331 pSMB->req.Capabilities |= CAP_DFS;
2333 pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
2335 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2336 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2337 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2338 SecurityBlob->MessageType = NtLmAuthenticate;
2339 bcc_ptr += SecurityBlobLength;
2340 SecurityBlob->NegotiateFlags =
2341 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2342 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2343 0x80000000 | NTLMSSP_NEGOTIATE_128;
2345 SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2347 SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
2349 /* setup pointers to domain name and workstation name */
2351 SecurityBlob->WorkstationName.Buffer = 0;
2352 SecurityBlob->WorkstationName.Length = 0;
2353 SecurityBlob->WorkstationName.MaximumLength = 0;
2354 SecurityBlob->SessionKey.Length = 0;
2355 SecurityBlob->SessionKey.MaximumLength = 0;
2356 SecurityBlob->SessionKey.Buffer = 0;
2358 SecurityBlob->LmChallengeResponse.Length = 0;
2359 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2360 SecurityBlob->LmChallengeResponse.Buffer = 0;
2362 SecurityBlob->NtChallengeResponse.Length =
2363 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2364 SecurityBlob->NtChallengeResponse.MaximumLength =
2365 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2366 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2367 SecurityBlob->NtChallengeResponse.Buffer =
2368 cpu_to_le32(SecurityBlobLength);
2369 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2370 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2372 if (ses->capabilities & CAP_UNICODE) {
2373 if (domain == NULL) {
2374 SecurityBlob->DomainName.Buffer = 0;
2375 SecurityBlob->DomainName.Length = 0;
2376 SecurityBlob->DomainName.MaximumLength = 0;
2378 SecurityBlob->DomainName.Length =
2379 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2381 SecurityBlob->DomainName.Length *= 2;
2382 SecurityBlob->DomainName.MaximumLength =
2383 cpu_to_le16(SecurityBlob->DomainName.Length);
2384 SecurityBlob->DomainName.Buffer =
2385 cpu_to_le32(SecurityBlobLength);
2386 bcc_ptr += SecurityBlob->DomainName.Length;
2387 SecurityBlobLength += SecurityBlob->DomainName.Length;
2388 SecurityBlob->DomainName.Length =
2389 cpu_to_le16(SecurityBlob->DomainName.Length);
2392 SecurityBlob->UserName.Buffer = 0;
2393 SecurityBlob->UserName.Length = 0;
2394 SecurityBlob->UserName.MaximumLength = 0;
2396 SecurityBlob->UserName.Length =
2397 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2399 SecurityBlob->UserName.Length *= 2;
2400 SecurityBlob->UserName.MaximumLength =
2401 cpu_to_le16(SecurityBlob->UserName.Length);
2402 SecurityBlob->UserName.Buffer =
2403 cpu_to_le32(SecurityBlobLength);
2404 bcc_ptr += SecurityBlob->UserName.Length;
2405 SecurityBlobLength += SecurityBlob->UserName.Length;
2406 SecurityBlob->UserName.Length =
2407 cpu_to_le16(SecurityBlob->UserName.Length);
2410 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2411 SecurityBlob->WorkstationName.Length *= 2;
2412 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2413 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2414 bcc_ptr += SecurityBlob->WorkstationName.Length;
2415 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2416 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2418 if ((long) bcc_ptr % 2) {
2423 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2425 bcc_ptr += 2 * bytes_returned;
2427 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
2429 bcc_ptr += 2 * bytes_returned;
2430 bcc_ptr += 2; /* null term version string */
2432 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2434 bcc_ptr += 2 * bytes_returned;
2437 bcc_ptr += 2; /* null terminate network opsys string */
2440 bcc_ptr += 2; /* null domain */
2441 } else { /* ASCII */
2442 if (domain == NULL) {
2443 SecurityBlob->DomainName.Buffer = 0;
2444 SecurityBlob->DomainName.Length = 0;
2445 SecurityBlob->DomainName.MaximumLength = 0;
2447 SecurityBlob->NegotiateFlags |=
2448 NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2449 strncpy(bcc_ptr, domain, 63);
2450 SecurityBlob->DomainName.Length = strnlen(domain, 64);
2451 SecurityBlob->DomainName.MaximumLength =
2452 cpu_to_le16(SecurityBlob->DomainName.Length);
2453 SecurityBlob->DomainName.Buffer =
2454 cpu_to_le32(SecurityBlobLength);
2455 bcc_ptr += SecurityBlob->DomainName.Length;
2456 SecurityBlobLength += SecurityBlob->DomainName.Length;
2457 SecurityBlob->DomainName.Length =
2458 cpu_to_le16(SecurityBlob->DomainName.Length);
2461 SecurityBlob->UserName.Buffer = 0;
2462 SecurityBlob->UserName.Length = 0;
2463 SecurityBlob->UserName.MaximumLength = 0;
2465 strncpy(bcc_ptr, user, 63);
2466 SecurityBlob->UserName.Length = strnlen(user, 64);
2467 SecurityBlob->UserName.MaximumLength =
2468 cpu_to_le16(SecurityBlob->UserName.Length);
2469 SecurityBlob->UserName.Buffer =
2470 cpu_to_le32(SecurityBlobLength);
2471 bcc_ptr += SecurityBlob->UserName.Length;
2472 SecurityBlobLength += SecurityBlob->UserName.Length;
2473 SecurityBlob->UserName.Length =
2474 cpu_to_le16(SecurityBlob->UserName.Length);
2476 /* BB fill in our workstation name if known BB */
2478 strcpy(bcc_ptr, "Linux version ");
2479 bcc_ptr += strlen("Linux version ");
2480 strcpy(bcc_ptr, UTS_RELEASE);
2481 bcc_ptr += strlen(UTS_RELEASE) + 1;
2482 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2483 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2484 bcc_ptr++; /* null domain */
2487 SecurityBlob->NegotiateFlags =
2488 cpu_to_le32(SecurityBlob->NegotiateFlags);
2489 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2490 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2491 smb_buffer->smb_buf_length += BCC(smb_buffer);
2492 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
2494 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2495 &bytes_returned, 1);
2497 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2498 } else if ((smb_buffer_response->WordCount == 3)
2499 || (smb_buffer_response->WordCount == 4)) {
2500 pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
2501 pSMBr->resp.SecurityBlobLength =
2502 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2503 if (pSMBr->resp.Action & GUEST_LOGIN)
2504 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2505 /* if(SecurityBlob2->MessageType != NtLm??){
2506 cFYI("Unexpected message type on auth response is %d "));
2510 ("Does UID on challenge %d match auth response UID %d ",
2511 ses->Suid, smb_buffer_response->Uid));
2512 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2513 bcc_ptr = pByteArea(smb_buffer_response);
2514 /* response can have either 3 or 4 word count - Samba sends 3 */
2515 if ((pSMBr->resp.hdr.WordCount == 3)
2516 || ((pSMBr->resp.hdr.WordCount == 4)
2517 && (pSMBr->resp.SecurityBlobLength <
2518 pSMBr->resp.ByteCount))) {
2519 if (pSMBr->resp.hdr.WordCount == 4) {
2521 pSMBr->resp.SecurityBlobLength;
2523 ("Security Blob Length %d ",
2524 pSMBr->resp.SecurityBlobLength));
2528 ("NTLMSSP response to Authenticate "));
2530 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2531 if ((long) (bcc_ptr) % 2) {
2533 (BCC(smb_buffer_response)
2535 bcc_ptr++; /* Unicode strings must be word aligned */
2537 remaining_words = BCC(smb_buffer_response) / 2;
2540 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2541 /* We look for obvious messed up bcc or strings in response so we do not go off
2542 the end since (at least) WIN2K and Windows XP have a major bug in not null
2543 terminating last Unicode string in response */
2545 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2546 cifs_strfromUCS_le(ses->serverOS,
2550 bcc_ptr += 2 * (len + 1);
2551 remaining_words -= len + 1;
2552 ses->serverOS[2 * len] = 0;
2553 ses->serverOS[1 + (2 * len)] = 0;
2554 if (remaining_words > 0) {
2555 len = UniStrnlen((wchar_t *)
2560 cifs_kcalloc(2 * (len + 1),
2562 cifs_strfromUCS_le(ses->
2568 bcc_ptr += 2 * (len + 1);
2569 ses->serverNOS[2 * len] = 0;
2570 ses->serverNOS[1+(2*len)] = 0;
2571 remaining_words -= len + 1;
2572 if (remaining_words > 0) {
2573 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2574 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2599 } /* else no more room so create dummy domain string */
2601 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
2602 } else { /* no room so create dummy domain and NOS string */
2603 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2604 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2606 } else { /* ASCII */
2607 len = strnlen(bcc_ptr, 1024);
2608 if (((long) bcc_ptr + len) -
2609 (long) pByteArea(smb_buffer_response)
2610 <= BCC(smb_buffer_response)) {
2611 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2612 strncpy(ses->serverOS,bcc_ptr, len);
2615 bcc_ptr[0] = 0; /* null terminate the string */
2618 len = strnlen(bcc_ptr, 1024);
2619 ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
2620 strncpy(ses->serverNOS, bcc_ptr, len);
2625 len = strnlen(bcc_ptr, 1024);
2626 ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
2627 strncpy(ses->serverDomain, bcc_ptr, len);
2633 ("Variable field of length %d extends beyond end of smb ",
2638 (" Security Blob Length extends beyond end of SMB"));
2641 cERROR(1, ("No session structure passed in."));
2645 (" Invalid Word count %d: ",
2646 smb_buffer_response->WordCount));
2651 cifs_buf_release(smb_buffer);
2657 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2658 const char *tree, struct cifsTconInfo *tcon,
2659 const struct nls_table *nls_codepage)
2661 struct smb_hdr *smb_buffer;
2662 struct smb_hdr *smb_buffer_response;
2672 smb_buffer = cifs_buf_get();
2673 if (smb_buffer == 0) {
2676 smb_buffer_response = smb_buffer;
2678 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2679 NULL /*no tid */ , 4 /*wct */ );
2680 smb_buffer->Uid = ses->Suid;
2681 pSMB = (TCONX_REQ *) smb_buffer;
2682 pSMBr = (TCONX_RSP *) smb_buffer_response;
2684 pSMB->AndXCommand = 0xFF;
2685 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2686 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2687 bcc_ptr = &(pSMB->Password[0]);
2688 bcc_ptr++; /* skip password */
2690 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2691 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2693 if (ses->capabilities & CAP_STATUS32) {
2694 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2696 if (ses->capabilities & CAP_DFS) {
2697 smb_buffer->Flags2 |= SMBFLG2_DFS;
2699 if (ses->capabilities & CAP_UNICODE) {
2700 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2702 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2703 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2704 bcc_ptr += 2; /* skip trailing null */
2705 } else { /* ASCII */
2707 strcpy(bcc_ptr, tree);
2708 bcc_ptr += strlen(tree) + 1;
2710 strcpy(bcc_ptr, "?????");
2711 bcc_ptr += strlen("?????");
2713 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2714 smb_buffer->smb_buf_length += BCC(smb_buffer);
2715 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
2717 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2719 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2720 /* above now done in SendReceive */
2721 if ((rc == 0) && (tcon != NULL)) {
2722 tcon->tidStatus = CifsGood;
2723 tcon->tid = smb_buffer_response->Tid;
2724 bcc_ptr = pByteArea(smb_buffer_response);
2725 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2726 /* skip service field (NB: this field is always ASCII) */
2727 bcc_ptr += length + 1;
2728 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2729 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2730 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2731 if (((long) bcc_ptr + (2 * length)) -
2732 (long) pByteArea(smb_buffer_response) <=
2733 BCC(smb_buffer_response)) {
2734 if(tcon->nativeFileSystem)
2735 kfree(tcon->nativeFileSystem);
2736 tcon->nativeFileSystem =
2737 cifs_kcalloc(length + 2, GFP_KERNEL);
2738 cifs_strfromUCS_le(tcon->nativeFileSystem,
2739 (wchar_t *) bcc_ptr,
2740 length, nls_codepage);
2741 bcc_ptr += 2 * length;
2742 bcc_ptr[0] = 0; /* null terminate the string */
2746 /* else do not bother copying these informational fields */
2748 length = strnlen(bcc_ptr, 1024);
2749 if (((long) bcc_ptr + length) -
2750 (long) pByteArea(smb_buffer_response) <=
2751 BCC(smb_buffer_response)) {
2752 if(tcon->nativeFileSystem)
2753 kfree(tcon->nativeFileSystem);
2754 tcon->nativeFileSystem =
2755 cifs_kcalloc(length + 1, GFP_KERNEL);
2756 strncpy(tcon->nativeFileSystem, bcc_ptr,
2759 /* else do not bother copying these informational fields */
2761 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2762 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2763 } else if ((rc == 0) && tcon == NULL) {
2764 /* all we need to save for IPC$ connection */
2765 ses->ipc_tid = smb_buffer_response->Tid;
2769 cifs_buf_release(smb_buffer);
2774 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
2778 struct cifsSesInfo *ses = NULL;
2779 struct task_struct *cifsd_task;
2783 if (cifs_sb->tcon) {
2784 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
2785 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
2790 tconInfoFree(cifs_sb->tcon);
2791 if ((ses) && (ses->server)) {
2792 /* save off task so we do not refer to ses later */
2793 cifsd_task = ses->server->tsk;
2794 cFYI(1, ("About to do SMBLogoff "));
2795 rc = CIFSSMBLogoff(xid, ses);
2799 } else if (rc == -ESHUTDOWN) {
2800 cFYI(1,("Waking up socket by sending it signal"));
2801 send_sig(SIGKILL,cifsd_task,1);
2803 } /* else - we have an smb session
2804 left on this socket do not kill cifsd */
2806 cFYI(1, ("No session or bad tcon"));
2809 cifs_sb->tcon = NULL;
2811 set_current_state(TASK_INTERRUPTIBLE);
2812 schedule_timeout(HZ / 2);
2818 return rc; /* BB check if we should always return zero here */
2821 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2822 struct nls_table * nls_info)
2825 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
2826 int ntlmv2_flag = FALSE;
2828 /* what if server changes its buffer size after dropping the session? */
2829 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
2830 rc = CIFSSMBNegotiate(xid, pSesInfo);
2831 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
2832 rc = CIFSSMBNegotiate(xid, pSesInfo);
2837 spin_lock(&GlobalMid_Lock);
2838 if(pSesInfo->server->tcpStatus != CifsExiting)
2839 pSesInfo->server->tcpStatus = CifsGood;
2842 spin_unlock(&GlobalMid_Lock);
2847 pSesInfo->capabilities = pSesInfo->server->capabilities;
2848 if(linuxExtEnabled == 0)
2849 pSesInfo->capabilities &= (~CAP_UNIX);
2850 pSesInfo->sequence_number = 0;
2851 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2852 pSesInfo->server->secMode,
2853 pSesInfo->server->capabilities,
2854 pSesInfo->server->timeZone));
2855 if (extended_security
2856 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
2857 && (pSesInfo->server->secType == NTLMSSP)) {
2858 cFYI(1, ("New style sesssetup "));
2859 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
2860 NULL /* security blob */,
2861 0 /* blob length */,
2863 } else if (extended_security
2864 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
2865 && (pSesInfo->server->secType == RawNTLMSSP)) {
2866 cFYI(1, ("NTLMSSP sesssetup "));
2867 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
2874 cFYI(1,("Can use more secure NTLM version 2 password hash"));
2875 CalcNTLMv2_partial_mac_key(pSesInfo,
2877 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
2879 CalcNTLMv2_response(pSesInfo,v2_response);
2880 /* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
2882 /* BB Put dummy sig in SessSetup PDU? */
2887 SMBNTencrypt(pSesInfo->password,
2888 pSesInfo->server->cryptKey,
2891 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
2893 pSesInfo->password);
2895 /* for better security the weaker lanman hash not sent
2896 in AuthSessSetup so we no longer calculate it */
2898 rc = CIFSNTLMSSPAuthSessSetup(xid,
2904 } else { /* old style NTLM 0.12 session setup */
2905 SMBNTencrypt(pSesInfo->password,
2906 pSesInfo->server->cryptKey,
2909 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
2910 ntlm_session_key, pSesInfo->password);
2911 rc = CIFSSessSetup(xid, pSesInfo,
2912 ntlm_session_key, nls_info);
2915 cERROR(1,("Send error in SessSetup = %d",rc));
2917 cFYI(1,("CIFS Session Established successfully"));
2918 pSesInfo->status = CifsGood;