4 * Copyright (C) International Business Machines Corp., 2002,2004
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/net.h>
23 #include <linux/string.h>
24 #include <linux/list.h>
25 #include <linux/wait.h>
26 #include <linux/version.h>
27 #include <linux/ipv6.h>
28 #include <linux/pagemap.h>
29 #include <linux/ctype.h>
30 #include <linux/utsname.h>
31 #include <linux/mempool.h>
32 #include <asm/uaccess.h>
33 #include <asm/processor.h>
36 #include "cifsproto.h"
37 #include "cifs_unicode.h"
38 #include "cifs_debug.h"
39 #include "cifs_fs_sb.h"
42 #include "rfc1002pdu.h"
45 #define RFC1001_PORT 139
47 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
49 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
51 extern int cifs_inet_pton(int, const char *, void *dst);
53 extern mempool_t *cifs_req_poolp;
61 char *iocharset; /* local code page for mapping to and from Unicode */
62 char source_rfc1001_name[16]; /* netbios name of client */
75 unsigned short int port;
78 static int ipv4_connect(struct sockaddr_in *psin_server,
79 struct socket **csocket,
81 static int ipv6_connect(struct sockaddr_in6 *psin_server,
82 struct socket **csocket);
86 * cifs tcp session reconnection
88 * mark tcp session as reconnecting so temporarily locked
89 * mark all smb sessions as reconnecting for tcp session
90 * reconnect tcp session
91 * wake up waiters on reconnection? - (not needed currently)
95 cifs_reconnect(struct TCP_Server_Info *server)
98 struct list_head *tmp;
99 struct cifsSesInfo *ses;
100 struct cifsTconInfo *tcon;
101 struct mid_q_entry * mid_entry;
103 spin_lock(&GlobalMid_Lock);
104 if(server->tcpStatus == CifsExiting) {
105 /* the demux thread will exit normally
106 next time through the loop */
107 spin_unlock(&GlobalMid_Lock);
110 server->tcpStatus = CifsNeedReconnect;
111 spin_unlock(&GlobalMid_Lock);
114 cFYI(1, ("Reconnecting tcp session "));
116 /* before reconnecting the tcp session, mark the smb session (uid)
117 and the tid bad so they are not used until reconnected */
118 read_lock(&GlobalSMBSeslock);
119 list_for_each(tmp, &GlobalSMBSessionList) {
120 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
122 if (ses->server == server) {
123 ses->status = CifsNeedReconnect;
127 /* else tcp and smb sessions need reconnection */
129 list_for_each(tmp, &GlobalTreeConnectionList) {
130 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
131 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
132 tcon->tidStatus = CifsNeedReconnect;
135 read_unlock(&GlobalSMBSeslock);
136 /* do not want to be sending data on a socket we are freeing */
137 down(&server->tcpSem);
138 if(server->ssocket) {
139 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
140 server->ssocket->flags));
141 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
142 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
143 server->ssocket->flags));
144 sock_release(server->ssocket);
145 server->ssocket = NULL;
148 spin_lock(&GlobalMid_Lock);
149 list_for_each(tmp, &server->pending_mid_q) {
150 mid_entry = list_entry(tmp, struct
154 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
155 /* Mark other intransit requests as needing retry so
156 we do not immediately mark the session bad again
157 (ie after we reconnect below) as they timeout too */
158 mid_entry->midState = MID_RETRY_NEEDED;
162 spin_unlock(&GlobalMid_Lock);
165 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
167 if(server->protocolType == IPV6) {
168 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
170 rc = ipv4_connect(&server->addr.sockAddr,
172 server->workstation_RFC1001_name);
175 set_current_state(TASK_INTERRUPTIBLE);
176 schedule_timeout(3 * HZ);
178 atomic_inc(&tcpSesReconnectCount);
179 spin_lock(&GlobalMid_Lock);
180 if(server->tcpStatus != CifsExiting)
181 server->tcpStatus = CifsGood;
182 spin_unlock(&GlobalMid_Lock);
183 /* atomic_set(&server->inFlight,0);*/
184 wake_up(&server->response_q);
191 cifs_demultiplex_thread(struct TCP_Server_Info *server)
194 unsigned int pdu_length, total_read;
195 struct smb_hdr *smb_buffer = NULL;
196 struct msghdr smb_msg;
198 struct socket *csocket = server->ssocket;
199 struct list_head *tmp;
200 struct cifsSesInfo *ses;
201 struct task_struct *task_to_wake = NULL;
202 struct mid_q_entry *mid_entry;
206 allow_signal(SIGKILL);
207 current->flags |= PF_MEMALLOC;
208 server->tsk = current; /* save process info to wake at shutdown */
209 cFYI(1, ("Demultiplex PID: %d", current->pid));
210 write_lock(&GlobalSMBSeslock);
211 atomic_inc(&tcpSesAllocCount);
212 length = tcpSesAllocCount.counter;
213 write_unlock(&GlobalSMBSeslock);
215 mempool_resize(cifs_req_poolp,
216 length + CIFS_MIN_RCV_POOL,
220 while (server->tcpStatus != CifsExiting) {
221 if (smb_buffer == NULL)
222 smb_buffer = cifs_buf_get();
224 memset(smb_buffer, 0, sizeof (struct smb_hdr));
226 if (smb_buffer == NULL) {
227 cERROR(1,("Can not get memory for SMB response"));
228 set_current_state(TASK_INTERRUPTIBLE);
229 schedule_timeout(HZ * 3); /* give system time to free memory */
232 iov.iov_base = smb_buffer;
233 iov.iov_len = sizeof (struct smb_hdr) - 1;
234 /* 1 byte less above since wct is not always returned in error cases */
235 smb_msg.msg_control = NULL;
236 smb_msg.msg_controllen = 0;
239 kernel_recvmsg(csocket, &smb_msg,
241 sizeof (struct smb_hdr) -
242 1 /* RFC1001 header and SMB header */ ,
243 MSG_PEEK /* flags see socket.h */ );
245 if(server->tcpStatus == CifsExiting) {
247 } else if (server->tcpStatus == CifsNeedReconnect) {
248 cFYI(1,("Reconnecting after server stopped responding"));
249 cifs_reconnect(server);
250 cFYI(1,("call to reconnect done"));
251 csocket = server->ssocket;
253 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
254 set_current_state(TASK_INTERRUPTIBLE);
255 schedule_timeout(1); /* minimum sleep to prevent looping
256 allowing socket to clear and app threads to set
257 tcpStatus CifsNeedReconnect if server hung */
259 } else if (length <= 0) {
260 if(server->tcpStatus == CifsNew) {
261 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
262 /* some servers kill tcp session rather than returning
263 smb negprot error in which case reconnecting here is
264 not going to help - return error to mount */
267 if(length == -EINTR) {
268 cFYI(1,("cifsd thread killed"));
271 cFYI(1,("Reconnecting after unexpected peek error %d",length));
272 cifs_reconnect(server);
273 csocket = server->ssocket;
274 wake_up(&server->response_q);
278 pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
279 /* Ony read pdu_length after below checks for too short (due
280 to e.g. int overflow) and too long ie beyond end of buf */
281 cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
283 temp = (char *) smb_buffer;
285 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
286 iov.iov_base = smb_buffer;
288 length = kernel_recvmsg(csocket, &smb_msg,
290 cFYI(0,("Received 4 byte keep alive packet"));
291 } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
292 iov.iov_base = smb_buffer;
294 length = kernel_recvmsg(csocket, &smb_msg,
296 cFYI(1,("Good RFC 1002 session rsp"));
297 } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
299 /* we get this from Windows 98 instead of error on SMB negprot response */
300 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
301 if(server->tcpStatus == CifsNew) {
302 /* if nack on negprot (rather than
303 ret of smb negprot error) reconnecting
304 not going to help, ret error to mount */
307 /* give server a second to
308 clean up before reconnect attempt */
309 set_current_state(TASK_INTERRUPTIBLE);
310 schedule_timeout(HZ);
311 /* always try 445 first on reconnect
312 since we get NACK on some if we ever
313 connected to port 139 (the NACK is
314 since we do not begin with RFC1001
315 session initialize frame) */
316 server->addr.sockAddr.sin_port = CIFS_PORT;
317 cifs_reconnect(server);
318 csocket = server->ssocket;
319 wake_up(&server->response_q);
322 } else if (temp[0] != (char) 0) {
323 cERROR(1,("Unknown RFC 1002 frame"));
324 cifs_dump_mem(" Received Data: ", temp, length);
325 cifs_reconnect(server);
326 csocket = server->ssocket;
329 if ((length != sizeof (struct smb_hdr) - 1)
331 CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE)
333 sizeof (struct smb_hdr) - 1)
336 (smb_buffer, smb_buffer->Mid))) {
338 ("Invalid size or format for SMB found with length %d and pdu_lenght %d",
339 length, pdu_length));
340 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
341 /* could we fix this network corruption by finding next
342 smb header (instead of killing the session) and
343 restart reading from next valid SMB found? */
344 cifs_reconnect(server);
345 csocket = server->ssocket;
347 } else { /* length ok */
350 iov.iov_base = smb_buffer;
351 iov.iov_len = pdu_length;
353 total_read < pdu_length;
354 total_read += length) {
355 length = kernel_recvmsg(csocket, &smb_msg,
357 pdu_length - total_read, 0);
360 ("Zero length receive when expecting %d ",
361 pdu_length - total_read));
362 cifs_reconnect(server);
363 csocket = server->ssocket;
369 dump_smb(smb_buffer, length);
371 (smb_buffer, smb_buffer->Mid, total_read)) {
372 cERROR(1, ("Bad SMB Received "));
377 spin_lock(&GlobalMid_Lock);
378 list_for_each(tmp, &server->pending_mid_q) {
379 mid_entry = list_entry(tmp, struct
383 if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
385 (" Mid 0x%x matched - waking up ",mid_entry->mid));
386 task_to_wake = mid_entry->tsk;
387 mid_entry->resp_buf =
389 mid_entry->midState =
390 MID_RESPONSE_RECEIVED;
393 spin_unlock(&GlobalMid_Lock);
395 smb_buffer = NULL; /* will be freed by users thread after he is done */
396 wake_up_process(task_to_wake);
397 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
398 cERROR(1, ("No task to wake, unknown frame rcvd!"));
399 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
404 ("Frame less than four bytes received %d bytes long.",
407 length = kernel_recvmsg(csocket, &smb_msg,
409 length, 0); /* throw away junk frame */
411 (" with junk 0x%x in it ",
412 *(__u32 *) smb_buffer));
416 spin_lock(&GlobalMid_Lock);
417 server->tcpStatus = CifsExiting;
419 atomic_set(&server->inFlight, 0);
420 spin_unlock(&GlobalMid_Lock);
421 /* Although there should not be any requests blocked on
422 this queue it can not hurt to be paranoid and try to wake up requests
423 that may haven been blocked when more than 50 at time were on the wire
424 to the same server - they now will see the session is in exit state
425 and get out of SendReceive. */
426 wake_up_all(&server->request_q);
427 /* give those requests time to exit */
428 set_current_state(TASK_INTERRUPTIBLE);
429 schedule_timeout(HZ/8);
431 if(server->ssocket) {
432 sock_release(csocket);
433 server->ssocket = NULL;
435 if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
436 cifs_buf_release(smb_buffer);
438 read_lock(&GlobalSMBSeslock);
439 if (list_empty(&server->pending_mid_q)) {
440 /* loop through server session structures attached to this and mark them dead */
441 list_for_each(tmp, &GlobalSMBSessionList) {
443 list_entry(tmp, struct cifsSesInfo,
445 if (ses->server == server) {
446 ses->status = CifsExiting;
450 read_unlock(&GlobalSMBSeslock);
452 spin_lock(&GlobalMid_Lock);
453 list_for_each(tmp, &server->pending_mid_q) {
454 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
455 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
457 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
458 task_to_wake = mid_entry->tsk;
460 wake_up_process(task_to_wake);
464 spin_unlock(&GlobalMid_Lock);
465 read_unlock(&GlobalSMBSeslock);
466 set_current_state(TASK_INTERRUPTIBLE);
467 /* 1/8th of sec is more than enough time for them to exit */
468 schedule_timeout(HZ/8);
471 if (list_empty(&server->pending_mid_q)) {
472 /* mpx threads have not exited yet give them
473 at least the smb send timeout time for long ops */
474 cFYI(1, ("Wait for exit from demultiplex thread"));
475 set_current_state(TASK_INTERRUPTIBLE);
476 schedule_timeout(46 * HZ);
477 /* if threads still have not exited they are probably never
478 coming home not much else we can do but free the memory */
482 write_lock(&GlobalSMBSeslock);
483 atomic_dec(&tcpSesAllocCount);
484 length = tcpSesAllocCount.counter;
485 write_unlock(&GlobalSMBSeslock);
487 mempool_resize(cifs_req_poolp,
488 length + CIFS_MIN_RCV_POOL,
492 set_current_state(TASK_INTERRUPTIBLE);
493 schedule_timeout(HZ/4);
498 cifs_kcalloc(size_t size, int type)
501 addr = kmalloc(size, type);
503 memset(addr, 0, size);
508 cifs_parse_mount_options(char *options, const char *devname, struct smb_vol *vol)
512 unsigned int temp_len, i, j;
518 memset(vol->source_rfc1001_name,0x20,15);
519 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
520 /* does not have to be a perfect mapping since the field is
521 informational, only used for servers that do not support
522 port 445 and it can be overridden at mount time */
523 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
525 vol->source_rfc1001_name[15] = 0;
527 vol->linux_uid = current->uid; /* current->euid instead? */
528 vol->linux_gid = current->gid;
529 vol->dir_mode = S_IRWXUGO;
530 /* 2767 perms indicate mandatory locking support */
531 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
533 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
539 if(strncmp(options,"sep=",4) == 0) {
540 if(options[4] != 0) {
541 separator[0] = options[4];
544 cFYI(1,("Null separator not allowed"));
548 while ((data = strsep(&options, separator)) != NULL) {
551 if ((value = strchr(data, '=')) != NULL)
553 if (strnicmp(data, "user", 4) == 0) {
554 if (!value || !*value) {
556 "CIFS: invalid or missing username\n");
557 return 1; /* needs_arg; */
559 if (strnlen(value, 200) < 200) {
560 vol->username = value;
562 printk(KERN_WARNING "CIFS: username too long\n");
565 } else if (strnicmp(data, "pass", 4) == 0) {
566 if (!value || !*value) {
567 vol->password = NULL;
570 temp_len = strlen(value);
571 /* removed password length check, NTLM passwords
572 can be arbitrarily long */
574 /* if comma in password, the string will be
575 prematurely null terminated. Commas in password are
576 specified across the cifs mount interface by a double
577 comma ie ,, and a comma used as in other cases ie ','
578 as a parameter delimiter/separator is single and due
579 to the strsep above is temporarily zeroed. */
581 /* NB: password legally can have multiple commas and
582 the only illegal character in a password is null */
584 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
586 value[temp_len] = separator[0];
587 temp_len+=2; /* move after the second comma */
588 while(value[temp_len] != 0) {
589 if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
590 /* single comma indicating start of next parm */
595 if(value[temp_len] == 0) {
599 /* move options to point to start of next parm */
600 options = value + temp_len + 1;
602 /* go from value to (value + temp_len) condensing double commas to singles */
603 vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
604 for(i=0,j=0;i<temp_len;i++,j++) {
605 vol->password[j] = value[i];
606 if(value[i] == separator[0] && value[i+1] == separator[0]) {
607 /* skip second comma */
611 /* value[temp_len] is zeroed above so
612 vol->password[temp_len] guaranteed to be null */
614 vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
615 strcpy(vol->password, value);
617 } else if (strnicmp(data, "ip", 2) == 0) {
618 if (!value || !*value) {
620 } else if (strnlen(value, 35) < 35) {
623 printk(KERN_WARNING "CIFS: ip address too long\n");
626 } else if ((strnicmp(data, "unc", 3) == 0)
627 || (strnicmp(data, "target", 6) == 0)
628 || (strnicmp(data, "path", 4) == 0)) {
629 if (!value || !*value) {
631 "CIFS: invalid path to network resource\n");
632 return 1; /* needs_arg; */
634 if ((temp_len = strnlen(value, 300)) < 300) {
635 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
638 strcpy(vol->UNC,value);
639 if (strncmp(vol->UNC, "//", 2) == 0) {
642 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
644 "CIFS: UNC Path does not begin with // or \\\\ \n");
648 printk(KERN_WARNING "CIFS: UNC name too long\n");
651 } else if ((strnicmp(data, "domain", 3) == 0)
652 || (strnicmp(data, "workgroup", 5) == 0)) {
653 if (!value || !*value) {
654 printk(KERN_WARNING "CIFS: invalid domain name\n");
655 return 1; /* needs_arg; */
657 /* BB are there cases in which a comma can be valid in
658 a domain name and need special handling? */
659 if (strnlen(value, 65) < 65) {
660 vol->domainname = value;
661 cFYI(1, ("Domain name set"));
663 printk(KERN_WARNING "CIFS: domain name too long\n");
666 } else if (strnicmp(data, "iocharset", 9) == 0) {
667 if (!value || !*value) {
668 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
669 return 1; /* needs_arg; */
671 if (strnlen(value, 65) < 65) {
672 if(strnicmp(value,"default",7))
673 vol->iocharset = value;
674 /* if iocharset not set load_nls_default used by caller */
675 cFYI(1, ("iocharset set to %s",value));
677 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
680 } else if (strnicmp(data, "uid", 3) == 0) {
681 if (value && *value) {
683 simple_strtoul(value, &value, 0);
685 } else if (strnicmp(data, "gid", 3) == 0) {
686 if (value && *value) {
688 simple_strtoul(value, &value, 0);
690 } else if (strnicmp(data, "file_mode", 4) == 0) {
691 if (value && *value) {
693 simple_strtoul(value, &value, 0);
695 } else if (strnicmp(data, "dir_mode", 3) == 0) {
696 if (value && *value) {
698 simple_strtoul(value, &value, 0);
700 } else if (strnicmp(data, "port", 4) == 0) {
701 if (value && *value) {
703 simple_strtoul(value, &value, 0);
705 } else if (strnicmp(data, "rsize", 5) == 0) {
706 if (value && *value) {
708 simple_strtoul(value, &value, 0);
710 } else if (strnicmp(data, "wsize", 5) == 0) {
711 if (value && *value) {
713 simple_strtoul(value, &value, 0);
715 } else if (strnicmp(data, "sockopt", 5) == 0) {
716 if (value && *value) {
718 simple_strtoul(value, &value, 0);
720 } else if (strnicmp(data, "netbiosname", 4) == 0) {
721 if (!value || !*value || (*value == ' ')) {
722 cFYI(1,("invalid (empty) netbiosname specified"));
724 memset(vol->source_rfc1001_name,0x20,15);
726 /* BB are there cases in which a comma can be
727 valid in this workstation netbios name (and need
728 special handling)? */
730 /* We do not uppercase netbiosname for user */
734 vol->source_rfc1001_name[i] = value[i];
736 /* The string has 16th byte zero still from
737 set at top of the function */
738 if((i==15) && (value[i] != 0))
739 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
741 } else if (strnicmp(data, "credentials", 4) == 0) {
743 } else if (strnicmp(data, "version", 3) == 0) {
745 } else if (strnicmp(data, "rw", 2) == 0) {
747 } else if ((strnicmp(data, "suid", 4) == 0) ||
748 (strnicmp(data, "nosuid", 6) == 0) ||
749 (strnicmp(data, "exec", 4) == 0) ||
750 (strnicmp(data, "noexec", 6) == 0) ||
751 (strnicmp(data, "nodev", 5) == 0) ||
752 (strnicmp(data, "noauto", 6) == 0) ||
753 (strnicmp(data, "dev", 3) == 0)) {
754 /* The mount tool or mount.cifs helper (if present)
755 uses these opts to set flags, and the flags are read
756 by the kernel vfs layer before we get here (ie
757 before read super) so there is no point trying to
758 parse these options again and set anything and it
759 is ok to just ignore them */
761 } else if (strnicmp(data, "ro", 2) == 0) {
763 } else if (strnicmp(data, "hard", 4) == 0) {
765 } else if (strnicmp(data, "soft", 4) == 0) {
767 } else if (strnicmp(data, "perm", 4) == 0) {
769 } else if (strnicmp(data, "noperm", 6) == 0) {
771 } else if (strnicmp(data, "setuids", 7) == 0) {
773 } else if (strnicmp(data, "nosetuids", 9) == 0) {
775 } else if (strnicmp(data, "nohard", 6) == 0) {
777 } else if (strnicmp(data, "nosoft", 6) == 0) {
779 } else if (strnicmp(data, "nointr", 6) == 0) {
781 } else if (strnicmp(data, "intr", 4) == 0) {
783 } else if (strnicmp(data, "noac", 4) == 0) {
784 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
786 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
788 if (vol->UNC == NULL) {
789 if(devname == NULL) {
790 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
793 if ((temp_len = strnlen(devname, 300)) < 300) {
794 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
797 strcpy(vol->UNC,devname);
798 if (strncmp(vol->UNC, "//", 2) == 0) {
801 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
802 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
806 printk(KERN_WARNING "CIFS: UNC name too long\n");
811 vol->UNCip = &vol->UNC[2];
816 static struct cifsSesInfo *
817 cifs_find_tcp_session(__u32 new_target_ip_addr,
818 char *userName, struct TCP_Server_Info **psrvTcp)
820 struct list_head *tmp;
821 struct cifsSesInfo *ses;
824 read_lock(&GlobalSMBSeslock);
825 list_for_each(tmp, &GlobalSMBSessionList) {
826 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
828 if (ses->server->addr.sockAddr.sin_addr.s_addr ==
829 new_target_ip_addr) {
830 /* BB lock server and tcp session and increment use count here?? */
831 *psrvTcp = ses->server; /* found a match on the TCP session */
832 /* BB check if reconnection needed */
834 (ses->userName, userName,
835 MAX_USERNAME_SIZE) == 0){
836 read_unlock(&GlobalSMBSeslock);
837 return ses; /* found exact match on both tcp and SMB sessions */
841 /* else tcp and smb sessions need reconnection */
843 read_unlock(&GlobalSMBSeslock);
847 static struct cifsTconInfo *
848 find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
850 struct list_head *tmp;
851 struct cifsTconInfo *tcon;
853 read_lock(&GlobalSMBSeslock);
854 list_for_each(tmp, &GlobalTreeConnectionList) {
855 cFYI(1, ("Next tcon - "));
856 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
858 if (tcon->ses->server) {
860 (" old ip addr: %x == new ip %x ?",
861 tcon->ses->server->addr.sockAddr.sin_addr.
862 s_addr, new_target_ip_addr));
863 if (tcon->ses->server->addr.sockAddr.sin_addr.
864 s_addr == new_target_ip_addr) {
865 /* BB lock tcon and server and tcp session and increment use count here? */
866 /* found a match on the TCP session */
867 /* BB check if reconnection needed */
868 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
869 tcon->treeName, uncName));
871 (tcon->treeName, uncName,
872 MAX_TREE_SIZE) == 0) {
874 ("Matched UNC, old user: %s == new: %s ?",
875 tcon->treeName, uncName));
877 (tcon->ses->userName,
879 MAX_USERNAME_SIZE) == 0) {
880 read_unlock(&GlobalSMBSeslock);
881 return tcon;/* also matched user (smb session)*/
888 read_unlock(&GlobalSMBSeslock);
893 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
894 const char *old_path, const struct nls_table *nls_codepage)
896 unsigned char *referrals = NULL;
897 unsigned int num_referrals;
900 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
901 &num_referrals, &referrals);
903 /* BB Add in code to: if valid refrl, if not ip address contact
904 the helper that resolves tcp names, mount to it, try to
905 tcon to it unmount it if fail */
914 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
915 const char *old_path, const struct nls_table *nls_codepage,
916 unsigned int *pnum_referrals, unsigned char ** preferrals)
923 if (pSesInfo->ipc_tid == 0) {
924 temp_unc = kmalloc(2 /* for slashes */ +
925 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
926 + 1 + 4 /* slash IPC$ */ + 2,
928 if (temp_unc == NULL)
932 strcpy(temp_unc + 2, pSesInfo->serverName);
933 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
934 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
936 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
940 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
941 pnum_referrals, nls_codepage);
946 /* See RFC1001 section 14 on representation of Netbios names */
947 static void rfc1002mangle(char * target,char * source, unsigned int length)
951 for(i=0,j=0;i<(length);i++) {
952 /* mask a nibble at a time and encode */
953 target[j] = 'A' + (0x0F & (source[i] >> 4));
954 target[j+1] = 'A' + (0x0F & source[i]);
962 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
967 unsigned short int orig_port = 0;
969 if(*csocket == NULL) {
970 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
972 cERROR(1, ("Error %d creating socket",rc));
976 /* BB other socket options to set KEEPALIVE, NODELAY? */
977 cFYI(1,("Socket created"));
978 (*csocket)->sk->sk_allocation = GFP_NOFS;
982 psin_server->sin_family = AF_INET;
983 if(psin_server->sin_port) { /* user overrode default port */
984 rc = (*csocket)->ops->connect(*csocket,
985 (struct sockaddr *) psin_server,
986 sizeof (struct sockaddr_in),0);
992 /* save original port so we can retry user specified port
993 later if fall back ports fail this time */
994 orig_port = psin_server->sin_port;
996 /* do not retry on the same port we just failed on */
997 if(psin_server->sin_port != htons(CIFS_PORT)) {
998 psin_server->sin_port = htons(CIFS_PORT);
1000 rc = (*csocket)->ops->connect(*csocket,
1001 (struct sockaddr *) psin_server,
1002 sizeof (struct sockaddr_in),0);
1008 psin_server->sin_port = htons(RFC1001_PORT);
1009 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1010 psin_server, sizeof (struct sockaddr_in),0);
1015 /* give up here - unless we want to retry on different
1016 protocol families some day */
1019 psin_server->sin_port = orig_port;
1020 cFYI(1,("Error %d connecting to server via ipv4",rc));
1021 sock_release(*csocket);
1025 /* Eventually check for other socket options to change from
1026 the default. sock_setsockopt not used because it expects
1027 user space buffer */
1028 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1030 /* send RFC1001 sessinit */
1032 if(psin_server->sin_port == htons(139)) {
1033 /* some servers require RFC1001 sessinit before sending
1034 negprot - BB check reconnection in case where second
1035 sessinit is sent but no second negprot */
1036 struct rfc1002_session_packet * ses_init_buf;
1037 struct smb_hdr * smb_buf;
1038 ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1040 ses_init_buf->trailer.session_req.called_len = 32;
1041 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1042 DEFAULT_CIFS_CALLED_NAME,16);
1043 ses_init_buf->trailer.session_req.calling_len = 32;
1044 /* calling name ends in null (byte 16) from old smb
1046 if(netbios_name && (netbios_name[0] !=0)) {
1047 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1050 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1051 "LINUX_CIFS_CLNT",16);
1053 ses_init_buf->trailer.session_req.scope1 = 0;
1054 ses_init_buf->trailer.session_req.scope2 = 0;
1055 smb_buf = (struct smb_hdr *)ses_init_buf;
1056 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1057 smb_buf->smb_buf_length = 0x81000044;
1058 rc = smb_send(*csocket, smb_buf, 0x44,
1059 (struct sockaddr *)psin_server);
1060 kfree(ses_init_buf);
1062 /* else the negprot may still work without this
1063 even though malloc failed */
1071 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1076 if(*csocket == NULL) {
1077 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1079 cERROR(1, ("Error %d creating ipv6 socket",rc));
1083 /* BB other socket options to set KEEPALIVE, NODELAY? */
1084 cFYI(1,("ipv6 Socket created"));
1085 (*csocket)->sk->sk_allocation = GFP_NOFS;
1089 psin_server->sin6_family = AF_INET6;
1091 if(psin_server->sin6_port) { /* user overrode default port */
1092 rc = (*csocket)->ops->connect(*csocket,
1093 (struct sockaddr *) psin_server,
1094 sizeof (struct sockaddr_in6),0);
1100 /* do not retry on the same port we just failed on */
1101 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1102 psin_server->sin6_port = htons(CIFS_PORT);
1104 rc = (*csocket)->ops->connect(*csocket,
1105 (struct sockaddr *) psin_server,
1106 sizeof (struct sockaddr_in6),0);
1112 psin_server->sin6_port = htons(RFC1001_PORT);
1113 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1114 psin_server, sizeof (struct sockaddr_in6),0);
1119 /* give up here - unless we want to retry on different
1120 protocol families some day */
1122 cFYI(1,("Error %d connecting to server via ipv6",rc));
1123 sock_release(*csocket);
1127 /* Eventually check for other socket options to change from
1128 the default. sock_setsockopt not used because it expects
1129 user space buffer */
1130 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1136 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1137 char *mount_data, const char *devname)
1141 struct socket *csocket = NULL;
1142 struct sockaddr_in sin_server;
1143 struct sockaddr_in6 sin_server6;
1144 struct smb_vol volume_info;
1145 struct cifsSesInfo *pSesInfo = NULL;
1146 struct cifsSesInfo *existingCifsSes = NULL;
1147 struct cifsTconInfo *tcon = NULL;
1148 struct TCP_Server_Info *srvTcp = NULL;
1152 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1154 memset(&volume_info,0,sizeof(struct smb_vol));
1155 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1157 kfree(volume_info.UNC);
1158 if(volume_info.password)
1159 kfree(volume_info.password);
1164 if (volume_info.username) {
1165 cFYI(1, ("Username: %s ", volume_info.username));
1168 cifserror("No username specified ");
1169 /* In userspace mount helper we can get user name from alternate
1170 locations such as env variables and files on disk */
1172 kfree(volume_info.UNC);
1173 if(volume_info.password)
1174 kfree(volume_info.password);
1179 if (volume_info.UNCip && volume_info.UNC) {
1180 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1183 /* not ipv4 address, try ipv6 */
1184 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1188 /* we failed translating address */
1190 kfree(volume_info.UNC);
1191 if(volume_info.password)
1192 kfree(volume_info.password);
1197 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1200 } else if (volume_info.UNCip){
1201 /* BB using ip addr as server name connect to the DFS root below */
1202 cERROR(1,("Connecting to DFS root not implemented yet"));
1204 kfree(volume_info.UNC);
1205 if(volume_info.password)
1206 kfree(volume_info.password);
1209 } else /* which servers DFS root would we conect to */ {
1211 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1213 kfree(volume_info.UNC);
1214 if(volume_info.password)
1215 kfree(volume_info.password);
1220 /* this is needed for ASCII cp to Unicode converts */
1221 if(volume_info.iocharset == NULL) {
1222 cifs_sb->local_nls = load_nls_default();
1223 /* load_nls_default can not return null */
1225 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1226 if(cifs_sb->local_nls == NULL) {
1227 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1229 kfree(volume_info.UNC);
1230 if(volume_info.password)
1231 kfree(volume_info.password);
1238 cifs_find_tcp_session(sin_server.sin_addr.s_addr,
1239 volume_info.username, &srvTcp);
1241 cFYI(1, ("Existing tcp session with server found "));
1242 } else { /* create socket */
1243 if(volume_info.port)
1244 sin_server.sin_port = htons(volume_info.port);
1246 sin_server.sin_port = 0;
1247 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1250 ("Error connecting to IPv4 socket. Aborting operation"));
1252 sock_release(csocket);
1254 kfree(volume_info.UNC);
1255 if(volume_info.password)
1256 kfree(volume_info.password);
1261 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1262 if (srvTcp == NULL) {
1264 sock_release(csocket);
1266 kfree(volume_info.UNC);
1267 if(volume_info.password)
1268 kfree(volume_info.password);
1272 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1273 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1274 atomic_set(&srvTcp->inFlight,0);
1275 /* BB Add code for ipv6 case too */
1276 srvTcp->ssocket = csocket;
1277 srvTcp->protocolType = IPV4;
1278 init_waitqueue_head(&srvTcp->response_q);
1279 init_waitqueue_head(&srvTcp->request_q);
1280 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1281 /* at this point we are the only ones with the pointer
1282 to the struct since the kernel thread not created yet
1283 so no need to spinlock this init of tcpStatus */
1284 srvTcp->tcpStatus = CifsNew;
1285 init_MUTEX(&srvTcp->tcpSem);
1286 kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1287 CLONE_FS | CLONE_FILES | CLONE_VM);
1288 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1292 if (existingCifsSes) {
1293 pSesInfo = existingCifsSes;
1294 cFYI(1, ("Existing smb sess found "));
1295 if(volume_info.password)
1296 kfree(volume_info.password);
1297 /* volume_info.UNC freed at end of function */
1299 cFYI(1, ("Existing smb sess not found "));
1300 pSesInfo = sesInfoAlloc();
1301 if (pSesInfo == NULL)
1304 pSesInfo->server = srvTcp;
1305 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1306 NIPQUAD(sin_server.sin_addr.s_addr));
1310 /* volume_info.password freed at unmount */
1311 if (volume_info.password)
1312 pSesInfo->password = volume_info.password;
1313 if (volume_info.username)
1314 strncpy(pSesInfo->userName,
1315 volume_info.username,MAX_USERNAME_SIZE);
1316 if (volume_info.domainname)
1317 strncpy(pSesInfo->domainName,
1318 volume_info.domainname,MAX_USERNAME_SIZE);
1319 pSesInfo->linux_uid = volume_info.linux_uid;
1320 down(&pSesInfo->sesSem);
1321 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1322 up(&pSesInfo->sesSem);
1324 atomic_inc(&srvTcp->socketUseCount);
1326 if(volume_info.password)
1327 kfree(volume_info.password);
1330 /* search for existing tcon to this server share */
1332 if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
1333 cifs_sb->rsize = volume_info.rsize;
1335 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1336 if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
1337 cifs_sb->wsize = volume_info.wsize;
1339 cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1340 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1341 cifs_sb->rsize = PAGE_CACHE_SIZE;
1342 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1344 cifs_sb->mnt_uid = volume_info.linux_uid;
1345 cifs_sb->mnt_gid = volume_info.linux_gid;
1346 cifs_sb->mnt_file_mode = volume_info.file_mode;
1347 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1348 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1350 if(volume_info.noperm)
1351 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1352 if(volume_info.setuids)
1353 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1356 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1357 volume_info.username);
1359 cFYI(1, ("Found match on UNC path "));
1360 /* we can have only one retry value for a connection
1361 to a share so for resources mounted more than once
1362 to the same server share the last value passed in
1363 for the retry flag is used */
1364 tcon->retry = volume_info.retry;
1366 tcon = tconInfoAlloc();
1370 /* check for null share name ie connect to dfs root */
1372 /* BB check if this works for exactly length three strings */
1373 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1374 && (strchr(volume_info.UNC + 3, '/') ==
1376 rc = connect_to_dfs_path(xid,
1382 kfree(volume_info.UNC);
1386 rc = CIFSTCon(xid, pSesInfo,
1388 tcon, cifs_sb->local_nls);
1389 cFYI(1, ("CIFS Tcon rc = %d", rc));
1392 atomic_inc(&pSesInfo->inUse);
1393 tcon->retry = volume_info.retry;
1399 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1400 sb->s_maxbytes = (u64) 1 << 63;
1402 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1405 /* on error free sesinfo and tcon struct if needed */
1407 /* if session setup failed, use count is zero but
1408 we still need to free cifsd thread */
1409 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1410 spin_lock(&GlobalMid_Lock);
1411 srvTcp->tcpStatus = CifsExiting;
1412 spin_unlock(&GlobalMid_Lock);
1414 send_sig(SIGKILL,srvTcp->tsk,1);
1416 /* If find_unc succeeded then rc == 0 so we can not end */
1417 if (tcon) /* up accidently freeing someone elses tcon struct */
1419 if (existingCifsSes == 0) {
1421 if ((pSesInfo->server) &&
1422 (pSesInfo->status == CifsGood)) {
1424 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1425 /* if the socketUseCount is now zero */
1426 if((temp_rc == -ESHUTDOWN) &&
1427 (pSesInfo->server->tsk))
1428 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1430 cFYI(1, ("No session or bad tcon"));
1431 sesInfoFree(pSesInfo);
1432 /* pSesInfo = NULL; */
1436 atomic_inc(&tcon->useCount);
1437 cifs_sb->tcon = tcon;
1438 tcon->ses = pSesInfo;
1440 /* do not care if following two calls succeed - informational only */
1441 CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
1442 CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
1443 if (tcon->ses->capabilities & CAP_UNIX)
1444 CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls);
1447 /* volume_info.password is freed above when existing session found
1448 (in which case it is not needed anymore) but when new sesion is created
1449 the password ptr is put in the new session structure (in which case the
1450 password will be freed at unmount time) */
1452 kfree(volume_info.UNC);
1458 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1459 char session_key[CIFS_SESSION_KEY_SIZE],
1460 const struct nls_table *nls_codepage)
1462 struct smb_hdr *smb_buffer;
1463 struct smb_hdr *smb_buffer_response;
1464 SESSION_SETUP_ANDX *pSMB;
1465 SESSION_SETUP_ANDX *pSMBr;
1467 char *user = ses->userName;
1468 char *domain = ses->domainName;
1470 int remaining_words = 0;
1471 int bytes_returned = 0;
1474 cFYI(1, ("In sesssetup "));
1476 smb_buffer = cifs_buf_get();
1477 if (smb_buffer == 0) {
1480 smb_buffer_response = smb_buffer;
1481 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1483 /* send SMBsessionSetup here */
1484 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1485 NULL /* no tCon exists yet */ , 13 /* wct */ );
1487 pSMB->req_no_secext.AndXCommand = 0xFF;
1488 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1489 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1491 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1492 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1494 pSMB->req_no_secext.Capabilities =
1495 CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
1496 if (ses->capabilities & CAP_UNICODE) {
1497 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1498 pSMB->req_no_secext.Capabilities |= CAP_UNICODE;
1500 if (ses->capabilities & CAP_STATUS32) {
1501 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1502 pSMB->req_no_secext.Capabilities |= CAP_STATUS32;
1504 if (ses->capabilities & CAP_DFS) {
1505 smb_buffer->Flags2 |= SMBFLG2_DFS;
1506 pSMB->req_no_secext.Capabilities |= CAP_DFS;
1508 pSMB->req_no_secext.Capabilities =
1509 cpu_to_le32(pSMB->req_no_secext.Capabilities);
1510 /* pSMB->req_no_secext.CaseInsensitivePasswordLength =
1511 CIFS_SESSION_KEY_SIZE; */
1512 pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
1513 pSMB->req_no_secext.CaseSensitivePasswordLength =
1514 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1515 bcc_ptr = pByteArea(smb_buffer);
1516 /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
1517 bcc_ptr += CIFS_SESSION_KEY_SIZE; */
1518 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1519 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1521 if (ses->capabilities & CAP_UNICODE) {
1522 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1527 bytes_returned = 0; /* skill null user */
1530 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1532 bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
1533 bcc_ptr += 2; /* trailing null */
1536 cifs_strtoUCS((wchar_t *) bcc_ptr,
1537 "CIFS_LINUX_DOM", 32, nls_codepage);
1540 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1542 bcc_ptr += 2 * bytes_returned;
1545 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1547 bcc_ptr += 2 * bytes_returned;
1549 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
1551 bcc_ptr += 2 * bytes_returned;
1554 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1556 bcc_ptr += 2 * bytes_returned;
1560 strncpy(bcc_ptr, user, 200);
1561 bcc_ptr += strnlen(user, 200);
1565 if (domain == NULL) {
1566 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1567 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1569 strncpy(bcc_ptr, domain, 64);
1570 bcc_ptr += strnlen(domain, 64);
1574 strcpy(bcc_ptr, "Linux version ");
1575 bcc_ptr += strlen("Linux version ");
1576 strcpy(bcc_ptr, UTS_RELEASE);
1577 bcc_ptr += strlen(UTS_RELEASE) + 1;
1578 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1579 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1581 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1582 smb_buffer->smb_buf_length += BCC(smb_buffer);
1583 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
1585 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1586 &bytes_returned, 1);
1588 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1589 } else if ((smb_buffer_response->WordCount == 3)
1590 || (smb_buffer_response->WordCount == 4)) {
1591 pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
1592 if (pSMBr->resp.Action & GUEST_LOGIN)
1593 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1595 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1596 cFYI(1, ("UID = %d ", ses->Suid));
1597 /* response can have either 3 or 4 word count - Samba sends 3 */
1598 bcc_ptr = pByteArea(smb_buffer_response);
1599 if ((pSMBr->resp.hdr.WordCount == 3)
1600 || ((pSMBr->resp.hdr.WordCount == 4)
1601 && (pSMBr->resp.SecurityBlobLength <
1602 pSMBr->resp.ByteCount))) {
1603 if (pSMBr->resp.hdr.WordCount == 4)
1605 pSMBr->resp.SecurityBlobLength;
1607 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1608 if ((long) (bcc_ptr) % 2) {
1610 (BCC(smb_buffer_response)
1612 bcc_ptr++; /* Unicode strings must be word aligned */
1616 (smb_buffer_response) / 2;
1619 UniStrnlen((wchar_t *) bcc_ptr,
1620 remaining_words - 1);
1621 /* We look for obvious messed up bcc or strings in response so we do not go off
1622 the end since (at least) WIN2K and Windows XP have a major bug in not null
1623 terminating last Unicode string in response */
1624 ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1625 cifs_strfromUCS_le(ses->serverOS,
1626 (wchar_t *)bcc_ptr, len,nls_codepage);
1627 bcc_ptr += 2 * (len + 1);
1628 remaining_words -= len + 1;
1629 ses->serverOS[2 * len] = 0;
1630 ses->serverOS[1 + (2 * len)] = 0;
1631 if (remaining_words > 0) {
1632 len = UniStrnlen((wchar_t *)bcc_ptr,
1635 ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
1636 cifs_strfromUCS_le(ses->serverNOS,
1637 (wchar_t *)bcc_ptr,len,nls_codepage);
1638 bcc_ptr += 2 * (len + 1);
1639 ses->serverNOS[2 * len] = 0;
1640 ses->serverNOS[1 + (2 * len)] = 0;
1641 remaining_words -= len + 1;
1642 if (remaining_words > 0) {
1643 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1644 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1646 cifs_kcalloc(2*(len+1),GFP_KERNEL);
1647 cifs_strfromUCS_le(ses->serverDomain,
1648 (wchar_t *)bcc_ptr,len,nls_codepage);
1649 bcc_ptr += 2 * (len + 1);
1650 ses->serverDomain[2*len] = 0;
1651 ses->serverDomain[1+(2*len)] = 0;
1652 } /* else no more room so create dummy domain string */
1657 } else { /* no room so create dummy domain and NOS string */
1659 cifs_kcalloc(2, GFP_KERNEL);
1661 cifs_kcalloc(2, GFP_KERNEL);
1663 } else { /* ASCII */
1664 len = strnlen(bcc_ptr, 1024);
1665 if (((long) bcc_ptr + len) - (long)
1666 pByteArea(smb_buffer_response)
1667 <= BCC(smb_buffer_response)) {
1668 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1669 strncpy(ses->serverOS,bcc_ptr, len);
1672 bcc_ptr[0] = 0; /* null terminate the string */
1675 len = strnlen(bcc_ptr, 1024);
1676 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1677 strncpy(ses->serverNOS, bcc_ptr, len);
1682 len = strnlen(bcc_ptr, 1024);
1683 ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
1684 strncpy(ses->serverDomain, bcc_ptr, len);
1690 ("Variable field of length %d extends beyond end of smb ",
1695 (" Security Blob Length extends beyond end of SMB"));
1698 cERROR(1, ("No session structure passed in."));
1702 (" Invalid Word count %d: ",
1703 smb_buffer_response->WordCount));
1708 cifs_buf_release(smb_buffer);
1714 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1715 char *SecurityBlob,int SecurityBlobLength,
1716 const struct nls_table *nls_codepage)
1718 struct smb_hdr *smb_buffer;
1719 struct smb_hdr *smb_buffer_response;
1720 SESSION_SETUP_ANDX *pSMB;
1721 SESSION_SETUP_ANDX *pSMBr;
1723 char *user = ses->userName;
1724 char *domain = ses->domainName;
1726 int remaining_words = 0;
1727 int bytes_returned = 0;
1730 cFYI(1, ("In spnego sesssetup "));
1732 smb_buffer = cifs_buf_get();
1733 if (smb_buffer == 0) {
1736 smb_buffer_response = smb_buffer;
1737 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1739 /* send SMBsessionSetup here */
1740 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1741 NULL /* no tCon exists yet */ , 12 /* wct */ );
1742 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1743 pSMB->req.AndXCommand = 0xFF;
1744 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1745 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1747 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1748 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1750 pSMB->req.Capabilities =
1751 CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1752 CAP_EXTENDED_SECURITY;
1753 if (ses->capabilities & CAP_UNICODE) {
1754 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1755 pSMB->req.Capabilities |= CAP_UNICODE;
1757 if (ses->capabilities & CAP_STATUS32) {
1758 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1759 pSMB->req.Capabilities |= CAP_STATUS32;
1761 if (ses->capabilities & CAP_DFS) {
1762 smb_buffer->Flags2 |= SMBFLG2_DFS;
1763 pSMB->req.Capabilities |= CAP_DFS;
1765 pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
1767 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1768 bcc_ptr = pByteArea(smb_buffer);
1769 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1770 bcc_ptr += SecurityBlobLength;
1772 if (ses->capabilities & CAP_UNICODE) {
1773 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1778 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1779 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1780 bcc_ptr += 2; /* trailing null */
1783 cifs_strtoUCS((wchar_t *) bcc_ptr,
1784 "CIFS_LINUX_DOM", 32, nls_codepage);
1787 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1789 bcc_ptr += 2 * bytes_returned;
1792 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1794 bcc_ptr += 2 * bytes_returned;
1796 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
1798 bcc_ptr += 2 * bytes_returned;
1801 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1803 bcc_ptr += 2 * bytes_returned;
1806 strncpy(bcc_ptr, user, 200);
1807 bcc_ptr += strnlen(user, 200);
1810 if (domain == NULL) {
1811 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1812 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1814 strncpy(bcc_ptr, domain, 64);
1815 bcc_ptr += strnlen(domain, 64);
1819 strcpy(bcc_ptr, "Linux version ");
1820 bcc_ptr += strlen("Linux version ");
1821 strcpy(bcc_ptr, UTS_RELEASE);
1822 bcc_ptr += strlen(UTS_RELEASE) + 1;
1823 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1824 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1826 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1827 smb_buffer->smb_buf_length += BCC(smb_buffer);
1828 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
1830 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1831 &bytes_returned, 1);
1833 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1834 } else if ((smb_buffer_response->WordCount == 3)
1835 || (smb_buffer_response->WordCount == 4)) {
1836 pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
1837 pSMBr->resp.SecurityBlobLength =
1838 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1839 if (pSMBr->resp.Action & GUEST_LOGIN)
1840 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1842 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1843 cFYI(1, ("UID = %d ", ses->Suid));
1844 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
1846 /* BB Fix below to make endian neutral !! */
1848 if ((pSMBr->resp.hdr.WordCount == 3)
1849 || ((pSMBr->resp.hdr.WordCount == 4)
1850 && (pSMBr->resp.SecurityBlobLength <
1851 pSMBr->resp.ByteCount))) {
1852 if (pSMBr->resp.hdr.WordCount == 4) {
1854 pSMBr->resp.SecurityBlobLength;
1856 ("Security Blob Length %d ",
1857 pSMBr->resp.SecurityBlobLength));
1860 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1861 if ((long) (bcc_ptr) % 2) {
1863 (BCC(smb_buffer_response)
1865 bcc_ptr++; /* Unicode strings must be word aligned */
1869 (smb_buffer_response) / 2;
1872 UniStrnlen((wchar_t *) bcc_ptr,
1873 remaining_words - 1);
1874 /* We look for obvious messed up bcc or strings in response so we do not go off
1875 the end since (at least) WIN2K and Windows XP have a major bug in not null
1876 terminating last Unicode string in response */
1878 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1879 cifs_strfromUCS_le(ses->serverOS,
1883 bcc_ptr += 2 * (len + 1);
1884 remaining_words -= len + 1;
1885 ses->serverOS[2 * len] = 0;
1886 ses->serverOS[1 + (2 * len)] = 0;
1887 if (remaining_words > 0) {
1888 len = UniStrnlen((wchar_t *)bcc_ptr,
1892 cifs_kcalloc(2 * (len + 1),
1894 cifs_strfromUCS_le(ses->serverNOS,
1898 bcc_ptr += 2 * (len + 1);
1899 ses->serverNOS[2 * len] = 0;
1900 ses->serverNOS[1 + (2 * len)] = 0;
1901 remaining_words -= len + 1;
1902 if (remaining_words > 0) {
1903 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1904 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1905 ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
1906 cifs_strfromUCS_le(ses->serverDomain,
1910 bcc_ptr += 2*(len+1);
1911 ses->serverDomain[2*len] = 0;
1912 ses->serverDomain[1+(2*len)] = 0;
1913 } /* else no more room so create dummy domain string */
1916 cifs_kcalloc(2,GFP_KERNEL);
1917 } else { /* no room so create dummy domain and NOS string */
1918 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
1919 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
1921 } else { /* ASCII */
1923 len = strnlen(bcc_ptr, 1024);
1924 if (((long) bcc_ptr + len) - (long)
1925 pByteArea(smb_buffer_response)
1926 <= BCC(smb_buffer_response)) {
1927 ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
1928 strncpy(ses->serverOS, bcc_ptr, len);
1931 bcc_ptr[0] = 0; /* null terminate the string */
1934 len = strnlen(bcc_ptr, 1024);
1935 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1936 strncpy(ses->serverNOS, bcc_ptr, len);
1941 len = strnlen(bcc_ptr, 1024);
1942 ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
1943 strncpy(ses->serverDomain, bcc_ptr, len);
1949 ("Variable field of length %d extends beyond end of smb ",
1954 (" Security Blob Length extends beyond end of SMB"));
1957 cERROR(1, ("No session structure passed in."));
1961 (" Invalid Word count %d: ",
1962 smb_buffer_response->WordCount));
1967 cifs_buf_release(smb_buffer);
1973 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
1974 struct cifsSesInfo *ses, int * pNTLMv2_flag,
1975 const struct nls_table *nls_codepage)
1977 struct smb_hdr *smb_buffer;
1978 struct smb_hdr *smb_buffer_response;
1979 SESSION_SETUP_ANDX *pSMB;
1980 SESSION_SETUP_ANDX *pSMBr;
1982 char *domain = ses->domainName;
1984 int remaining_words = 0;
1985 int bytes_returned = 0;
1987 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
1988 PNEGOTIATE_MESSAGE SecurityBlob;
1989 PCHALLENGE_MESSAGE SecurityBlob2;
1991 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
1992 *pNTLMv2_flag = FALSE;
1993 smb_buffer = cifs_buf_get();
1994 if (smb_buffer == 0) {
1997 smb_buffer_response = smb_buffer;
1998 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1999 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2001 /* send SMBsessionSetup here */
2002 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2003 NULL /* no tCon exists yet */ , 12 /* wct */ );
2004 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2005 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2007 pSMB->req.AndXCommand = 0xFF;
2008 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2009 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2011 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2012 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2014 pSMB->req.Capabilities =
2015 CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2016 CAP_EXTENDED_SECURITY;
2017 if (ses->capabilities & CAP_UNICODE) {
2018 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2019 pSMB->req.Capabilities |= CAP_UNICODE;
2021 if (ses->capabilities & CAP_STATUS32) {
2022 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2023 pSMB->req.Capabilities |= CAP_STATUS32;
2025 if (ses->capabilities & CAP_DFS) {
2026 smb_buffer->Flags2 |= SMBFLG2_DFS;
2027 pSMB->req.Capabilities |= CAP_DFS;
2029 pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
2031 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2032 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2033 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2034 SecurityBlob->MessageType = NtLmNegotiate;
2035 SecurityBlob->NegotiateFlags =
2036 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2037 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2038 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2040 SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN;
2042 SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
2043 /* setup pointers to domain name and workstation name */
2044 bcc_ptr += SecurityBlobLength;
2046 SecurityBlob->WorkstationName.Buffer = 0;
2047 SecurityBlob->WorkstationName.Length = 0;
2048 SecurityBlob->WorkstationName.MaximumLength = 0;
2050 if (domain == NULL) {
2051 SecurityBlob->DomainName.Buffer = 0;
2052 SecurityBlob->DomainName.Length = 0;
2053 SecurityBlob->DomainName.MaximumLength = 0;
2055 SecurityBlob->NegotiateFlags |=
2056 NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2057 strncpy(bcc_ptr, domain, 63);
2058 SecurityBlob->DomainName.Length = strnlen(domain, 64);
2059 SecurityBlob->DomainName.MaximumLength =
2060 cpu_to_le16(SecurityBlob->DomainName.Length);
2061 SecurityBlob->DomainName.Buffer =
2062 cpu_to_le32((long) &SecurityBlob->
2064 (long) &SecurityBlob->Signature);
2065 bcc_ptr += SecurityBlob->DomainName.Length;
2066 SecurityBlobLength += SecurityBlob->DomainName.Length;
2067 SecurityBlob->DomainName.Length =
2068 cpu_to_le16(SecurityBlob->DomainName.Length);
2070 if (ses->capabilities & CAP_UNICODE) {
2071 if ((long) bcc_ptr % 2) {
2077 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2079 bcc_ptr += 2 * bytes_returned;
2081 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
2083 bcc_ptr += 2 * bytes_returned;
2084 bcc_ptr += 2; /* null terminate Linux version */
2086 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2088 bcc_ptr += 2 * bytes_returned;
2091 bcc_ptr += 2; /* null terminate network opsys string */
2094 bcc_ptr += 2; /* null domain */
2095 } else { /* ASCII */
2096 strcpy(bcc_ptr, "Linux version ");
2097 bcc_ptr += strlen("Linux version ");
2098 strcpy(bcc_ptr, UTS_RELEASE);
2099 bcc_ptr += strlen(UTS_RELEASE) + 1;
2100 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2101 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2102 bcc_ptr++; /* empty domain field */
2105 SecurityBlob->NegotiateFlags =
2106 cpu_to_le32(SecurityBlob->NegotiateFlags);
2107 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2108 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2109 smb_buffer->smb_buf_length += BCC(smb_buffer);
2110 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
2112 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2113 &bytes_returned, 1);
2115 if (smb_buffer_response->Status.CifsError ==
2116 (NT_STATUS_MORE_PROCESSING_REQUIRED))
2120 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2121 } else if ((smb_buffer_response->WordCount == 3)
2122 || (smb_buffer_response->WordCount == 4)) {
2123 pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
2124 pSMBr->resp.SecurityBlobLength =
2125 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2126 if (pSMBr->resp.Action & GUEST_LOGIN)
2127 cFYI(1, (" Guest login"));
2128 /* Do we want to set anything in SesInfo struct when guest login? */
2130 bcc_ptr = pByteArea(smb_buffer_response);
2131 /* response can have either 3 or 4 word count - Samba sends 3 */
2133 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2134 if (SecurityBlob2->MessageType != NtLmChallenge) {
2136 ("Unexpected NTLMSSP message type received %d",
2137 SecurityBlob2->MessageType));
2139 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2140 cFYI(1, ("UID = %d ", ses->Suid));
2141 if ((pSMBr->resp.hdr.WordCount == 3)
2142 || ((pSMBr->resp.hdr.WordCount == 4)
2143 && (pSMBr->resp.SecurityBlobLength <
2144 pSMBr->resp.ByteCount))) {
2145 if (pSMBr->resp.hdr.WordCount == 4) {
2147 pSMBr->resp.SecurityBlobLength;
2149 ("Security Blob Length %d ",
2150 pSMBr->resp.SecurityBlobLength));
2153 cFYI(1, ("NTLMSSP Challenge rcvd "));
2155 memcpy(ses->server->cryptKey,
2156 SecurityBlob2->Challenge,
2157 CIFS_CRYPTO_KEY_SIZE);
2158 if(SecurityBlob2->NegotiateFlags & NTLMSSP_NEGOTIATE_NTLMV2)
2159 *pNTLMv2_flag = TRUE;
2161 if((SecurityBlob2->NegotiateFlags &
2162 NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
2163 || (sign_CIFS_PDUs > 1))
2164 ses->server->secMode |=
2165 SECMODE_SIGN_REQUIRED;
2166 if ((SecurityBlob2->NegotiateFlags &
2167 NTLMSSP_NEGOTIATE_SIGN) && (sign_CIFS_PDUs))
2168 ses->server->secMode |=
2169 SECMODE_SIGN_ENABLED;
2171 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2172 if ((long) (bcc_ptr) % 2) {
2174 (BCC(smb_buffer_response)
2176 bcc_ptr++; /* Unicode strings must be word aligned */
2180 (smb_buffer_response) / 2;
2183 UniStrnlen((wchar_t *) bcc_ptr,
2184 remaining_words - 1);
2185 /* We look for obvious messed up bcc or strings in response so we do not go off
2186 the end since (at least) WIN2K and Windows XP have a major bug in not null
2187 terminating last Unicode string in response */
2189 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2190 cifs_strfromUCS_le(ses->serverOS,
2194 bcc_ptr += 2 * (len + 1);
2195 remaining_words -= len + 1;
2196 ses->serverOS[2 * len] = 0;
2197 ses->serverOS[1 + (2 * len)] = 0;
2198 if (remaining_words > 0) {
2199 len = UniStrnlen((wchar_t *)
2204 cifs_kcalloc(2 * (len + 1),
2206 cifs_strfromUCS_le(ses->
2212 bcc_ptr += 2 * (len + 1);
2213 ses->serverNOS[2 * len] = 0;
2216 remaining_words -= len + 1;
2217 if (remaining_words > 0) {
2218 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2219 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2244 } /* else no more room so create dummy domain string */
2249 } else { /* no room so create dummy domain and NOS string */
2251 cifs_kcalloc(2, GFP_KERNEL);
2253 cifs_kcalloc(2, GFP_KERNEL);
2255 } else { /* ASCII */
2256 len = strnlen(bcc_ptr, 1024);
2257 if (((long) bcc_ptr + len) - (long)
2258 pByteArea(smb_buffer_response)
2259 <= BCC(smb_buffer_response)) {
2261 cifs_kcalloc(len + 1,
2263 strncpy(ses->serverOS,
2267 bcc_ptr[0] = 0; /* null terminate string */
2270 len = strnlen(bcc_ptr, 1024);
2272 cifs_kcalloc(len + 1,
2274 strncpy(ses->serverNOS, bcc_ptr, len);
2279 len = strnlen(bcc_ptr, 1024);
2281 cifs_kcalloc(len + 1,
2283 strncpy(ses->serverDomain, bcc_ptr, len);
2289 ("Variable field of length %d extends beyond end of smb ",
2294 (" Security Blob Length extends beyond end of SMB"));
2297 cERROR(1, ("No session structure passed in."));
2301 (" Invalid Word count %d: ",
2302 smb_buffer_response->WordCount));
2307 cifs_buf_release(smb_buffer);
2313 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2314 char *ntlm_session_key, int ntlmv2_flag,
2315 const struct nls_table *nls_codepage)
2317 struct smb_hdr *smb_buffer;
2318 struct smb_hdr *smb_buffer_response;
2319 SESSION_SETUP_ANDX *pSMB;
2320 SESSION_SETUP_ANDX *pSMBr;
2322 char *user = ses->userName;
2323 char *domain = ses->domainName;
2325 int remaining_words = 0;
2326 int bytes_returned = 0;
2328 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2329 PAUTHENTICATE_MESSAGE SecurityBlob;
2331 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2333 smb_buffer = cifs_buf_get();
2334 if (smb_buffer == 0) {
2337 smb_buffer_response = smb_buffer;
2338 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2339 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2341 /* send SMBsessionSetup here */
2342 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2343 NULL /* no tCon exists yet */ , 12 /* wct */ );
2344 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2345 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2346 pSMB->req.AndXCommand = 0xFF;
2347 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2348 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2350 pSMB->req.hdr.Uid = ses->Suid;
2352 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2353 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2355 pSMB->req.Capabilities =
2356 CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2357 CAP_EXTENDED_SECURITY;
2358 if (ses->capabilities & CAP_UNICODE) {
2359 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2360 pSMB->req.Capabilities |= CAP_UNICODE;
2362 if (ses->capabilities & CAP_STATUS32) {
2363 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2364 pSMB->req.Capabilities |= CAP_STATUS32;
2366 if (ses->capabilities & CAP_DFS) {
2367 smb_buffer->Flags2 |= SMBFLG2_DFS;
2368 pSMB->req.Capabilities |= CAP_DFS;
2370 pSMB->req.Capabilities = cpu_to_le32(pSMB->req.Capabilities);
2372 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2373 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2374 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2375 SecurityBlob->MessageType = NtLmAuthenticate;
2376 bcc_ptr += SecurityBlobLength;
2377 SecurityBlob->NegotiateFlags =
2378 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2379 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2380 0x80000000 | NTLMSSP_NEGOTIATE_128;
2382 SecurityBlob->NegotiateFlags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2384 SecurityBlob->NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLMV2;
2386 /* setup pointers to domain name and workstation name */
2388 SecurityBlob->WorkstationName.Buffer = 0;
2389 SecurityBlob->WorkstationName.Length = 0;
2390 SecurityBlob->WorkstationName.MaximumLength = 0;
2391 SecurityBlob->SessionKey.Length = 0;
2392 SecurityBlob->SessionKey.MaximumLength = 0;
2393 SecurityBlob->SessionKey.Buffer = 0;
2395 SecurityBlob->LmChallengeResponse.Length = 0;
2396 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2397 SecurityBlob->LmChallengeResponse.Buffer = 0;
2399 SecurityBlob->NtChallengeResponse.Length =
2400 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2401 SecurityBlob->NtChallengeResponse.MaximumLength =
2402 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2403 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2404 SecurityBlob->NtChallengeResponse.Buffer =
2405 cpu_to_le32(SecurityBlobLength);
2406 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2407 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2409 if (ses->capabilities & CAP_UNICODE) {
2410 if (domain == NULL) {
2411 SecurityBlob->DomainName.Buffer = 0;
2412 SecurityBlob->DomainName.Length = 0;
2413 SecurityBlob->DomainName.MaximumLength = 0;
2415 SecurityBlob->DomainName.Length =
2416 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2418 SecurityBlob->DomainName.Length *= 2;
2419 SecurityBlob->DomainName.MaximumLength =
2420 cpu_to_le16(SecurityBlob->DomainName.Length);
2421 SecurityBlob->DomainName.Buffer =
2422 cpu_to_le32(SecurityBlobLength);
2423 bcc_ptr += SecurityBlob->DomainName.Length;
2424 SecurityBlobLength += SecurityBlob->DomainName.Length;
2425 SecurityBlob->DomainName.Length =
2426 cpu_to_le16(SecurityBlob->DomainName.Length);
2429 SecurityBlob->UserName.Buffer = 0;
2430 SecurityBlob->UserName.Length = 0;
2431 SecurityBlob->UserName.MaximumLength = 0;
2433 SecurityBlob->UserName.Length =
2434 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2436 SecurityBlob->UserName.Length *= 2;
2437 SecurityBlob->UserName.MaximumLength =
2438 cpu_to_le16(SecurityBlob->UserName.Length);
2439 SecurityBlob->UserName.Buffer =
2440 cpu_to_le32(SecurityBlobLength);
2441 bcc_ptr += SecurityBlob->UserName.Length;
2442 SecurityBlobLength += SecurityBlob->UserName.Length;
2443 SecurityBlob->UserName.Length =
2444 cpu_to_le16(SecurityBlob->UserName.Length);
2447 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2448 SecurityBlob->WorkstationName.Length *= 2;
2449 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2450 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2451 bcc_ptr += SecurityBlob->WorkstationName.Length;
2452 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2453 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2455 if ((long) bcc_ptr % 2) {
2460 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2462 bcc_ptr += 2 * bytes_returned;
2464 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
2466 bcc_ptr += 2 * bytes_returned;
2467 bcc_ptr += 2; /* null term version string */
2469 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2471 bcc_ptr += 2 * bytes_returned;
2474 bcc_ptr += 2; /* null terminate network opsys string */
2477 bcc_ptr += 2; /* null domain */
2478 } else { /* ASCII */
2479 if (domain == NULL) {
2480 SecurityBlob->DomainName.Buffer = 0;
2481 SecurityBlob->DomainName.Length = 0;
2482 SecurityBlob->DomainName.MaximumLength = 0;
2484 SecurityBlob->NegotiateFlags |=
2485 NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2486 strncpy(bcc_ptr, domain, 63);
2487 SecurityBlob->DomainName.Length = strnlen(domain, 64);
2488 SecurityBlob->DomainName.MaximumLength =
2489 cpu_to_le16(SecurityBlob->DomainName.Length);
2490 SecurityBlob->DomainName.Buffer =
2491 cpu_to_le32(SecurityBlobLength);
2492 bcc_ptr += SecurityBlob->DomainName.Length;
2493 SecurityBlobLength += SecurityBlob->DomainName.Length;
2494 SecurityBlob->DomainName.Length =
2495 cpu_to_le16(SecurityBlob->DomainName.Length);
2498 SecurityBlob->UserName.Buffer = 0;
2499 SecurityBlob->UserName.Length = 0;
2500 SecurityBlob->UserName.MaximumLength = 0;
2502 strncpy(bcc_ptr, user, 63);
2503 SecurityBlob->UserName.Length = strnlen(user, 64);
2504 SecurityBlob->UserName.MaximumLength =
2505 cpu_to_le16(SecurityBlob->UserName.Length);
2506 SecurityBlob->UserName.Buffer =
2507 cpu_to_le32(SecurityBlobLength);
2508 bcc_ptr += SecurityBlob->UserName.Length;
2509 SecurityBlobLength += SecurityBlob->UserName.Length;
2510 SecurityBlob->UserName.Length =
2511 cpu_to_le16(SecurityBlob->UserName.Length);
2513 /* BB fill in our workstation name if known BB */
2515 strcpy(bcc_ptr, "Linux version ");
2516 bcc_ptr += strlen("Linux version ");
2517 strcpy(bcc_ptr, UTS_RELEASE);
2518 bcc_ptr += strlen(UTS_RELEASE) + 1;
2519 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2520 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2521 bcc_ptr++; /* null domain */
2524 SecurityBlob->NegotiateFlags =
2525 cpu_to_le32(SecurityBlob->NegotiateFlags);
2526 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2527 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2528 smb_buffer->smb_buf_length += BCC(smb_buffer);
2529 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
2531 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2532 &bytes_returned, 1);
2534 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2535 } else if ((smb_buffer_response->WordCount == 3)
2536 || (smb_buffer_response->WordCount == 4)) {
2537 pSMBr->resp.Action = le16_to_cpu(pSMBr->resp.Action);
2538 pSMBr->resp.SecurityBlobLength =
2539 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2540 if (pSMBr->resp.Action & GUEST_LOGIN)
2541 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2542 /* if(SecurityBlob2->MessageType != NtLm??){
2543 cFYI("Unexpected message type on auth response is %d "));
2547 ("Does UID on challenge %d match auth response UID %d ",
2548 ses->Suid, smb_buffer_response->Uid));
2549 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2550 bcc_ptr = pByteArea(smb_buffer_response);
2551 /* response can have either 3 or 4 word count - Samba sends 3 */
2552 if ((pSMBr->resp.hdr.WordCount == 3)
2553 || ((pSMBr->resp.hdr.WordCount == 4)
2554 && (pSMBr->resp.SecurityBlobLength <
2555 pSMBr->resp.ByteCount))) {
2556 if (pSMBr->resp.hdr.WordCount == 4) {
2558 pSMBr->resp.SecurityBlobLength;
2560 ("Security Blob Length %d ",
2561 pSMBr->resp.SecurityBlobLength));
2565 ("NTLMSSP response to Authenticate "));
2567 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2568 if ((long) (bcc_ptr) % 2) {
2570 (BCC(smb_buffer_response)
2572 bcc_ptr++; /* Unicode strings must be word aligned */
2574 remaining_words = BCC(smb_buffer_response) / 2;
2577 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2578 /* We look for obvious messed up bcc or strings in response so we do not go off
2579 the end since (at least) WIN2K and Windows XP have a major bug in not null
2580 terminating last Unicode string in response */
2582 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2583 cifs_strfromUCS_le(ses->serverOS,
2587 bcc_ptr += 2 * (len + 1);
2588 remaining_words -= len + 1;
2589 ses->serverOS[2 * len] = 0;
2590 ses->serverOS[1 + (2 * len)] = 0;
2591 if (remaining_words > 0) {
2592 len = UniStrnlen((wchar_t *)
2597 cifs_kcalloc(2 * (len + 1),
2599 cifs_strfromUCS_le(ses->
2605 bcc_ptr += 2 * (len + 1);
2606 ses->serverNOS[2 * len] = 0;
2607 ses->serverNOS[1+(2*len)] = 0;
2608 remaining_words -= len + 1;
2609 if (remaining_words > 0) {
2610 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2611 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2636 } /* else no more room so create dummy domain string */
2638 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
2639 } else { /* no room so create dummy domain and NOS string */
2640 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2641 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2643 } else { /* ASCII */
2644 len = strnlen(bcc_ptr, 1024);
2645 if (((long) bcc_ptr + len) -
2646 (long) pByteArea(smb_buffer_response)
2647 <= BCC(smb_buffer_response)) {
2648 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2649 strncpy(ses->serverOS,bcc_ptr, len);
2652 bcc_ptr[0] = 0; /* null terminate the string */
2655 len = strnlen(bcc_ptr, 1024);
2656 ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
2657 strncpy(ses->serverNOS, bcc_ptr, len);
2662 len = strnlen(bcc_ptr, 1024);
2663 ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
2664 strncpy(ses->serverDomain, bcc_ptr, len);
2670 ("Variable field of length %d extends beyond end of smb ",
2675 (" Security Blob Length extends beyond end of SMB"));
2678 cERROR(1, ("No session structure passed in."));
2682 (" Invalid Word count %d: ",
2683 smb_buffer_response->WordCount));
2688 cifs_buf_release(smb_buffer);
2694 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2695 const char *tree, struct cifsTconInfo *tcon,
2696 const struct nls_table *nls_codepage)
2698 struct smb_hdr *smb_buffer;
2699 struct smb_hdr *smb_buffer_response;
2709 smb_buffer = cifs_buf_get();
2710 if (smb_buffer == 0) {
2713 smb_buffer_response = smb_buffer;
2715 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2716 NULL /*no tid */ , 4 /*wct */ );
2717 smb_buffer->Uid = ses->Suid;
2718 pSMB = (TCONX_REQ *) smb_buffer;
2719 pSMBr = (TCONX_RSP *) smb_buffer_response;
2721 pSMB->AndXCommand = 0xFF;
2722 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2723 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2724 bcc_ptr = &(pSMB->Password[0]);
2725 bcc_ptr++; /* skip password */
2727 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2728 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2730 if (ses->capabilities & CAP_STATUS32) {
2731 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2733 if (ses->capabilities & CAP_DFS) {
2734 smb_buffer->Flags2 |= SMBFLG2_DFS;
2736 if (ses->capabilities & CAP_UNICODE) {
2737 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2739 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2740 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2741 bcc_ptr += 2; /* skip trailing null */
2742 } else { /* ASCII */
2744 strcpy(bcc_ptr, tree);
2745 bcc_ptr += strlen(tree) + 1;
2747 strcpy(bcc_ptr, "?????");
2748 bcc_ptr += strlen("?????");
2750 BCC(smb_buffer) = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2751 smb_buffer->smb_buf_length += BCC(smb_buffer);
2752 BCC(smb_buffer) = cpu_to_le16(BCC(smb_buffer));
2754 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2756 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2757 /* above now done in SendReceive */
2758 if ((rc == 0) && (tcon != NULL)) {
2759 tcon->tidStatus = CifsGood;
2760 tcon->tid = smb_buffer_response->Tid;
2761 bcc_ptr = pByteArea(smb_buffer_response);
2762 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2763 /* skip service field (NB: this field is always ASCII) */
2764 bcc_ptr += length + 1;
2765 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2766 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2767 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2768 if (((long) bcc_ptr + (2 * length)) -
2769 (long) pByteArea(smb_buffer_response) <=
2770 BCC(smb_buffer_response)) {
2771 if(tcon->nativeFileSystem)
2772 kfree(tcon->nativeFileSystem);
2773 tcon->nativeFileSystem =
2774 cifs_kcalloc(length + 2, GFP_KERNEL);
2775 cifs_strfromUCS_le(tcon->nativeFileSystem,
2776 (wchar_t *) bcc_ptr,
2777 length, nls_codepage);
2778 bcc_ptr += 2 * length;
2779 bcc_ptr[0] = 0; /* null terminate the string */
2783 /* else do not bother copying these informational fields */
2785 length = strnlen(bcc_ptr, 1024);
2786 if (((long) bcc_ptr + length) -
2787 (long) pByteArea(smb_buffer_response) <=
2788 BCC(smb_buffer_response)) {
2789 if(tcon->nativeFileSystem)
2790 kfree(tcon->nativeFileSystem);
2791 tcon->nativeFileSystem =
2792 cifs_kcalloc(length + 1, GFP_KERNEL);
2793 strncpy(tcon->nativeFileSystem, bcc_ptr,
2796 /* else do not bother copying these informational fields */
2798 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2799 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2800 } else if ((rc == 0) && tcon == NULL) {
2801 /* all we need to save for IPC$ connection */
2802 ses->ipc_tid = smb_buffer_response->Tid;
2806 cifs_buf_release(smb_buffer);
2811 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
2815 struct cifsSesInfo *ses = NULL;
2816 struct task_struct *cifsd_task;
2820 if (cifs_sb->tcon) {
2821 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
2822 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
2827 tconInfoFree(cifs_sb->tcon);
2828 if ((ses) && (ses->server)) {
2829 /* save off task so we do not refer to ses later */
2830 cifsd_task = ses->server->tsk;
2831 cFYI(1, ("About to do SMBLogoff "));
2832 rc = CIFSSMBLogoff(xid, ses);
2836 } else if (rc == -ESHUTDOWN) {
2837 cFYI(1,("Waking up socket by sending it signal"));
2838 send_sig(SIGKILL,cifsd_task,1);
2840 } /* else - we have an smb session
2841 left on this socket do not kill cifsd */
2843 cFYI(1, ("No session or bad tcon"));
2846 cifs_sb->tcon = NULL;
2848 set_current_state(TASK_INTERRUPTIBLE);
2849 schedule_timeout(HZ / 2);
2855 return rc; /* BB check if we should always return zero here */
2858 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2859 struct nls_table * nls_info)
2862 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
2863 int ntlmv2_flag = FALSE;
2865 /* what if server changes its buffer size after dropping the session? */
2866 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
2867 rc = CIFSSMBNegotiate(xid, pSesInfo);
2868 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
2869 rc = CIFSSMBNegotiate(xid, pSesInfo);
2874 spin_lock(&GlobalMid_Lock);
2875 if(pSesInfo->server->tcpStatus != CifsExiting)
2876 pSesInfo->server->tcpStatus = CifsGood;
2879 spin_unlock(&GlobalMid_Lock);
2884 pSesInfo->capabilities = pSesInfo->server->capabilities;
2885 if(linuxExtEnabled == 0)
2886 pSesInfo->capabilities &= (~CAP_UNIX);
2887 pSesInfo->sequence_number = 0;
2888 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2889 pSesInfo->server->secMode,
2890 pSesInfo->server->capabilities,
2891 pSesInfo->server->timeZone));
2892 if (extended_security
2893 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
2894 && (pSesInfo->server->secType == NTLMSSP)) {
2895 cFYI(1, ("New style sesssetup "));
2896 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
2897 NULL /* security blob */,
2898 0 /* blob length */,
2900 } else if (extended_security
2901 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
2902 && (pSesInfo->server->secType == RawNTLMSSP)) {
2903 cFYI(1, ("NTLMSSP sesssetup "));
2904 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
2911 cFYI(1,("Can use more secure NTLM version 2 password hash"));
2912 CalcNTLMv2_partial_mac_key(pSesInfo,
2914 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
2916 CalcNTLMv2_response(pSesInfo,v2_response);
2917 /* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
2919 /* BB Put dummy sig in SessSetup PDU? */
2924 SMBNTencrypt(pSesInfo->password,
2925 pSesInfo->server->cryptKey,
2928 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
2930 pSesInfo->password);
2932 /* for better security the weaker lanman hash not sent
2933 in AuthSessSetup so we no longer calculate it */
2935 rc = CIFSNTLMSSPAuthSessSetup(xid,
2941 } else { /* old style NTLM 0.12 session setup */
2942 SMBNTencrypt(pSesInfo->password,
2943 pSesInfo->server->cryptKey,
2946 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
2947 ntlm_session_key, pSesInfo->password);
2948 rc = CIFSSessSetup(xid, pSesInfo,
2949 ntlm_session_key, nls_info);
2952 cERROR(1,("Send error in SessSetup = %d",rc));
2954 cFYI(1,("CIFS Session Established successfully"));
2955 pSesInfo->status = CifsGood;