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 */
69 unsigned short int port;
72 static int ipv4_connect(struct sockaddr_in *psin_server,
73 struct socket **csocket,
75 static int ipv6_connect(struct sockaddr_in6 *psin_server,
76 struct socket **csocket);
80 * cifs tcp session reconnection
82 * mark tcp session as reconnecting so temporarily locked
83 * mark all smb sessions as reconnecting for tcp session
84 * reconnect tcp session
85 * wake up waiters on reconnection? - (not needed currently)
89 cifs_reconnect(struct TCP_Server_Info *server)
92 struct list_head *tmp;
93 struct cifsSesInfo *ses;
94 struct cifsTconInfo *tcon;
95 struct mid_q_entry * mid_entry;
97 if(server->tcpStatus == CifsExiting)
99 server->tcpStatus = CifsNeedReconnect;
102 cFYI(1, ("Reconnecting tcp session "));
104 /* before reconnecting the tcp session, mark the smb session (uid)
105 and the tid bad so they are not used until reconnected */
106 read_lock(&GlobalSMBSeslock);
107 list_for_each(tmp, &GlobalSMBSessionList) {
108 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
110 if (ses->server == server) {
111 ses->status = CifsNeedReconnect;
115 /* else tcp and smb sessions need reconnection */
117 list_for_each(tmp, &GlobalTreeConnectionList) {
118 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
119 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
120 tcon->tidStatus = CifsNeedReconnect;
123 read_unlock(&GlobalSMBSeslock);
125 if(server->ssocket) {
126 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
127 server->ssocket->flags));
128 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
129 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
130 server->ssocket->flags));
131 sock_release(server->ssocket);
132 server->ssocket = NULL;
135 spin_lock(&GlobalMid_Lock);
136 list_for_each(tmp, &server->pending_mid_q) {
137 mid_entry = list_entry(tmp, struct
141 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
142 /* Mark other intransit requests as needing retry so
143 we do not immediately mark the session bad again
144 (ie after we reconnect below) as they timeout too */
145 mid_entry->midState = MID_RETRY_NEEDED;
149 spin_unlock(&GlobalMid_Lock);
152 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
154 if(server->protocolType == IPV6) {
155 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
157 rc = ipv4_connect(&server->addr.sockAddr,
159 server->workstation_RFC1001_name);
162 set_current_state(TASK_INTERRUPTIBLE);
163 schedule_timeout(3 * HZ);
165 atomic_inc(&tcpSesReconnectCount);
166 server->tcpStatus = CifsGood;
167 wake_up(&server->response_q);
174 cifs_demultiplex_thread(struct TCP_Server_Info *server)
177 unsigned int pdu_length, total_read;
178 struct smb_hdr *smb_buffer = NULL;
179 struct msghdr smb_msg;
180 mm_segment_t temp_fs;
182 struct socket *csocket = server->ssocket;
183 struct list_head *tmp;
184 struct cifsSesInfo *ses;
185 struct task_struct *task_to_wake = NULL;
186 struct mid_q_entry *mid_entry;
190 allow_signal(SIGKILL);
191 current->flags |= PF_MEMALLOC;
192 server->tsk = current; /* save process info to wake at shutdown */
193 cFYI(1, ("Demultiplex PID: %d", current->pid));
195 temp_fs = get_fs(); /* we must turn off socket api parm checking */
198 while (server->tcpStatus != CifsExiting) {
199 if (smb_buffer == NULL)
200 smb_buffer = cifs_buf_get();
202 memset(smb_buffer, 0, sizeof (struct smb_hdr));
204 if (smb_buffer == NULL) {
205 cERROR(1,("Can not get memory for SMB response"));
206 set_current_state(TASK_INTERRUPTIBLE);
207 schedule_timeout(HZ * 3); /* give system time to free memory */
210 iov.iov_base = smb_buffer;
211 iov.iov_len = sizeof (struct smb_hdr) - 1;
212 /* 1 byte less above since wct is not always returned in error cases */
213 smb_msg.msg_iov = &iov;
214 smb_msg.msg_iovlen = 1;
215 smb_msg.msg_control = NULL;
216 smb_msg.msg_controllen = 0;
219 sock_recvmsg(csocket, &smb_msg,
220 sizeof (struct smb_hdr) -
221 1 /* RFC1001 header and SMB header */ ,
222 MSG_PEEK /* flags see socket.h */ );
224 if(server->tcpStatus == CifsExiting) {
226 } else if (server->tcpStatus == CifsNeedReconnect) {
227 cFYI(1,("Reconnecting after server stopped responding"));
228 cifs_reconnect(server);
229 cFYI(1,("call to reconnect done"));
230 csocket = server->ssocket;
232 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
233 set_current_state(TASK_INTERRUPTIBLE);
234 schedule_timeout(1); /* minimum sleep to prevent looping
235 allowing socket to clear and app threads to set
236 tcpStatus CifsNeedReconnect if server hung */
238 } else if (length <= 0) {
239 if(server->tcpStatus == CifsNew) {
240 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
241 /* some servers kill tcp session rather than returning
242 smb negprot error in which case reconnecting here is
243 not going to help - return error to mount */
244 server->tcpStatus = CifsExiting;
245 wake_up(&server->response_q);
249 cFYI(1,("Reconnecting after unexpected rcvmsg error "));
250 cifs_reconnect(server);
251 csocket = server->ssocket;
252 wake_up(&server->response_q);
256 pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
257 /* Ony read pdu_length after below checks for too short (due
258 to e.g. int overflow) and too long ie beyond end of buf */
259 cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
261 temp = (char *) smb_buffer;
263 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
264 iov.iov_base = smb_buffer;
266 length = sock_recvmsg(csocket, &smb_msg, 4, 0);
267 cFYI(0,("Received 4 byte keep alive packet"));
268 } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
269 iov.iov_base = smb_buffer;
271 length = sock_recvmsg(csocket, &smb_msg, 4, 0);
272 cFYI(1,("Good RFC 1002 session rsp"));
273 } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
275 /* we get this from Windows 98 instead of error on SMB negprot response */
276 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
277 if(server->tcpStatus == CifsNew) {
278 /* if nack on negprot (rather than
279 ret of smb negprot error) reconnecting
280 not going to help, ret error to mount */
281 server->tcpStatus = CifsExiting;
282 /* wake up thread doing negprot */
283 wake_up(&server->response_q);
286 /* give server a second to
287 clean up before reconnect attempt */
288 set_current_state(TASK_INTERRUPTIBLE);
289 schedule_timeout(HZ);
290 /* always try 445 first on reconnect
291 since we get NACK on some if we ever
292 connected to port 139 (the NACK is
293 since we do not begin with RFC1001
294 session initialize frame) */
295 server->addr.sockAddr.sin_port = CIFS_PORT;
296 cifs_reconnect(server);
297 csocket = server->ssocket;
298 wake_up(&server->response_q);
301 } else if (temp[0] != (char) 0) {
302 cERROR(1,("Unknown RFC 1002 frame"));
303 cifs_dump_mem(" Received Data: ", temp, length);
304 cifs_reconnect(server);
305 csocket = server->ssocket;
308 if ((length != sizeof (struct smb_hdr) - 1)
310 CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
312 sizeof (struct smb_hdr) - 1)
315 (smb_buffer, smb_buffer->Mid))) {
317 ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
318 length, pdu_length));
319 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
320 /* could we fix this network corruption by finding next
321 smb header (instead of killing the session) and
322 restart reading from next valid SMB found? */
323 cifs_reconnect(server);
324 csocket = server->ssocket;
326 } else { /* length ok */
329 iov.iov_base = smb_buffer;
330 iov.iov_len = pdu_length;
332 total_read < pdu_length;
333 total_read += length) {
334 length = sock_recvmsg(csocket, &smb_msg,
335 pdu_length - total_read, 0);
338 ("Zero length receive when expecting %d ",
339 pdu_length - total_read));
340 cifs_reconnect(server);
341 csocket = server->ssocket;
347 dump_smb(smb_buffer, length);
349 (smb_buffer, smb_buffer->Mid, total_read)) {
350 cERROR(1, ("Bad SMB Received "));
355 spin_lock(&GlobalMid_Lock);
356 list_for_each(tmp, &server->pending_mid_q) {
357 mid_entry = list_entry(tmp, struct
361 if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
363 (" Mid 0x%x matched - waking up ",mid_entry->mid));
364 task_to_wake = mid_entry->tsk;
365 mid_entry->resp_buf =
367 mid_entry->midState =
368 MID_RESPONSE_RECEIVED;
371 spin_unlock(&GlobalMid_Lock);
373 smb_buffer = NULL; /* will be freed by users thread after he is done */
374 wake_up_process(task_to_wake);
375 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
376 cERROR(1, ("No task to wake, unknown frame rcvd!"));
377 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
382 ("Frame less than four bytes received %d bytes long.",
385 length = sock_recvmsg(csocket, &smb_msg, length, 0); /* throw away junk frame */
387 (" with junk 0x%x in it ",
388 *(__u32 *) smb_buffer));
393 server->tcpStatus = CifsExiting;
395 if(server->ssocket) {
396 sock_release(csocket);
397 server->ssocket = NULL;
400 if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
401 cifs_buf_release(smb_buffer);
403 read_lock(&GlobalSMBSeslock);
404 if (list_empty(&server->pending_mid_q)) {
405 /* loop through server session structures attached to this and mark them dead */
406 list_for_each(tmp, &GlobalSMBSessionList) {
408 list_entry(tmp, struct cifsSesInfo,
410 if (ses->server == server) {
411 ses->status = CifsExiting;
415 read_unlock(&GlobalSMBSeslock);
417 spin_lock(&GlobalMid_Lock);
418 list_for_each(tmp, &server->pending_mid_q) {
419 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
420 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
422 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
423 task_to_wake = mid_entry->tsk;
425 wake_up_process(task_to_wake);
429 spin_unlock(&GlobalMid_Lock);
430 read_unlock(&GlobalSMBSeslock);
431 set_current_state(TASK_INTERRUPTIBLE);
432 /* 1/8th of sec should be more than enough time for them to exit */
433 schedule_timeout(HZ/8);
436 if (list_empty(&server->pending_mid_q)) {
437 /* mpx threads have not exited yet give them
438 at least the smb send timeout time for long ops */
439 cFYI(1, ("Wait for exit from demultiplex thread"));
440 set_current_state(TASK_INTERRUPTIBLE);
441 schedule_timeout(46 * HZ);
442 /* if threads still have not exited they are probably never
443 coming home not much else we can do but free the memory */
447 cFYI(1, ("About to exit from demultiplex thread"));
452 cifs_kcalloc(size_t size, int type)
455 addr = kmalloc(size, type);
457 memset(addr, 0, size);
462 cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
466 unsigned int temp_len, i, j;
472 memset(vol->source_rfc1001_name,0x20,15);
473 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
474 /* does not have to be a perfect mapping since the field is
475 informational, only used for servers that do not support
476 port 445 and it can be overridden at mount time */
477 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
479 vol->source_rfc1001_name[15] = 0;
481 vol->linux_uid = current->uid; /* current->euid instead? */
482 vol->linux_gid = current->gid;
483 vol->dir_mode = S_IRWXUGO;
484 /* 2767 perms indicate mandatory locking support */
485 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
487 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
493 if(strncmp(options,"sep=",4) == 0) {
494 if(options[4] != 0) {
495 separator[0] = options[4];
498 cFYI(1,("Null separator not allowed"));
502 while ((data = strsep(&options, separator)) != NULL) {
505 if ((value = strchr(data, '=')) != NULL)
507 if (strnicmp(data, "user", 4) == 0) {
508 if (!value || !*value) {
510 "CIFS: invalid or missing username\n");
511 return 1; /* needs_arg; */
513 if (strnlen(value, 200) < 200) {
514 vol->username = value;
516 printk(KERN_WARNING "CIFS: username too long\n");
519 } else if (strnicmp(data, "pass", 4) == 0) {
520 if (!value || !*value) {
521 vol->password = NULL;
524 temp_len = strlen(value);
525 /* removed password length check, NTLM passwords
526 can be arbitrarily long */
528 /* if comma in password, the string will be
529 prematurely null terminated. Commas in password are
530 specified across the cifs mount interface by a double
531 comma ie ,, and a comma used as in other cases ie ','
532 as a parameter delimiter/separator is single and due
533 to the strsep above is temporarily zeroed. */
535 /* NB: password legally can have multiple commas and
536 the only illegal character in a password is null */
538 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
540 value[temp_len] = separator[0];
541 temp_len+=2; /* move after the second comma */
542 while(value[temp_len] != 0) {
543 if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
544 /* single comma indicating start of next parm */
549 if(value[temp_len] == 0) {
553 /* move options to point to start of next parm */
554 options = value + temp_len + 1;
556 /* go from value to (value + temp_len) condensing double commas to singles */
557 vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
558 for(i=0,j=0;i<temp_len;i++,j++) {
559 vol->password[j] = value[i];
560 if(value[i] == separator[0] && value[i+1] == separator[0]) {
561 /* skip second comma */
565 /* value[temp_len] is zeroed above so
566 vol->password[temp_len] guaranteed to be null */
568 vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
569 strcpy(vol->password, value);
571 } else if (strnicmp(data, "ip", 2) == 0) {
572 if (!value || !*value) {
574 } else if (strnlen(value, 35) < 35) {
577 printk(KERN_WARNING "CIFS: ip address too long\n");
580 } else if ((strnicmp(data, "unc", 3) == 0)
581 || (strnicmp(data, "target", 6) == 0)
582 || (strnicmp(data, "path", 4) == 0)) {
583 if (!value || !*value) {
585 "CIFS: invalid path to network resource\n");
586 return 1; /* needs_arg; */
588 if ((temp_len = strnlen(value, 300)) < 300) {
589 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
590 strcpy(vol->UNC,value);
591 if (strncmp(vol->UNC, "//", 2) == 0) {
594 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
596 "CIFS: UNC Path does not begin with // or \\\\ \n");
600 printk(KERN_WARNING "CIFS: UNC name too long\n");
603 } else if ((strnicmp(data, "domain", 3) == 0)
604 || (strnicmp(data, "workgroup", 5) == 0)) {
605 if (!value || !*value) {
606 printk(KERN_WARNING "CIFS: invalid domain name\n");
607 return 1; /* needs_arg; */
609 /* BB are there cases in which a comma can be valid in
610 a domain name and need special handling? */
611 if (strnlen(value, 65) < 65) {
612 vol->domainname = value;
613 cFYI(1, ("Domain name set"));
615 printk(KERN_WARNING "CIFS: domain name too long\n");
618 } else if (strnicmp(data, "iocharset", 9) == 0) {
619 if (!value || !*value) {
620 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
621 return 1; /* needs_arg; */
623 if (strnlen(value, 65) < 65) {
624 if(strnicmp(value,"default",7))
625 vol->iocharset = value;
626 /* if iocharset not set load_nls_default used by caller */
627 cFYI(1, ("iocharset set to %s",value));
629 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
632 } else if (strnicmp(data, "uid", 3) == 0) {
633 if (value && *value) {
635 simple_strtoul(value, &value, 0);
637 } else if (strnicmp(data, "gid", 3) == 0) {
638 if (value && *value) {
640 simple_strtoul(value, &value, 0);
642 } else if (strnicmp(data, "file_mode", 4) == 0) {
643 if (value && *value) {
645 simple_strtoul(value, &value, 0);
647 } else if (strnicmp(data, "dir_mode", 3) == 0) {
648 if (value && *value) {
650 simple_strtoul(value, &value, 0);
652 } else if (strnicmp(data, "port", 4) == 0) {
653 if (value && *value) {
655 simple_strtoul(value, &value, 0);
657 } else if (strnicmp(data, "rsize", 5) == 0) {
658 if (value && *value) {
660 simple_strtoul(value, &value, 0);
662 } else if (strnicmp(data, "wsize", 5) == 0) {
663 if (value && *value) {
665 simple_strtoul(value, &value, 0);
667 } else if (strnicmp(data, "sockopt", 5) == 0) {
668 if (value && *value) {
670 simple_strtoul(value, &value, 0);
672 } else if (strnicmp(data, "netbiosname", 4) == 0) {
673 if (!value || !*value || (*value == ' ')) {
674 cFYI(1,("invalid (empty) netbiosname specified"));
676 memset(vol->source_rfc1001_name,0x20,15);
678 /* BB are there cases in which a comma can be
679 valid in this workstation netbios name (and need
680 special handling)? */
682 /* We do not uppercase netbiosname for user */
686 vol->source_rfc1001_name[i] = value[i];
688 /* The string has 16th byte zero still from
689 set at top of the function */
690 if((i==15) && (value[i] != 0))
691 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
693 } else if (strnicmp(data, "version", 3) == 0) {
695 } else if (strnicmp(data, "rw", 2) == 0) {
697 } else if ((strnicmp(data, "suid", 4) == 0) ||
698 (strnicmp(data, "nosuid", 6) == 0) ||
699 (strnicmp(data, "exec", 4) == 0) ||
700 (strnicmp(data, "noexec", 6) == 0) ||
701 (strnicmp(data, "nodev", 5) == 0) ||
702 (strnicmp(data, "dev", 3) == 0)) {
703 /* The mount tool or mount.cifs helper (if present)
704 uses these opts to set flags, and the flags are read
705 by the kernel vfs layer before we get here (ie
706 before read super) so there is no point trying to
707 parse these options again and set anything and it
708 is ok to just ignore them */
710 } else if (strnicmp(data, "ro", 2) == 0) {
712 } else if (strnicmp(data, "hard", 4) == 0) {
714 } else if (strnicmp(data, "soft", 4) == 0) {
716 } else if (strnicmp(data, "nohard", 6) == 0) {
718 } else if (strnicmp(data, "nosoft", 6) == 0) {
721 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
723 if (vol->UNC == NULL) {
724 if(devname == NULL) {
725 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
728 if ((temp_len = strnlen(devname, 300)) < 300) {
729 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
730 strcpy(vol->UNC,devname);
731 if (strncmp(vol->UNC, "//", 2) == 0) {
734 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
735 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
739 printk(KERN_WARNING "CIFS: UNC name too long\n");
744 vol->UNCip = &vol->UNC[2];
749 static struct cifsSesInfo *
750 cifs_find_tcp_session(__u32 new_target_ip_addr,
751 char *userName, struct TCP_Server_Info **psrvTcp)
753 struct list_head *tmp;
754 struct cifsSesInfo *ses;
757 read_lock(&GlobalSMBSeslock);
758 list_for_each(tmp, &GlobalSMBSessionList) {
759 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
761 if (ses->server->addr.sockAddr.sin_addr.s_addr ==
762 new_target_ip_addr) {
763 /* BB lock server and tcp session and increment use count here?? */
764 *psrvTcp = ses->server; /* found a match on the TCP session */
765 /* BB check if reconnection needed */
767 (ses->userName, userName,
768 MAX_USERNAME_SIZE) == 0){
769 read_unlock(&GlobalSMBSeslock);
770 return ses; /* found exact match on both tcp and SMB sessions */
774 /* else tcp and smb sessions need reconnection */
776 read_unlock(&GlobalSMBSeslock);
780 static struct cifsTconInfo *
781 find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
783 struct list_head *tmp;
784 struct cifsTconInfo *tcon;
786 read_lock(&GlobalSMBSeslock);
787 list_for_each(tmp, &GlobalTreeConnectionList) {
788 cFYI(1, ("Next tcon - "));
789 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
791 if (tcon->ses->server) {
793 (" old ip addr: %x == new ip %x ?",
794 tcon->ses->server->addr.sockAddr.sin_addr.
795 s_addr, new_target_ip_addr));
796 if (tcon->ses->server->addr.sockAddr.sin_addr.
797 s_addr == new_target_ip_addr) {
798 /* BB lock tcon and server and tcp session and increment use count here? */
799 /* found a match on the TCP session */
800 /* BB check if reconnection needed */
801 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
802 tcon->treeName, uncName));
804 (tcon->treeName, uncName,
805 MAX_TREE_SIZE) == 0) {
807 ("Matched UNC, old user: %s == new: %s ?",
808 tcon->treeName, uncName));
810 (tcon->ses->userName,
812 MAX_USERNAME_SIZE) == 0) {
813 read_unlock(&GlobalSMBSeslock);
814 return tcon;/* also matched user (smb session)*/
821 read_unlock(&GlobalSMBSeslock);
826 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
827 const char *old_path, const struct nls_table *nls_codepage)
829 unsigned char *referrals = NULL;
830 unsigned int num_referrals;
833 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
834 &num_referrals, &referrals);
836 /* BB Add in code to: if valid refrl, if not ip address contact
837 the helper that resolves tcp names, mount to it, try to
838 tcon to it unmount it if fail */
847 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
848 const char *old_path, const struct nls_table *nls_codepage,
849 unsigned int *pnum_referrals, unsigned char ** preferrals)
856 if (pSesInfo->ipc_tid == 0) {
857 temp_unc = kmalloc(2 /* for slashes */ +
858 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
859 + 1 + 4 /* slash IPC$ */ + 2,
861 if (temp_unc == NULL)
865 strcpy(temp_unc + 2, pSesInfo->serverName);
866 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
867 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
869 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
873 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
874 pnum_referrals, nls_codepage);
879 /* See RFC1001 section 14 on representation of Netbios names */
880 static void rfc1002mangle(char * target,char * source, unsigned int length)
884 for(i=0,j=0;i<(length);i++) {
885 /* mask a nibble at a time and encode */
886 target[j] = 'A' + (0x0F & (source[i] >> 4));
887 target[j+1] = 'A' + (0x0F & source[i]);
895 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
900 unsigned short int orig_port = 0;
902 if(*csocket == NULL) {
903 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
905 cERROR(1, ("Error %d creating socket",rc));
909 /* BB other socket options to set KEEPALIVE, NODELAY? */
910 cFYI(1,("Socket created"));
911 /* (*csocket)->sk->allocation = GFP_NOFS; */ /* BB is there equivalent in 2.6 */
915 psin_server->sin_family = AF_INET;
916 if(psin_server->sin_port) { /* user overrode default port */
917 rc = (*csocket)->ops->connect(*csocket,
918 (struct sockaddr *) psin_server,
919 sizeof (struct sockaddr_in),0);
925 /* save original port so we can retry user specified port
926 later if fall back ports fail this time */
927 orig_port = psin_server->sin_port;
929 /* do not retry on the same port we just failed on */
930 if(psin_server->sin_port != htons(CIFS_PORT)) {
931 psin_server->sin_port = htons(CIFS_PORT);
933 rc = (*csocket)->ops->connect(*csocket,
934 (struct sockaddr *) psin_server,
935 sizeof (struct sockaddr_in),0);
941 psin_server->sin_port = htons(RFC1001_PORT);
942 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
943 psin_server, sizeof (struct sockaddr_in),0);
948 /* give up here - unless we want to retry on different
949 protocol families some day */
952 psin_server->sin_port = orig_port;
953 cFYI(1,("Error %d connecting to server via ipv4",rc));
954 sock_release(*csocket);
958 /* Eventually check for other socket options to change from
959 the default. sock_setsockopt not used because it expects
961 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
963 /* send RFC1001 sessinit */
965 if(psin_server->sin_port == htons(139)) {
966 /* some servers require RFC1001 sessinit before sending
967 negprot - BB check reconnection in case where second
968 sessinit is sent but no second negprot */
969 struct rfc1002_session_packet * ses_init_buf;
970 struct smb_hdr * smb_buf;
971 ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
973 ses_init_buf->trailer.session_req.called_len = 32;
974 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
975 DEFAULT_CIFS_CALLED_NAME,16);
976 ses_init_buf->trailer.session_req.calling_len = 32;
977 /* calling name ends in null (byte 16) from old smb
979 if(netbios_name && (netbios_name[0] !=0)) {
980 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
983 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
984 "LINUX_CIFS_CLNT",16);
986 ses_init_buf->trailer.session_req.scope1 = 0;
987 ses_init_buf->trailer.session_req.scope2 = 0;
988 smb_buf = (struct smb_hdr *)ses_init_buf;
989 /* sizeof RFC1002_SESSION_REQUEST with no scope */
990 smb_buf->smb_buf_length = 0x81000044;
991 rc = smb_send(*csocket, smb_buf, 0x44,
992 (struct sockaddr *)psin_server);
995 /* else the negprot may still work without this
996 even though malloc failed */
1004 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1009 if(*csocket == NULL) {
1010 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1012 cERROR(1, ("Error %d creating ipv6 socket",rc));
1016 /* BB other socket options to set KEEPALIVE, NODELAY? */
1017 cFYI(1,("ipv6 Socket created"));
1021 psin_server->sin6_family = AF_INET6;
1023 if(psin_server->sin6_port) { /* user overrode default port */
1024 rc = (*csocket)->ops->connect(*csocket,
1025 (struct sockaddr *) psin_server,
1026 sizeof (struct sockaddr_in6),0);
1032 /* do not retry on the same port we just failed on */
1033 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1034 psin_server->sin6_port = htons(CIFS_PORT);
1036 rc = (*csocket)->ops->connect(*csocket,
1037 (struct sockaddr *) psin_server,
1038 sizeof (struct sockaddr_in6),0);
1044 psin_server->sin6_port = htons(RFC1001_PORT);
1045 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1046 psin_server, sizeof (struct sockaddr_in6),0);
1051 /* give up here - unless we want to retry on different
1052 protocol families some day */
1054 cFYI(1,("Error %d connecting to server via ipv6",rc));
1055 sock_release(*csocket);
1059 /* Eventually check for other socket options to change from
1060 the default. sock_setsockopt not used because it expects
1061 user space buffer */
1062 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1068 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1069 char *mount_data, const char *devname)
1073 struct socket *csocket = NULL;
1074 struct sockaddr_in sin_server;
1075 struct sockaddr_in6 sin_server6;
1076 struct smb_vol volume_info;
1077 struct cifsSesInfo *pSesInfo = NULL;
1078 struct cifsSesInfo *existingCifsSes = NULL;
1079 struct cifsTconInfo *tcon = NULL;
1080 struct TCP_Server_Info *srvTcp = NULL;
1084 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1086 memset(&volume_info,0,sizeof(struct smb_vol));
1087 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1089 kfree(volume_info.UNC);
1090 if(volume_info.password)
1091 kfree(volume_info.password);
1096 if (volume_info.username) {
1097 cFYI(1, ("Username: %s ", volume_info.username));
1100 cifserror("No username specified ");
1101 /* In userspace mount helper we can get user name from alternate
1102 locations such as env variables and files on disk */
1104 kfree(volume_info.UNC);
1105 if(volume_info.password)
1106 kfree(volume_info.password);
1111 if (volume_info.UNCip && volume_info.UNC) {
1112 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1115 /* not ipv4 address, try ipv6 */
1116 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1120 /* we failed translating address */
1122 kfree(volume_info.UNC);
1123 if(volume_info.password)
1124 kfree(volume_info.password);
1129 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1132 } else if (volume_info.UNCip){
1133 /* BB using ip addr as server name connect to the DFS root below */
1134 cERROR(1,("Connecting to DFS root not implemented yet"));
1136 kfree(volume_info.UNC);
1137 if(volume_info.password)
1138 kfree(volume_info.password);
1141 } else /* which servers DFS root would we conect to */ {
1143 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1145 kfree(volume_info.UNC);
1146 if(volume_info.password)
1147 kfree(volume_info.password);
1152 /* this is needed for ASCII cp to Unicode converts */
1153 if(volume_info.iocharset == NULL) {
1154 cifs_sb->local_nls = load_nls_default();
1155 /* load_nls_default can not return null */
1157 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1158 if(cifs_sb->local_nls == NULL) {
1159 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1161 kfree(volume_info.UNC);
1162 if(volume_info.password)
1163 kfree(volume_info.password);
1170 cifs_find_tcp_session(sin_server.sin_addr.s_addr,
1171 volume_info.username, &srvTcp);
1173 cFYI(1, ("Existing tcp session with server found "));
1174 } else { /* create socket */
1175 if(volume_info.port)
1176 sin_server.sin_port = htons(volume_info.port);
1178 sin_server.sin_port = 0;
1179 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1182 ("Error connecting to IPv4 socket. Aborting operation"));
1184 sock_release(csocket);
1186 kfree(volume_info.UNC);
1187 if(volume_info.password)
1188 kfree(volume_info.password);
1193 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1194 if (srvTcp == NULL) {
1196 sock_release(csocket);
1198 kfree(volume_info.UNC);
1199 if(volume_info.password)
1200 kfree(volume_info.password);
1204 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1205 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1206 /* BB Add code for ipv6 case too */
1207 srvTcp->ssocket = csocket;
1208 srvTcp->protocolType = IPV4;
1209 init_waitqueue_head(&srvTcp->response_q);
1210 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1211 srvTcp->tcpStatus = CifsNew;
1212 init_MUTEX(&srvTcp->tcpSem);
1213 kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1214 CLONE_FS | CLONE_FILES | CLONE_VM);
1215 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1219 if (existingCifsSes) {
1220 pSesInfo = existingCifsSes;
1221 cFYI(1, ("Existing smb sess found "));
1222 if(volume_info.password)
1223 kfree(volume_info.password);
1224 /* volume_info.UNC freed at end of function */
1226 cFYI(1, ("Existing smb sess not found "));
1227 pSesInfo = sesInfoAlloc();
1228 if (pSesInfo == NULL)
1231 pSesInfo->server = srvTcp;
1232 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1233 NIPQUAD(sin_server.sin_addr.s_addr));
1237 /* volume_info.password freed at unmount */
1238 if (volume_info.password)
1239 pSesInfo->password = volume_info.password;
1240 if (volume_info.username)
1241 strncpy(pSesInfo->userName,
1242 volume_info.username,MAX_USERNAME_SIZE);
1243 if (volume_info.domainname)
1244 strncpy(pSesInfo->domainName,
1245 volume_info.domainname,MAX_USERNAME_SIZE);
1246 pSesInfo->linux_uid = volume_info.linux_uid;
1247 down(&pSesInfo->sesSem);
1248 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1249 up(&pSesInfo->sesSem);
1251 atomic_inc(&srvTcp->socketUseCount);
1253 if(volume_info.password)
1254 kfree(volume_info.password);
1257 /* search for existing tcon to this server share */
1259 if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
1260 cifs_sb->rsize = volume_info.rsize;
1262 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1263 if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
1264 cifs_sb->wsize = volume_info.wsize;
1266 cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1267 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1268 cifs_sb->rsize = PAGE_CACHE_SIZE;
1269 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1271 cifs_sb->mnt_uid = volume_info.linux_uid;
1272 cifs_sb->mnt_gid = volume_info.linux_gid;
1273 cifs_sb->mnt_file_mode = volume_info.file_mode;
1274 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1275 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1277 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1278 volume_info.username);
1280 cFYI(1, ("Found match on UNC path "));
1281 /* we can have only one retry value for a connection
1282 to a share so for resources mounted more than once
1283 to the same server share the last value passed in
1284 for the retry flag is used */
1285 tcon->retry = volume_info.retry;
1287 tcon = tconInfoAlloc();
1291 /* check for null share name ie connect to dfs root */
1293 /* BB check if this works for exactly length three strings */
1294 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1295 && (strchr(volume_info.UNC + 3, '/') ==
1297 rc = connect_to_dfs_path(xid,
1303 kfree(volume_info.UNC);
1307 rc = CIFSTCon(xid, pSesInfo,
1309 tcon, cifs_sb->local_nls);
1310 cFYI(1, ("CIFS Tcon rc = %d", rc));
1313 atomic_inc(&pSesInfo->inUse);
1314 tcon->retry = volume_info.retry;
1319 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1320 cFYI(0, ("Large files supported "));
1321 sb->s_maxbytes = (u64) 1 << 63;
1323 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1325 /* on error free sesinfo and tcon struct if needed */
1327 if(atomic_read(&srvTcp->socketUseCount) == 0)
1328 srvTcp->tcpStatus = CifsExiting;
1329 /* If find_unc succeeded then rc == 0 so we can not end */
1330 if (tcon) /* up here accidently freeing someone elses tcon struct */
1332 if (existingCifsSes == 0) {
1334 if (pSesInfo->server) {
1336 CIFSSMBLogoff(xid, pSesInfo);
1337 if(pSesInfo->server->tsk)
1338 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1339 set_current_state(TASK_INTERRUPTIBLE);
1340 schedule_timeout(HZ / 4); /* give captive thread time to exit */
1342 cFYI(1, ("No session or bad tcon"));
1343 sesInfoFree(pSesInfo);
1344 /* pSesInfo = NULL; */
1348 atomic_inc(&tcon->useCount);
1349 cifs_sb->tcon = tcon;
1350 tcon->ses = pSesInfo;
1352 /* do not care if following two calls succeed - informational only */
1353 CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
1354 CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
1355 if (tcon->ses->capabilities & CAP_UNIX)
1356 CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
1359 /* volume_info.password is freed above when existing session found
1360 (in which case it is not needed anymore) but when new sesion is created
1361 the password ptr is put in the new session structure (in which case the
1362 password will be freed at unmount time) */
1364 kfree(volume_info.UNC);
1370 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1371 char session_key[CIFS_SESSION_KEY_SIZE],
1372 const struct nls_table *nls_codepage)
1374 struct smb_hdr *smb_buffer;
1375 struct smb_hdr *smb_buffer_response;
1376 SESSION_SETUP_ANDX *pSMB;
1377 SESSION_SETUP_ANDX *pSMBr;
1379 char *user = ses->userName;
1380 char *domain = ses->domainName;
1382 int remaining_words = 0;
1383 int bytes_returned = 0;
1386 cFYI(1, ("In sesssetup "));
1388 smb_buffer = cifs_buf_get();
1389 if (smb_buffer == 0) {
1392 smb_buffer_response = smb_buffer;
1393 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1395 /* send SMBsessionSetup here */
1396 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1397 0 /* no tCon exists yet */ , 13 /* wct */ );
1399 pSMB->req_no_secext.AndXCommand = 0xFF;
1400 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1401 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1403 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1404 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1406 pSMB->req_no_secext.Capabilities =
1407 CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
1408 if (ses->capabilities & CAP_UNICODE) {
1409 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1410 pSMB->req_no_secext.Capabilities |= CAP_UNICODE;
1412 if (ses->capabilities & CAP_STATUS32) {
1413 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1414 pSMB->req_no_secext.Capabilities |= CAP_STATUS32;
1416 if (ses->capabilities & CAP_DFS) {
1417 smb_buffer->Flags2 |= SMBFLG2_DFS;
1418 pSMB->req_no_secext.Capabilities |= CAP_DFS;
1420 pSMB->req_no_secext.Capabilities =
1421 cpu_to_le32(pSMB->req_no_secext.Capabilities);
1422 /* pSMB->req_no_secext.CaseInsensitivePasswordLength =
1423 CIFS_SESSION_KEY_SIZE; */
1424 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
1425 pSMB->req_no_secext.CaseSensitivePasswordLength =
1426 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1427 bcc_ptr = pByteArea(smb_buffer);
1428 /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
1429 bcc_ptr += CIFS_SESSION_KEY_SIZE; */
1430 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1431 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1433 if (ses->capabilities & CAP_UNICODE) {
1434 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1439 bytes_returned = 0; /* skill null user */
1442 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1444 bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
1445 bcc_ptr += 2; /* trailing null */
1448 cifs_strtoUCS((wchar_t *) bcc_ptr,
1449 "CIFS_LINUX_DOM", 32, nls_codepage);
1452 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1454 bcc_ptr += 2 * bytes_returned;
1457 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1459 bcc_ptr += 2 * bytes_returned;
1461 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
1463 bcc_ptr += 2 * bytes_returned;
1466 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1468 bcc_ptr += 2 * bytes_returned;
1472 strncpy(bcc_ptr, user, 200);
1473 bcc_ptr += strnlen(user, 200);
1477 if (domain == NULL) {
1478 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1479 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1481 strncpy(bcc_ptr, domain, 64);
1482 bcc_ptr += strnlen(domain, 64);
1486 strcpy(bcc_ptr, "Linux version ");
1487 bcc_ptr += strlen("Linux version ");
1488 strcpy(bcc_ptr, UTS_RELEASE);
1489 bcc_ptr += strlen(UTS_RELEASE) + 1;
1490 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1491 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1493 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1494 smb_buffer->smb_buf_length += BCC(smb_buffer);
1495 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
1497 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1498 &bytes_returned, 1);
1500 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1501 } else if ((smb_buffer_response->WordCount == 3)
1502 || (smb_buffer_response->WordCount == 4)) {
1503 pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
1504 if (pSMBr->resp.Action & GUEST_LOGIN)
1505 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1507 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1508 cFYI(1, ("UID = %d ", ses->Suid));
1509 /* response can have either 3 or 4 word count - Samba sends 3 */
1510 bcc_ptr = pByteArea(smb_buffer_response);
1511 if ((pSMBr->resp.hdr.WordCount == 3)
1512 || ((pSMBr->resp.hdr.WordCount == 4)
1513 && (pSMBr->resp.SecurityBlobLength <
1514 pSMBr->resp.ByteCount))) {
1515 if (pSMBr->resp.hdr.WordCount == 4)
1517 pSMBr->resp.SecurityBlobLength;
1519 if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
1520 if ((long) (bcc_ptr) % 2) {
1522 (BCC(smb_buffer_response)
1524 bcc_ptr++; /* Unicode strings must be word aligned */
1528 (smb_buffer_response) / 2;
1531 UniStrnlen((wchar_t *) bcc_ptr,
1532 remaining_words - 1);
1533 /* We look for obvious messed up bcc or strings in response so we do not go off
1534 the end since (at least) WIN2K and Windows XP have a major bug in not null
1535 terminating last Unicode string in response */
1536 ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1537 cifs_strfromUCS_le(ses->serverOS,
1538 (wchar_t *)bcc_ptr, len,nls_codepage);
1539 bcc_ptr += 2 * (len + 1);
1540 remaining_words -= len + 1;
1541 ses->serverOS[2 * len] = 0;
1542 ses->serverOS[1 + (2 * len)] = 0;
1543 if (remaining_words > 0) {
1544 len = UniStrnlen((wchar_t *)bcc_ptr,
1547 ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
1548 cifs_strfromUCS_le(ses->serverNOS,
1549 (wchar_t *)bcc_ptr,len,nls_codepage);
1550 bcc_ptr += 2 * (len + 1);
1551 ses->serverNOS[2 * len] = 0;
1552 ses->serverNOS[1 + (2 * len)] = 0;
1553 remaining_words -= len + 1;
1554 if (remaining_words > 0) {
1555 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1556 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1558 cifs_kcalloc(2*(len+1),GFP_KERNEL);
1559 cifs_strfromUCS_le(ses->serverDomain,
1560 (wchar_t *)bcc_ptr,len,nls_codepage);
1561 bcc_ptr += 2 * (len + 1);
1562 ses->serverDomain[2*len] = 0;
1563 ses->serverDomain[1+(2*len)] = 0;
1564 } /* else no more room so create dummy domain string */
1569 } else { /* no room so create dummy domain and NOS string */
1571 cifs_kcalloc(2, GFP_KERNEL);
1573 cifs_kcalloc(2, GFP_KERNEL);
1575 } else { /* ASCII */
1576 len = strnlen(bcc_ptr, 1024);
1577 if (((long) bcc_ptr + len) - (long)
1578 pByteArea(smb_buffer_response)
1579 <= BCC(smb_buffer_response)) {
1580 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1581 strncpy(ses->serverOS,bcc_ptr, len);
1584 bcc_ptr[0] = 0; /* null terminate the string */
1587 len = strnlen(bcc_ptr, 1024);
1588 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1589 strncpy(ses->serverNOS, bcc_ptr, len);
1594 len = strnlen(bcc_ptr, 1024);
1595 ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
1596 strncpy(ses->serverDomain, bcc_ptr, len);
1602 ("Variable field of length %d extends beyond end of smb ",
1607 (" Security Blob Length extends beyond end of SMB"));
1610 cERROR(1, ("No session structure passed in."));
1614 (" Invalid Word count %d: ",
1615 smb_buffer_response->WordCount));
1620 cifs_buf_release(smb_buffer);
1626 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1627 char *SecurityBlob,int SecurityBlobLength,
1628 const struct nls_table *nls_codepage)
1630 struct smb_hdr *smb_buffer;
1631 struct smb_hdr *smb_buffer_response;
1632 SESSION_SETUP_ANDX *pSMB;
1633 SESSION_SETUP_ANDX *pSMBr;
1635 char *user = ses->userName;
1636 char *domain = ses->domainName;
1638 int remaining_words = 0;
1639 int bytes_returned = 0;
1642 cFYI(1, ("In spnego sesssetup "));
1644 smb_buffer = cifs_buf_get();
1645 if (smb_buffer == 0) {
1648 smb_buffer_response = smb_buffer;
1649 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1651 /* send SMBsessionSetup here */
1652 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1653 0 /* no tCon exists yet */ , 12 /* wct */ );
1654 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1655 pSMB->req.AndXCommand = 0xFF;
1656 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1657 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1659 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1660 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1662 pSMB->req.Capabilities =
1663 CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1664 CAP_EXTENDED_SECURITY;
1665 if (ses->capabilities & CAP_UNICODE) {
1666 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1667 pSMB->req.Capabilities |= CAP_UNICODE;
1669 if (ses->capabilities & CAP_STATUS32) {
1670 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1671 pSMB->req.Capabilities |= CAP_STATUS32;
1673 if (ses->capabilities & CAP_DFS) {
1674 smb_buffer->Flags2 |= SMBFLG2_DFS;
1675 pSMB->req.Capabilities |= CAP_DFS;
1677 pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
1679 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1680 bcc_ptr = pByteArea(smb_buffer);
1681 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1682 bcc_ptr += SecurityBlobLength;
1684 if (ses->capabilities & CAP_UNICODE) {
1685 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1690 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1691 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1692 bcc_ptr += 2; /* trailing null */
1695 cifs_strtoUCS((wchar_t *) bcc_ptr,
1696 "CIFS_LINUX_DOM", 32, nls_codepage);
1699 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1701 bcc_ptr += 2 * bytes_returned;
1704 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1706 bcc_ptr += 2 * bytes_returned;
1708 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
1710 bcc_ptr += 2 * bytes_returned;
1713 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1715 bcc_ptr += 2 * bytes_returned;
1718 strncpy(bcc_ptr, user, 200);
1719 bcc_ptr += strnlen(user, 200);
1722 if (domain == NULL) {
1723 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1724 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1726 strncpy(bcc_ptr, domain, 64);
1727 bcc_ptr += strnlen(domain, 64);
1731 strcpy(bcc_ptr, "Linux version ");
1732 bcc_ptr += strlen("Linux version ");
1733 strcpy(bcc_ptr, UTS_RELEASE);
1734 bcc_ptr += strlen(UTS_RELEASE) + 1;
1735 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1736 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1738 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1739 smb_buffer->smb_buf_length += BCC(smb_buffer);
1740 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
1742 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1743 &bytes_returned, 1);
1745 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1746 } else if ((smb_buffer_response->WordCount == 3)
1747 || (smb_buffer_response->WordCount == 4)) {
1748 pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
1749 pSMBr->resp.SecurityBlobLength =
1750 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1751 if (pSMBr->resp.Action & GUEST_LOGIN)
1752 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1754 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1755 cFYI(1, ("UID = %d ", ses->Suid));
1756 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
1758 /* BB Fix below to make endian neutral !! */
1760 if ((pSMBr->resp.hdr.WordCount == 3)
1761 || ((pSMBr->resp.hdr.WordCount == 4)
1762 && (pSMBr->resp.SecurityBlobLength <
1763 pSMBr->resp.ByteCount))) {
1764 if (pSMBr->resp.hdr.WordCount == 4) {
1766 pSMBr->resp.SecurityBlobLength;
1768 ("Security Blob Length %d ",
1769 pSMBr->resp.SecurityBlobLength));
1772 if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
1773 if ((long) (bcc_ptr) % 2) {
1775 (BCC(smb_buffer_response)
1777 bcc_ptr++; /* Unicode strings must be word aligned */
1781 (smb_buffer_response) / 2;
1784 UniStrnlen((wchar_t *) bcc_ptr,
1785 remaining_words - 1);
1786 /* We look for obvious messed up bcc or strings in response so we do not go off
1787 the end since (at least) WIN2K and Windows XP have a major bug in not null
1788 terminating last Unicode string in response */
1790 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1791 cifs_strfromUCS_le(ses->serverOS,
1795 bcc_ptr += 2 * (len + 1);
1796 remaining_words -= len + 1;
1797 ses->serverOS[2 * len] = 0;
1798 ses->serverOS[1 + (2 * len)] = 0;
1799 if (remaining_words > 0) {
1800 len = UniStrnlen((wchar_t *)bcc_ptr,
1804 cifs_kcalloc(2 * (len + 1),
1806 cifs_strfromUCS_le(ses->serverNOS,
1810 bcc_ptr += 2 * (len + 1);
1811 ses->serverNOS[2 * len] = 0;
1812 ses->serverNOS[1 + (2 * len)] = 0;
1813 remaining_words -= len + 1;
1814 if (remaining_words > 0) {
1815 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1816 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1817 ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
1818 cifs_strfromUCS_le(ses->serverDomain,
1822 bcc_ptr += 2*(len+1);
1823 ses->serverDomain[2*len] = 0;
1824 ses->serverDomain[1+(2*len)] = 0;
1825 } /* else no more room so create dummy domain string */
1828 cifs_kcalloc(2,GFP_KERNEL);
1829 } else { /* no room so create dummy domain and NOS string */
1830 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
1831 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
1833 } else { /* ASCII */
1835 len = strnlen(bcc_ptr, 1024);
1836 if (((long) bcc_ptr + len) - (long)
1837 pByteArea(smb_buffer_response)
1838 <= BCC(smb_buffer_response)) {
1839 ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
1840 strncpy(ses->serverOS, bcc_ptr, len);
1843 bcc_ptr[0] = 0; /* null terminate the string */
1846 len = strnlen(bcc_ptr, 1024);
1847 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1848 strncpy(ses->serverNOS, bcc_ptr, len);
1853 len = strnlen(bcc_ptr, 1024);
1854 ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
1855 strncpy(ses->serverDomain, bcc_ptr, len);
1861 ("Variable field of length %d extends beyond end of smb ",
1866 (" Security Blob Length extends beyond end of SMB"));
1869 cERROR(1, ("No session structure passed in."));
1873 (" Invalid Word count %d: ",
1874 smb_buffer_response->WordCount));
1879 cifs_buf_release(smb_buffer);
1885 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
1886 struct cifsSesInfo *ses, int * pNTLMv2_flag,
1887 const struct nls_table *nls_codepage)
1889 struct smb_hdr *smb_buffer;
1890 struct smb_hdr *smb_buffer_response;
1891 SESSION_SETUP_ANDX *pSMB;
1892 SESSION_SETUP_ANDX *pSMBr;
1894 char *domain = ses->domainName;
1896 int remaining_words = 0;
1897 int bytes_returned = 0;
1899 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
1900 PNEGOTIATE_MESSAGE SecurityBlob;
1901 PCHALLENGE_MESSAGE SecurityBlob2;
1903 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
1904 *pNTLMv2_flag = FALSE;
1905 smb_buffer = cifs_buf_get();
1906 if (smb_buffer == 0) {
1909 smb_buffer_response = smb_buffer;
1910 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1911 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
1913 /* send SMBsessionSetup here */
1914 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1915 0 /* no tCon exists yet */ , 12 /* wct */ );
1916 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1917 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
1919 pSMB->req.AndXCommand = 0xFF;
1920 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1921 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1923 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1924 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1926 pSMB->req.Capabilities =
1927 CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1928 CAP_EXTENDED_SECURITY;
1929 if (ses->capabilities & CAP_UNICODE) {
1930 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1931 pSMB->req.Capabilities |= CAP_UNICODE;
1933 if (ses->capabilities & CAP_STATUS32) {
1934 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1935 pSMB->req.Capabilities |= CAP_STATUS32;
1937 if (ses->capabilities & CAP_DFS) {
1938 smb_buffer->Flags2 |= SMBFLG2_DFS;
1939 pSMB->req.Capabilities |= CAP_DFS;
1941 pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
1943 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
1944 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
1945 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
1946 SecurityBlob->MessageType = NtLmNegotiate;
1947 SecurityBlob->NegotiateFlags =
1948 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
1949 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
1950 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
1952 SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
1954 SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
1955 /* setup pointers to domain name and workstation name */
1956 bcc_ptr += SecurityBlobLength;
1958 SecurityBlob->WorkstationName.Buffer = 0;
1959 SecurityBlob->WorkstationName.Length = 0;
1960 SecurityBlob->WorkstationName.MaximumLength = 0;
1962 if (domain == NULL) {
1963 SecurityBlob->DomainName.Buffer = 0;
1964 SecurityBlob->DomainName.Length = 0;
1965 SecurityBlob->DomainName.MaximumLength = 0;
1967 SecurityBlob->NegotiateFlags |=
1968 NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
1969 strncpy(bcc_ptr, domain, 63);
1970 SecurityBlob->DomainName.Length = strnlen(domain, 64);
1971 SecurityBlob->DomainName.MaximumLength =
1972 cpu_to_le16(SecurityBlob->DomainName.Length);
1973 SecurityBlob->DomainName.Buffer =
1974 cpu_to_le32((long) &SecurityBlob->
1976 (long) &SecurityBlob->Signature);
1977 bcc_ptr += SecurityBlob->DomainName.Length;
1978 SecurityBlobLength += SecurityBlob->DomainName.Length;
1979 SecurityBlob->DomainName.Length =
1980 cpu_to_le16(SecurityBlob->DomainName.Length);
1982 if (ses->capabilities & CAP_UNICODE) {
1983 if ((long) bcc_ptr % 2) {
1989 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1991 bcc_ptr += 2 * bytes_returned;
1993 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
1995 bcc_ptr += 2 * bytes_returned;
1996 bcc_ptr += 2; /* null terminate Linux version */
1998 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2000 bcc_ptr += 2 * bytes_returned;
2003 bcc_ptr += 2; /* null terminate network opsys string */
2006 bcc_ptr += 2; /* null domain */
2007 } else { /* ASCII */
2008 strcpy(bcc_ptr, "Linux version ");
2009 bcc_ptr += strlen("Linux version ");
2010 strcpy(bcc_ptr, UTS_RELEASE);
2011 bcc_ptr += strlen(UTS_RELEASE) + 1;
2012 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2013 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2014 bcc_ptr++; /* empty domain field */
2017 SecurityBlob->NegotiateFlags =
2018 cpu_to_le32(SecurityBlob->NegotiateFlags);
2019 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2020 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2021 smb_buffer->smb_buf_length += BCC(smb_buffer);
2022 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
2024 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2025 &bytes_returned, 1);
2027 if (smb_buffer_response->Status.CifsError ==
2028 (NT_STATUS_MORE_PROCESSING_REQUIRED))
2032 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2033 } else if ((smb_buffer_response->WordCount == 3)
2034 || (smb_buffer_response->WordCount == 4)) {
2035 pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
2036 pSMBr->resp.SecurityBlobLength =
2037 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2038 if (pSMBr->resp.Action & GUEST_LOGIN)
2039 cFYI(1, (" Guest login"));
2040 /* Do we want to set anything in SesInfo struct when guest login? */
2042 bcc_ptr = pByteArea(smb_buffer_response);
2043 /* response can have either 3 or 4 word count - Samba sends 3 */
2045 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2046 if (SecurityBlob2->MessageType != NtLmChallenge) {
2048 ("Unexpected NTLMSSP message type received %d",
2049 SecurityBlob2->MessageType));
2051 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2052 cFYI(1, ("UID = %d ", ses->Suid));
2053 if ((pSMBr->resp.hdr.WordCount == 3)
2054 || ((pSMBr->resp.hdr.WordCount == 4)
2055 && (pSMBr->resp.SecurityBlobLength <
2056 pSMBr->resp.ByteCount))) {
2057 if (pSMBr->resp.hdr.WordCount == 4) {
2059 pSMBr->resp.SecurityBlobLength;
2061 ("Security Blob Length %d ",
2062 pSMBr->resp.SecurityBlobLength));
2065 cFYI(1, ("NTLMSSP Challenge rcvd "));
2067 memcpy(ses->server->cryptKey,
2068 SecurityBlob2->Challenge,
2069 CIFS_CRYPTO_KEY_SIZE);
2070 if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
2071 *pNTLMv2_flag = TRUE;
2073 if((SecurityBlob2->NegotiateFlags &
2074 NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
2075 || (sign_CIFS_PDUs > 1))
2076 ses->server->secMode |=
2077 SECMODE_SIGN_REQUIRED;
2078 if ((SecurityBlob2->NegotiateFlags &
2079 NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
2080 ses->server->secMode |=
2081 SECMODE_SIGN_ENABLED;
2083 if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
2084 if ((long) (bcc_ptr) % 2) {
2086 (BCC(smb_buffer_response)
2088 bcc_ptr++; /* Unicode strings must be word aligned */
2092 (smb_buffer_response) / 2;
2095 UniStrnlen((wchar_t *) bcc_ptr,
2096 remaining_words - 1);
2097 /* We look for obvious messed up bcc or strings in response so we do not go off
2098 the end since (at least) WIN2K and Windows XP have a major bug in not null
2099 terminating last Unicode string in response */
2101 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2102 cifs_strfromUCS_le(ses->serverOS,
2106 bcc_ptr += 2 * (len + 1);
2107 remaining_words -= len + 1;
2108 ses->serverOS[2 * len] = 0;
2109 ses->serverOS[1 + (2 * len)] = 0;
2110 if (remaining_words > 0) {
2111 len = UniStrnlen((wchar_t *)
2116 cifs_kcalloc(2 * (len + 1),
2118 cifs_strfromUCS_le(ses->
2124 bcc_ptr += 2 * (len + 1);
2125 ses->serverNOS[2 * len] = 0;
2128 remaining_words -= len + 1;
2129 if (remaining_words > 0) {
2130 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2131 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2156 } /* else no more room so create dummy domain string */
2161 } else { /* no room so create dummy domain and NOS string */
2163 cifs_kcalloc(2, GFP_KERNEL);
2165 cifs_kcalloc(2, GFP_KERNEL);
2167 } else { /* ASCII */
2168 len = strnlen(bcc_ptr, 1024);
2169 if (((long) bcc_ptr + len) - (long)
2170 pByteArea(smb_buffer_response)
2171 <= BCC(smb_buffer_response)) {
2173 cifs_kcalloc(len + 1,
2175 strncpy(ses->serverOS,
2179 bcc_ptr[0] = 0; /* null terminate string */
2182 len = strnlen(bcc_ptr, 1024);
2184 cifs_kcalloc(len + 1,
2186 strncpy(ses->serverNOS, bcc_ptr, len);
2191 len = strnlen(bcc_ptr, 1024);
2193 cifs_kcalloc(len + 1,
2195 strncpy(ses->serverDomain, bcc_ptr, len);
2201 ("Variable field of length %d extends beyond end of smb ",
2206 (" Security Blob Length extends beyond end of SMB"));
2209 cERROR(1, ("No session structure passed in."));
2213 (" Invalid Word count %d: ",
2214 smb_buffer_response->WordCount));
2219 cifs_buf_release(smb_buffer);
2225 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2226 char *ntlm_session_key, int ntlmv2_flag,
2227 const struct nls_table *nls_codepage)
2229 struct smb_hdr *smb_buffer;
2230 struct smb_hdr *smb_buffer_response;
2231 SESSION_SETUP_ANDX *pSMB;
2232 SESSION_SETUP_ANDX *pSMBr;
2234 char *user = ses->userName;
2235 char *domain = ses->domainName;
2237 int remaining_words = 0;
2238 int bytes_returned = 0;
2240 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2241 PAUTHENTICATE_MESSAGE SecurityBlob;
2243 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2245 smb_buffer = cifs_buf_get();
2246 if (smb_buffer == 0) {
2249 smb_buffer_response = smb_buffer;
2250 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2251 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2253 /* send SMBsessionSetup here */
2254 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2255 0 /* no tCon exists yet */ , 12 /* wct */ );
2256 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2257 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2258 pSMB->req.AndXCommand = 0xFF;
2259 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2260 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2262 pSMB->req.hdr.Uid = ses->Suid;
2264 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2265 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2267 pSMB->req.Capabilities =
2268 CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2269 CAP_EXTENDED_SECURITY;
2270 if (ses->capabilities & CAP_UNICODE) {
2271 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2272 pSMB->req.Capabilities |= CAP_UNICODE;
2274 if (ses->capabilities & CAP_STATUS32) {
2275 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2276 pSMB->req.Capabilities |= CAP_STATUS32;
2278 if (ses->capabilities & CAP_DFS) {
2279 smb_buffer->Flags2 |= SMBFLG2_DFS;
2280 pSMB->req.Capabilities |= CAP_DFS;
2282 pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
2284 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2285 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2286 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2287 SecurityBlob->MessageType = NtLmAuthenticate;
2288 bcc_ptr += SecurityBlobLength;
2289 SecurityBlob->NegotiateFlags =
2290 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2291 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2292 0x80000000 | NTLMSSP_NEGOTIATE_128;
2294 SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2296 SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
2298 /* setup pointers to domain name and workstation name */
2300 SecurityBlob->WorkstationName.Buffer = 0;
2301 SecurityBlob->WorkstationName.Length = 0;
2302 SecurityBlob->WorkstationName.MaximumLength = 0;
2303 SecurityBlob->SessionKey.Length = 0;
2304 SecurityBlob->SessionKey.MaximumLength = 0;
2305 SecurityBlob->SessionKey.Buffer = 0;
2307 SecurityBlob->LmChallengeResponse.Length = 0;
2308 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2309 SecurityBlob->LmChallengeResponse.Buffer = 0;
2311 SecurityBlob->NtChallengeResponse.Length =
2312 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2313 SecurityBlob->NtChallengeResponse.MaximumLength =
2314 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2315 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2316 SecurityBlob->NtChallengeResponse.Buffer =
2317 cpu_to_le32(SecurityBlobLength);
2318 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2319 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2321 if (ses->capabilities & CAP_UNICODE) {
2322 if (domain == NULL) {
2323 SecurityBlob->DomainName.Buffer = 0;
2324 SecurityBlob->DomainName.Length = 0;
2325 SecurityBlob->DomainName.MaximumLength = 0;
2327 SecurityBlob->DomainName.Length =
2328 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2330 SecurityBlob->DomainName.Length *= 2;
2331 SecurityBlob->DomainName.MaximumLength =
2332 cpu_to_le16(SecurityBlob->DomainName.Length);
2333 SecurityBlob->DomainName.Buffer =
2334 cpu_to_le32(SecurityBlobLength);
2335 bcc_ptr += SecurityBlob->DomainName.Length;
2336 SecurityBlobLength += SecurityBlob->DomainName.Length;
2337 SecurityBlob->DomainName.Length =
2338 cpu_to_le16(SecurityBlob->DomainName.Length);
2341 SecurityBlob->UserName.Buffer = 0;
2342 SecurityBlob->UserName.Length = 0;
2343 SecurityBlob->UserName.MaximumLength = 0;
2345 SecurityBlob->UserName.Length =
2346 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2348 SecurityBlob->UserName.Length *= 2;
2349 SecurityBlob->UserName.MaximumLength =
2350 cpu_to_le16(SecurityBlob->UserName.Length);
2351 SecurityBlob->UserName.Buffer =
2352 cpu_to_le32(SecurityBlobLength);
2353 bcc_ptr += SecurityBlob->UserName.Length;
2354 SecurityBlobLength += SecurityBlob->UserName.Length;
2355 SecurityBlob->UserName.Length =
2356 cpu_to_le16(SecurityBlob->UserName.Length);
2359 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2360 SecurityBlob->WorkstationName.Length *= 2;
2361 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2362 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2363 bcc_ptr += SecurityBlob->WorkstationName.Length;
2364 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2365 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2367 if ((long) bcc_ptr % 2) {
2372 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2374 bcc_ptr += 2 * bytes_returned;
2376 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
2378 bcc_ptr += 2 * bytes_returned;
2379 bcc_ptr += 2; /* null term version string */
2381 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2383 bcc_ptr += 2 * bytes_returned;
2386 bcc_ptr += 2; /* null terminate network opsys string */
2389 bcc_ptr += 2; /* null domain */
2390 } else { /* ASCII */
2391 if (domain == NULL) {
2392 SecurityBlob->DomainName.Buffer = 0;
2393 SecurityBlob->DomainName.Length = 0;
2394 SecurityBlob->DomainName.MaximumLength = 0;
2396 SecurityBlob->NegotiateFlags |=
2397 NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2398 strncpy(bcc_ptr, domain, 63);
2399 SecurityBlob->DomainName.Length = strnlen(domain, 64);
2400 SecurityBlob->DomainName.MaximumLength =
2401 cpu_to_le16(SecurityBlob->DomainName.Length);
2402 SecurityBlob->DomainName.Buffer =
2403 cpu_to_le32(SecurityBlobLength);
2404 bcc_ptr += SecurityBlob->DomainName.Length;
2405 SecurityBlobLength += SecurityBlob->DomainName.Length;
2406 SecurityBlob->DomainName.Length =
2407 cpu_to_le16(SecurityBlob->DomainName.Length);
2410 SecurityBlob->UserName.Buffer = 0;
2411 SecurityBlob->UserName.Length = 0;
2412 SecurityBlob->UserName.MaximumLength = 0;
2414 strncpy(bcc_ptr, user, 63);
2415 SecurityBlob->UserName.Length = strnlen(user, 64);
2416 SecurityBlob->UserName.MaximumLength =
2417 cpu_to_le16(SecurityBlob->UserName.Length);
2418 SecurityBlob->UserName.Buffer =
2419 cpu_to_le32(SecurityBlobLength);
2420 bcc_ptr += SecurityBlob->UserName.Length;
2421 SecurityBlobLength += SecurityBlob->UserName.Length;
2422 SecurityBlob->UserName.Length =
2423 cpu_to_le16(SecurityBlob->UserName.Length);
2425 /* BB fill in our workstation name if known BB */
2427 strcpy(bcc_ptr, "Linux version ");
2428 bcc_ptr += strlen("Linux version ");
2429 strcpy(bcc_ptr, UTS_RELEASE);
2430 bcc_ptr += strlen(UTS_RELEASE) + 1;
2431 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2432 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2433 bcc_ptr++; /* null domain */
2436 SecurityBlob->NegotiateFlags =
2437 cpu_to_le32(SecurityBlob->NegotiateFlags);
2438 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2439 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2440 smb_buffer->smb_buf_length += BCC(smb_buffer);
2441 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
2443 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2444 &bytes_returned, 1);
2446 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2447 } else if ((smb_buffer_response->WordCount == 3)
2448 || (smb_buffer_response->WordCount == 4)) {
2449 pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
2450 pSMBr->resp.SecurityBlobLength =
2451 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2452 if (pSMBr->resp.Action & GUEST_LOGIN)
2453 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2454 /* if(SecurityBlob2->MessageType != NtLm??){
2455 cFYI("Unexpected message type on auth response is %d "));
2459 ("Does UID on challenge %d match auth response UID %d ",
2460 ses->Suid, smb_buffer_response->Uid));
2461 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2462 bcc_ptr = pByteArea(smb_buffer_response);
2463 /* response can have either 3 or 4 word count - Samba sends 3 */
2464 if ((pSMBr->resp.hdr.WordCount == 3)
2465 || ((pSMBr->resp.hdr.WordCount == 4)
2466 && (pSMBr->resp.SecurityBlobLength <
2467 pSMBr->resp.ByteCount))) {
2468 if (pSMBr->resp.hdr.WordCount == 4) {
2470 pSMBr->resp.SecurityBlobLength;
2472 ("Security Blob Length %d ",
2473 pSMBr->resp.SecurityBlobLength));
2477 ("NTLMSSP response to Authenticate "));
2479 if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
2480 if ((long) (bcc_ptr) % 2) {
2482 (BCC(smb_buffer_response)
2484 bcc_ptr++; /* Unicode strings must be word aligned */
2486 remaining_words = BCC(smb_buffer_response) / 2;
2489 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2490 /* We look for obvious messed up bcc or strings in response so we do not go off
2491 the end since (at least) WIN2K and Windows XP have a major bug in not null
2492 terminating last Unicode string in response */
2494 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2495 cifs_strfromUCS_le(ses->serverOS,
2499 bcc_ptr += 2 * (len + 1);
2500 remaining_words -= len + 1;
2501 ses->serverOS[2 * len] = 0;
2502 ses->serverOS[1 + (2 * len)] = 0;
2503 if (remaining_words > 0) {
2504 len = UniStrnlen((wchar_t *)
2509 cifs_kcalloc(2 * (len + 1),
2511 cifs_strfromUCS_le(ses->
2517 bcc_ptr += 2 * (len + 1);
2518 ses->serverNOS[2 * len] = 0;
2519 ses->serverNOS[1+(2*len)] = 0;
2520 remaining_words -= len + 1;
2521 if (remaining_words > 0) {
2522 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2523 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2548 } /* else no more room so create dummy domain string */
2550 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
2551 } else { /* no room so create dummy domain and NOS string */
2552 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2553 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2555 } else { /* ASCII */
2556 len = strnlen(bcc_ptr, 1024);
2557 if (((long) bcc_ptr + len) -
2558 (long) pByteArea(smb_buffer_response)
2559 <= BCC(smb_buffer_response)) {
2560 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2561 strncpy(ses->serverOS,bcc_ptr, len);
2564 bcc_ptr[0] = 0; /* null terminate the string */
2567 len = strnlen(bcc_ptr, 1024);
2568 ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
2569 strncpy(ses->serverNOS, bcc_ptr, len);
2574 len = strnlen(bcc_ptr, 1024);
2575 ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
2576 strncpy(ses->serverDomain, bcc_ptr, len);
2582 ("Variable field of length %d extends beyond end of smb ",
2587 (" Security Blob Length extends beyond end of SMB"));
2590 cERROR(1, ("No session structure passed in."));
2594 (" Invalid Word count %d: ",
2595 smb_buffer_response->WordCount));
2600 cifs_buf_release(smb_buffer);
2606 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2607 const char *tree, struct cifsTconInfo *tcon,
2608 const struct nls_table *nls_codepage)
2610 struct smb_hdr *smb_buffer;
2611 struct smb_hdr *smb_buffer_response;
2621 smb_buffer = cifs_buf_get();
2622 if (smb_buffer == 0) {
2625 smb_buffer_response = smb_buffer;
2627 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2628 0 /*no tid */ , 4 /*wct */ );
2629 smb_buffer->Uid = ses->Suid;
2630 pSMB = (TCONX_REQ *) smb_buffer;
2631 pSMBr = (TCONX_RSP *) smb_buffer_response;
2633 pSMB->AndXCommand = 0xFF;
2634 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2635 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2636 bcc_ptr = &(pSMB->Password[0]);
2637 bcc_ptr++; /* skip password */
2639 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2640 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2642 if (ses->capabilities & CAP_STATUS32) {
2643 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2645 if (ses->capabilities & CAP_DFS) {
2646 smb_buffer->Flags2 |= SMBFLG2_DFS;
2648 if (ses->capabilities & CAP_UNICODE) {
2649 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2651 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2652 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2653 bcc_ptr += 2; /* skip trailing null */
2654 } else { /* ASCII */
2656 strcpy(bcc_ptr, tree);
2657 bcc_ptr += strlen(tree) + 1;
2659 strcpy(bcc_ptr, "?????");
2660 bcc_ptr += strlen("?????");
2662 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2663 smb_buffer->smb_buf_length += BCC(smb_buffer);
2664 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
2666 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2668 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2669 /* above now done in SendReceive */
2670 if ((rc == 0) && (tcon != NULL)) {
2671 tcon->tidStatus = CifsGood;
2672 tcon->tid = smb_buffer_response->Tid;
2673 bcc_ptr = pByteArea(smb_buffer_response);
2674 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2675 /* skip service field (NB: this field is always ASCII) */
2676 bcc_ptr += length + 1;
2677 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2678 if (smb_buffer->Flags2 &= SMBFLG2_UNICODE) {
2679 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2680 if (((long) bcc_ptr + (2 * length)) -
2681 (long) pByteArea(smb_buffer_response) <=
2682 BCC(smb_buffer_response)) {
2683 if(tcon->nativeFileSystem)
2684 kfree(tcon->nativeFileSystem);
2685 tcon->nativeFileSystem =
2686 cifs_kcalloc(length + 2, GFP_KERNEL);
2687 cifs_strfromUCS_le(tcon->nativeFileSystem,
2688 (wchar_t *) bcc_ptr,
2689 length, nls_codepage);
2690 bcc_ptr += 2 * length;
2691 bcc_ptr[0] = 0; /* null terminate the string */
2695 /* else do not bother copying these informational fields */
2697 length = strnlen(bcc_ptr, 1024);
2698 if (((long) bcc_ptr + length) -
2699 (long) pByteArea(smb_buffer_response) <=
2700 BCC(smb_buffer_response)) {
2701 if(tcon->nativeFileSystem)
2702 kfree(tcon->nativeFileSystem);
2703 tcon->nativeFileSystem =
2704 cifs_kcalloc(length + 1, GFP_KERNEL);
2705 strncpy(tcon->nativeFileSystem, bcc_ptr,
2708 /* else do not bother copying these informational fields */
2710 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2711 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2712 } else if ((rc == 0) && tcon == NULL) {
2713 /* all we need to save for IPC$ connection */
2714 ses->ipc_tid = smb_buffer_response->Tid;
2718 cifs_buf_release(smb_buffer);
2723 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
2727 struct cifsSesInfo *ses = NULL;
2731 if (cifs_sb->tcon) {
2732 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
2733 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
2738 tconInfoFree(cifs_sb->tcon);
2739 if ((ses) && (ses->server)) {
2740 cFYI(1, ("About to do SMBLogoff "));
2741 rc = CIFSSMBLogoff(xid, ses);
2746 set_current_state(TASK_INTERRUPTIBLE);
2747 schedule_timeout(HZ / 4); /* give captive thread time to exit */
2748 if((ses->server) && (ses->server->ssocket)) {
2749 cFYI(1,("Waking up socket by sending it signal "));
2750 send_sig(SIGKILL,ses->server->tsk,1);
2753 cFYI(1, ("No session or bad tcon"));
2756 cifs_sb->tcon = NULL;
2758 set_current_state(TASK_INTERRUPTIBLE);
2759 schedule_timeout(HZ / 2);
2765 return rc; /* BB check if we should always return zero here */
2768 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2769 struct nls_table * nls_info)
2772 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
2773 int ntlmv2_flag = FALSE;
2775 /* what if server changes its buffer size after dropping the session? */
2776 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
2777 rc = CIFSSMBNegotiate(xid, pSesInfo);
2778 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
2779 rc = CIFSSMBNegotiate(xid, pSesInfo);
2784 pSesInfo->server->tcpStatus = CifsGood;
2787 pSesInfo->capabilities = pSesInfo->server->capabilities;
2788 if(linuxExtEnabled == 0)
2789 pSesInfo->capabilities &= (~CAP_UNIX);
2790 pSesInfo->sequence_number = 0;
2791 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2792 pSesInfo->server->secMode,
2793 pSesInfo->server->capabilities,
2794 pSesInfo->server->timeZone));
2795 if (extended_security
2796 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
2797 && (pSesInfo->server->secType == NTLMSSP)) {
2798 cFYI(1, ("New style sesssetup "));
2799 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
2800 NULL /* security blob */,
2801 0 /* blob length */,
2803 } else if (extended_security
2804 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
2805 && (pSesInfo->server->secType == RawNTLMSSP)) {
2806 cFYI(1, ("NTLMSSP sesssetup "));
2807 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
2814 cFYI(1,("Can use more secure NTLM version 2 password hash"));
2815 CalcNTLMv2_partial_mac_key(pSesInfo,
2817 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
2819 CalcNTLMv2_response(pSesInfo,v2_response);
2820 /* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
2822 /* BB Put dummy sig in SessSetup PDU? */
2827 SMBNTencrypt(pSesInfo->password,
2828 pSesInfo->server->cryptKey,
2831 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
2833 pSesInfo->password);
2835 /* for better security the weaker lanman hash not sent
2836 in AuthSessSetup so we no longer calculate it */
2838 rc = CIFSNTLMSSPAuthSessSetup(xid,
2844 } else { /* old style NTLM 0.12 session setup */
2845 SMBNTencrypt(pSesInfo->password,
2846 pSesInfo->server->cryptKey,
2849 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
2850 ntlm_session_key, pSesInfo->password);
2851 rc = CIFSSessSetup(xid, pSesInfo,
2852 ntlm_session_key, nls_info);
2855 cERROR(1,("Send error in SessSetup = %d",rc));
2857 cFYI(1,("CIFS Session Established successfully"));
2858 pSesInfo->status = CifsGood;