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/ipv6.h>
27 #include <linux/pagemap.h>
28 #include <linux/ctype.h>
29 #include <linux/utsname.h>
30 #include <linux/mempool.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);
52 extern mempool_t *cifs_req_poolp;
60 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
61 char *iocharset; /* local code page for mapping to and from Unicode */
62 char source_rfc1001_name[16]; /* netbios name of client */
72 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
73 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
78 unsigned short int port;
81 static int ipv4_connect(struct sockaddr_in *psin_server,
82 struct socket **csocket,
84 static int ipv6_connect(struct sockaddr_in6 *psin_server,
85 struct socket **csocket);
89 * cifs tcp session reconnection
91 * mark tcp session as reconnecting so temporarily locked
92 * mark all smb sessions as reconnecting for tcp session
93 * reconnect tcp session
94 * wake up waiters on reconnection? - (not needed currently)
98 cifs_reconnect(struct TCP_Server_Info *server)
101 struct list_head *tmp;
102 struct cifsSesInfo *ses;
103 struct cifsTconInfo *tcon;
104 struct mid_q_entry * mid_entry;
106 spin_lock(&GlobalMid_Lock);
107 if(server->tcpStatus == CifsExiting) {
108 /* the demux thread will exit normally
109 next time through the loop */
110 spin_unlock(&GlobalMid_Lock);
113 server->tcpStatus = CifsNeedReconnect;
114 spin_unlock(&GlobalMid_Lock);
117 cFYI(1, ("Reconnecting tcp session "));
119 /* before reconnecting the tcp session, mark the smb session (uid)
120 and the tid bad so they are not used until reconnected */
121 read_lock(&GlobalSMBSeslock);
122 list_for_each(tmp, &GlobalSMBSessionList) {
123 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
125 if (ses->server == server) {
126 ses->status = CifsNeedReconnect;
130 /* else tcp and smb sessions need reconnection */
132 list_for_each(tmp, &GlobalTreeConnectionList) {
133 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
134 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
135 tcon->tidStatus = CifsNeedReconnect;
138 read_unlock(&GlobalSMBSeslock);
139 /* do not want to be sending data on a socket we are freeing */
140 down(&server->tcpSem);
141 if(server->ssocket) {
142 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
143 server->ssocket->flags));
144 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
145 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
146 server->ssocket->flags));
147 sock_release(server->ssocket);
148 server->ssocket = NULL;
151 spin_lock(&GlobalMid_Lock);
152 list_for_each(tmp, &server->pending_mid_q) {
153 mid_entry = list_entry(tmp, struct
157 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
158 /* Mark other intransit requests as needing retry so
159 we do not immediately mark the session bad again
160 (ie after we reconnect below) as they timeout too */
161 mid_entry->midState = MID_RETRY_NEEDED;
165 spin_unlock(&GlobalMid_Lock);
168 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
170 if(server->protocolType == IPV6) {
171 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
173 rc = ipv4_connect(&server->addr.sockAddr,
175 server->workstation_RFC1001_name);
178 set_current_state(TASK_INTERRUPTIBLE);
179 schedule_timeout(3 * HZ);
181 atomic_inc(&tcpSesReconnectCount);
182 spin_lock(&GlobalMid_Lock);
183 if(server->tcpStatus != CifsExiting)
184 server->tcpStatus = CifsGood;
185 spin_unlock(&GlobalMid_Lock);
186 /* atomic_set(&server->inFlight,0);*/
187 wake_up(&server->response_q);
194 cifs_demultiplex_thread(struct TCP_Server_Info *server)
197 unsigned int pdu_length, total_read;
198 struct smb_hdr *smb_buffer = NULL;
199 struct msghdr smb_msg;
201 struct socket *csocket = server->ssocket;
202 struct list_head *tmp;
203 struct cifsSesInfo *ses;
204 struct task_struct *task_to_wake = NULL;
205 struct mid_q_entry *mid_entry;
209 allow_signal(SIGKILL);
210 current->flags |= PF_MEMALLOC;
211 server->tsk = current; /* save process info to wake at shutdown */
212 cFYI(1, ("Demultiplex PID: %d", current->pid));
213 write_lock(&GlobalSMBSeslock);
214 atomic_inc(&tcpSesAllocCount);
215 length = tcpSesAllocCount.counter;
216 write_unlock(&GlobalSMBSeslock);
218 mempool_resize(cifs_req_poolp,
219 length + cifs_min_rcv,
223 while (server->tcpStatus != CifsExiting) {
224 if (smb_buffer == NULL)
225 smb_buffer = cifs_buf_get();
227 memset(smb_buffer, 0, sizeof (struct smb_hdr));
229 if (smb_buffer == NULL) {
230 cERROR(1,("Can not get memory for SMB response"));
231 set_current_state(TASK_INTERRUPTIBLE);
232 schedule_timeout(HZ * 3); /* give system time to free memory */
235 iov.iov_base = smb_buffer;
236 iov.iov_len = sizeof (struct smb_hdr) - 1;
237 /* 1 byte less above since wct is not always returned in error cases */
238 smb_msg.msg_control = NULL;
239 smb_msg.msg_controllen = 0;
242 kernel_recvmsg(csocket, &smb_msg,
244 sizeof (struct smb_hdr) -
245 1 /* RFC1001 header and SMB header */ ,
246 MSG_PEEK /* flags see socket.h */ );
248 if(server->tcpStatus == CifsExiting) {
250 } else if (server->tcpStatus == CifsNeedReconnect) {
251 cFYI(1,("Reconnecting after server stopped responding"));
252 cifs_reconnect(server);
253 cFYI(1,("call to reconnect done"));
254 csocket = server->ssocket;
256 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)
257 || ((length > 0) && (length <= 3)) ) {
258 set_current_state(TASK_INTERRUPTIBLE);
259 schedule_timeout(1); /* minimum sleep to prevent looping
260 allowing socket to clear and app threads to set
261 tcpStatus CifsNeedReconnect if server hung */
263 } else if (length <= 0) {
264 if(server->tcpStatus == CifsNew) {
265 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
266 /* some servers kill tcp session rather than returning
267 smb negprot error in which case reconnecting here is
268 not going to help - return error to mount */
271 if(length == -EINTR) {
272 cFYI(1,("cifsd thread killed"));
275 cFYI(1,("Reconnecting after unexpected peek error %d",length));
276 cifs_reconnect(server);
277 csocket = server->ssocket;
278 wake_up(&server->response_q);
282 pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
283 /* Only read pdu_length after below checks for too short (due
284 to e.g. int overflow) and too long ie beyond end of buf */
285 cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
287 temp = (char *) smb_buffer;
289 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
290 iov.iov_base = smb_buffer;
292 length = kernel_recvmsg(csocket, &smb_msg,
294 cFYI(0,("Received 4 byte keep alive packet"));
295 } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
296 iov.iov_base = smb_buffer;
298 length = kernel_recvmsg(csocket, &smb_msg,
300 cFYI(1,("Good RFC 1002 session rsp"));
301 } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
303 /* we get this from Windows 98 instead of error on SMB negprot response */
304 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
305 if(server->tcpStatus == CifsNew) {
306 /* if nack on negprot (rather than
307 ret of smb negprot error) reconnecting
308 not going to help, ret error to mount */
311 /* give server a second to
312 clean up before reconnect attempt */
313 set_current_state(TASK_INTERRUPTIBLE);
314 schedule_timeout(HZ);
315 /* always try 445 first on reconnect
316 since we get NACK on some if we ever
317 connected to port 139 (the NACK is
318 since we do not begin with RFC1001
319 session initialize frame) */
320 server->addr.sockAddr.sin_port = htons(CIFS_PORT);
321 cifs_reconnect(server);
322 csocket = server->ssocket;
323 wake_up(&server->response_q);
326 } else if (temp[0] != (char) 0) {
327 cERROR(1,("Unknown RFC 1002 frame"));
328 cifs_dump_mem(" Received Data: ", temp, length);
329 cifs_reconnect(server);
330 csocket = server->ssocket;
334 /* We can not validate the SMB unless
335 at least this much of SMB available
336 so give the socket time to copy
337 a few more bytes and retry */
338 set_current_state(TASK_INTERRUPTIBLE);
339 schedule_timeout(10);
341 } else if( (pdu_length >
342 CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
344 sizeof (struct smb_hdr) - 1)
346 (smb_buffer, smb_buffer->Mid))) {
348 ("Invalid size or format for SMB found with length %d and pdu_length %d",
349 length, pdu_length));
350 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)+3);
351 /* could we fix this network corruption by finding next
352 smb header (instead of killing the session) and
353 restart reading from next valid SMB found? */
354 cifs_reconnect(server);
355 csocket = server->ssocket;
357 } else { /* length ok */
360 iov.iov_base = smb_buffer;
361 iov.iov_len = pdu_length;
363 total_read < pdu_length;
364 total_read += length) {
365 length = kernel_recvmsg(csocket, &smb_msg,
367 pdu_length - total_read, 0);
370 ("Zero length receive when expecting %d ",
371 pdu_length - total_read));
372 cifs_reconnect(server);
373 csocket = server->ssocket;
379 dump_smb(smb_buffer, length);
381 (smb_buffer, smb_buffer->Mid, total_read)) {
382 cERROR(1, ("Bad SMB Received "));
387 spin_lock(&GlobalMid_Lock);
388 list_for_each(tmp, &server->pending_mid_q) {
389 mid_entry = list_entry(tmp, struct
393 if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
395 (" Mid 0x%x matched - waking up ",mid_entry->mid));
396 task_to_wake = mid_entry->tsk;
397 mid_entry->resp_buf =
399 mid_entry->midState =
400 MID_RESPONSE_RECEIVED;
403 spin_unlock(&GlobalMid_Lock);
405 smb_buffer = NULL; /* will be freed by users thread after he is done */
406 wake_up_process(task_to_wake);
407 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
408 cERROR(1, ("No task to wake, unknown frame rcvd!"));
409 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
414 ("Frame less than four bytes received %d bytes long.",
417 length = kernel_recvmsg(csocket, &smb_msg,
419 length, 0); /* throw away junk frame */
421 (" with junk 0x%x in it ",
422 *(__u32 *) smb_buffer));
426 spin_lock(&GlobalMid_Lock);
427 server->tcpStatus = CifsExiting;
429 atomic_set(&server->inFlight, 0);
430 spin_unlock(&GlobalMid_Lock);
431 /* Although there should not be any requests blocked on
432 this queue it can not hurt to be paranoid and try to wake up requests
433 that may haven been blocked when more than 50 at time were on the wire
434 to the same server - they now will see the session is in exit state
435 and get out of SendReceive. */
436 wake_up_all(&server->request_q);
437 /* give those requests time to exit */
438 set_current_state(TASK_INTERRUPTIBLE);
439 schedule_timeout(HZ/8);
441 if(server->ssocket) {
442 sock_release(csocket);
443 server->ssocket = NULL;
445 if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
446 cifs_buf_release(smb_buffer);
448 read_lock(&GlobalSMBSeslock);
449 if (list_empty(&server->pending_mid_q)) {
450 /* loop through server session structures attached to this and mark them dead */
451 list_for_each(tmp, &GlobalSMBSessionList) {
453 list_entry(tmp, struct cifsSesInfo,
455 if (ses->server == server) {
456 ses->status = CifsExiting;
460 read_unlock(&GlobalSMBSeslock);
462 spin_lock(&GlobalMid_Lock);
463 list_for_each(tmp, &server->pending_mid_q) {
464 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
465 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
467 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
468 task_to_wake = mid_entry->tsk;
470 wake_up_process(task_to_wake);
474 spin_unlock(&GlobalMid_Lock);
475 read_unlock(&GlobalSMBSeslock);
476 set_current_state(TASK_INTERRUPTIBLE);
477 /* 1/8th of sec is more than enough time for them to exit */
478 schedule_timeout(HZ/8);
481 if (list_empty(&server->pending_mid_q)) {
482 /* mpx threads have not exited yet give them
483 at least the smb send timeout time for long ops */
484 cFYI(1, ("Wait for exit from demultiplex thread"));
485 set_current_state(TASK_INTERRUPTIBLE);
486 schedule_timeout(46 * HZ);
487 /* if threads still have not exited they are probably never
488 coming home not much else we can do but free the memory */
492 write_lock(&GlobalSMBSeslock);
493 atomic_dec(&tcpSesAllocCount);
494 length = tcpSesAllocCount.counter;
495 write_unlock(&GlobalSMBSeslock);
497 mempool_resize(cifs_req_poolp,
498 length + cifs_min_rcv,
502 set_current_state(TASK_INTERRUPTIBLE);
503 schedule_timeout(HZ/4);
508 cifs_kcalloc(size_t size, int type)
511 addr = kmalloc(size, type);
513 memset(addr, 0, size);
518 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
522 unsigned int temp_len, i, j;
528 memset(vol->source_rfc1001_name,0x20,15);
529 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
530 /* does not have to be a perfect mapping since the field is
531 informational, only used for servers that do not support
532 port 445 and it can be overridden at mount time */
533 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
535 vol->source_rfc1001_name[15] = 0;
537 vol->linux_uid = current->uid; /* current->euid instead? */
538 vol->linux_gid = current->gid;
539 vol->dir_mode = S_IRWXUGO;
540 /* 2767 perms indicate mandatory locking support */
541 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
543 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
549 if(strncmp(options,"sep=",4) == 0) {
550 if(options[4] != 0) {
551 separator[0] = options[4];
554 cFYI(1,("Null separator not allowed"));
558 while ((data = strsep(&options, separator)) != NULL) {
561 if ((value = strchr(data, '=')) != NULL)
563 if (strnicmp(data, "user", 4) == 0) {
564 if (!value || !*value) {
566 "CIFS: invalid or missing username\n");
567 return 1; /* needs_arg; */
569 if (strnlen(value, 200) < 200) {
570 vol->username = value;
572 printk(KERN_WARNING "CIFS: username too long\n");
575 } else if (strnicmp(data, "pass", 4) == 0) {
576 if (!value || !*value) {
577 vol->password = NULL;
580 temp_len = strlen(value);
581 /* removed password length check, NTLM passwords
582 can be arbitrarily long */
584 /* if comma in password, the string will be
585 prematurely null terminated. Commas in password are
586 specified across the cifs mount interface by a double
587 comma ie ,, and a comma used as in other cases ie ','
588 as a parameter delimiter/separator is single and due
589 to the strsep above is temporarily zeroed. */
591 /* NB: password legally can have multiple commas and
592 the only illegal character in a password is null */
594 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
596 value[temp_len] = separator[0];
597 temp_len+=2; /* move after the second comma */
598 while(value[temp_len] != 0) {
599 if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
600 /* single comma indicating start of next parm */
605 if(value[temp_len] == 0) {
609 /* move options to point to start of next parm */
610 options = value + temp_len + 1;
612 /* go from value to (value + temp_len) condensing double commas to singles */
613 vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
614 for(i=0,j=0;i<temp_len;i++,j++) {
615 vol->password[j] = value[i];
616 if(value[i] == separator[0] && value[i+1] == separator[0]) {
617 /* skip second comma */
621 /* value[temp_len] is zeroed above so
622 vol->password[temp_len] guaranteed to be null */
624 vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
625 strcpy(vol->password, value);
627 } else if (strnicmp(data, "ip", 2) == 0) {
628 if (!value || !*value) {
630 } else if (strnlen(value, 35) < 35) {
633 printk(KERN_WARNING "CIFS: ip address too long\n");
636 } else if ((strnicmp(data, "unc", 3) == 0)
637 || (strnicmp(data, "target", 6) == 0)
638 || (strnicmp(data, "path", 4) == 0)) {
639 if (!value || !*value) {
641 "CIFS: invalid path to network resource\n");
642 return 1; /* needs_arg; */
644 if ((temp_len = strnlen(value, 300)) < 300) {
645 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
648 strcpy(vol->UNC,value);
649 if (strncmp(vol->UNC, "//", 2) == 0) {
652 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
654 "CIFS: UNC Path does not begin with // or \\\\ \n");
658 printk(KERN_WARNING "CIFS: UNC name too long\n");
661 } else if ((strnicmp(data, "domain", 3) == 0)
662 || (strnicmp(data, "workgroup", 5) == 0)) {
663 if (!value || !*value) {
664 printk(KERN_WARNING "CIFS: invalid domain name\n");
665 return 1; /* needs_arg; */
667 /* BB are there cases in which a comma can be valid in
668 a domain name and need special handling? */
669 if (strnlen(value, 65) < 65) {
670 vol->domainname = value;
671 cFYI(1, ("Domain name set"));
673 printk(KERN_WARNING "CIFS: domain name too long\n");
676 } else if (strnicmp(data, "iocharset", 9) == 0) {
677 if (!value || !*value) {
678 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
679 return 1; /* needs_arg; */
681 if (strnlen(value, 65) < 65) {
682 if(strnicmp(value,"default",7))
683 vol->iocharset = value;
684 /* if iocharset not set load_nls_default used by caller */
685 cFYI(1, ("iocharset set to %s",value));
687 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
690 } else if (strnicmp(data, "uid", 3) == 0) {
691 if (value && *value) {
693 simple_strtoul(value, &value, 0);
695 } else if (strnicmp(data, "gid", 3) == 0) {
696 if (value && *value) {
698 simple_strtoul(value, &value, 0);
700 } else if (strnicmp(data, "file_mode", 4) == 0) {
701 if (value && *value) {
703 simple_strtoul(value, &value, 0);
705 } else if (strnicmp(data, "dir_mode", 4) == 0) {
706 if (value && *value) {
708 simple_strtoul(value, &value, 0);
710 } else if (strnicmp(data, "dirmode", 4) == 0) {
711 if (value && *value) {
713 simple_strtoul(value, &value, 0);
715 } else if (strnicmp(data, "port", 4) == 0) {
716 if (value && *value) {
718 simple_strtoul(value, &value, 0);
720 } else if (strnicmp(data, "rsize", 5) == 0) {
721 if (value && *value) {
723 simple_strtoul(value, &value, 0);
725 } else if (strnicmp(data, "wsize", 5) == 0) {
726 if (value && *value) {
728 simple_strtoul(value, &value, 0);
730 } else if (strnicmp(data, "sockopt", 5) == 0) {
731 if (value && *value) {
733 simple_strtoul(value, &value, 0);
735 } else if (strnicmp(data, "netbiosname", 4) == 0) {
736 if (!value || !*value || (*value == ' ')) {
737 cFYI(1,("invalid (empty) netbiosname specified"));
739 memset(vol->source_rfc1001_name,0x20,15);
741 /* BB are there cases in which a comma can be
742 valid in this workstation netbios name (and need
743 special handling)? */
745 /* We do not uppercase netbiosname for user */
749 vol->source_rfc1001_name[i] = value[i];
751 /* The string has 16th byte zero still from
752 set at top of the function */
753 if((i==15) && (value[i] != 0))
754 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
756 } else if (strnicmp(data, "credentials", 4) == 0) {
758 } else if (strnicmp(data, "version", 3) == 0) {
760 } else if (strnicmp(data, "guest",5) == 0) {
762 } else if (strnicmp(data, "rw", 2) == 0) {
764 } else if ((strnicmp(data, "suid", 4) == 0) ||
765 (strnicmp(data, "nosuid", 6) == 0) ||
766 (strnicmp(data, "exec", 4) == 0) ||
767 (strnicmp(data, "noexec", 6) == 0) ||
768 (strnicmp(data, "nodev", 5) == 0) ||
769 (strnicmp(data, "noauto", 6) == 0) ||
770 (strnicmp(data, "dev", 3) == 0)) {
771 /* The mount tool or mount.cifs helper (if present)
772 uses these opts to set flags, and the flags are read
773 by the kernel vfs layer before we get here (ie
774 before read super) so there is no point trying to
775 parse these options again and set anything and it
776 is ok to just ignore them */
778 } else if (strnicmp(data, "ro", 2) == 0) {
780 } else if (strnicmp(data, "hard", 4) == 0) {
782 } else if (strnicmp(data, "soft", 4) == 0) {
784 } else if (strnicmp(data, "perm", 4) == 0) {
786 } else if (strnicmp(data, "noperm", 6) == 0) {
788 } else if (strnicmp(data, "setuids", 7) == 0) {
790 } else if (strnicmp(data, "nosetuids", 9) == 0) {
792 } else if (strnicmp(data, "nohard", 6) == 0) {
794 } else if (strnicmp(data, "nosoft", 6) == 0) {
796 } else if (strnicmp(data, "nointr", 6) == 0) {
798 } else if (strnicmp(data, "intr", 4) == 0) {
800 } else if (strnicmp(data, "serverino",7) == 0) {
802 } else if (strnicmp(data, "noserverino",9) == 0) {
804 } else if (strnicmp(data, "acl",3) == 0) {
806 } else if (strnicmp(data, "noacl",5) == 0) {
808 } else if (strnicmp(data, "direct",6) == 0) {
810 } else if (strnicmp(data, "forcedirectio",13) == 0) {
812 } else if (strnicmp(data, "in6_addr",8) == 0) {
813 if (!value || !*value) {
814 vol->in6_addr = NULL;
815 } else if (strnlen(value, 49) == 48) {
816 vol->in6_addr = value;
818 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
821 } else if (strnicmp(data, "noac", 4) == 0) {
822 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
824 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
826 if (vol->UNC == NULL) {
827 if(devname == NULL) {
828 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
831 if ((temp_len = strnlen(devname, 300)) < 300) {
832 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
835 strcpy(vol->UNC,devname);
836 if (strncmp(vol->UNC, "//", 2) == 0) {
839 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
840 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
844 printk(KERN_WARNING "CIFS: UNC name too long\n");
849 vol->UNCip = &vol->UNC[2];
854 static struct cifsSesInfo *
855 cifs_find_tcp_session(struct in_addr * target_ip_addr,
856 struct in6_addr *target_ip6_addr,
857 char *userName, struct TCP_Server_Info **psrvTcp)
859 struct list_head *tmp;
860 struct cifsSesInfo *ses;
862 read_lock(&GlobalSMBSeslock);
864 list_for_each(tmp, &GlobalSMBSessionList) {
865 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
867 if((target_ip_addr &&
868 (ses->server->addr.sockAddr.sin_addr.s_addr
869 == target_ip_addr->s_addr)) || (target_ip6_addr
870 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
871 target_ip6_addr,sizeof(*target_ip6_addr)))){
872 /* BB lock server and tcp session and increment use count here?? */
873 *psrvTcp = ses->server; /* found a match on the TCP session */
874 /* BB check if reconnection needed */
876 (ses->userName, userName,
877 MAX_USERNAME_SIZE) == 0){
878 read_unlock(&GlobalSMBSeslock);
879 return ses; /* found exact match on both tcp and SMB sessions */
883 /* else tcp and smb sessions need reconnection */
885 read_unlock(&GlobalSMBSeslock);
889 static struct cifsTconInfo *
890 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
892 struct list_head *tmp;
893 struct cifsTconInfo *tcon;
895 read_lock(&GlobalSMBSeslock);
896 list_for_each(tmp, &GlobalTreeConnectionList) {
897 cFYI(1, ("Next tcon - "));
898 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
900 if (tcon->ses->server) {
902 (" old ip addr: %x == new ip %x ?",
903 tcon->ses->server->addr.sockAddr.sin_addr.
904 s_addr, new_target_ip_addr));
905 if (tcon->ses->server->addr.sockAddr.sin_addr.
906 s_addr == new_target_ip_addr) {
907 /* BB lock tcon and server and tcp session and increment use count here? */
908 /* found a match on the TCP session */
909 /* BB check if reconnection needed */
910 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
911 tcon->treeName, uncName));
913 (tcon->treeName, uncName,
914 MAX_TREE_SIZE) == 0) {
916 ("Matched UNC, old user: %s == new: %s ?",
917 tcon->treeName, uncName));
919 (tcon->ses->userName,
921 MAX_USERNAME_SIZE) == 0) {
922 read_unlock(&GlobalSMBSeslock);
923 return tcon;/* also matched user (smb session)*/
930 read_unlock(&GlobalSMBSeslock);
935 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
936 const char *old_path, const struct nls_table *nls_codepage)
938 unsigned char *referrals = NULL;
939 unsigned int num_referrals;
942 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
943 &num_referrals, &referrals);
945 /* BB Add in code to: if valid refrl, if not ip address contact
946 the helper that resolves tcp names, mount to it, try to
947 tcon to it unmount it if fail */
956 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
957 const char *old_path, const struct nls_table *nls_codepage,
958 unsigned int *pnum_referrals, unsigned char ** preferrals)
965 if (pSesInfo->ipc_tid == 0) {
966 temp_unc = kmalloc(2 /* for slashes */ +
967 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
968 + 1 + 4 /* slash IPC$ */ + 2,
970 if (temp_unc == NULL)
974 strcpy(temp_unc + 2, pSesInfo->serverName);
975 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
976 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
978 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
982 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
983 pnum_referrals, nls_codepage);
988 /* See RFC1001 section 14 on representation of Netbios names */
989 static void rfc1002mangle(char * target,char * source, unsigned int length)
993 for(i=0,j=0;i<(length);i++) {
994 /* mask a nibble at a time and encode */
995 target[j] = 'A' + (0x0F & (source[i] >> 4));
996 target[j+1] = 'A' + (0x0F & source[i]);
1004 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1005 char * netbios_name)
1009 __be16 orig_port = 0;
1011 if(*csocket == NULL) {
1012 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1014 cERROR(1, ("Error %d creating socket",rc));
1018 /* BB other socket options to set KEEPALIVE, NODELAY? */
1019 cFYI(1,("Socket created"));
1020 (*csocket)->sk->sk_allocation = GFP_NOFS;
1024 psin_server->sin_family = AF_INET;
1025 if(psin_server->sin_port) { /* user overrode default port */
1026 rc = (*csocket)->ops->connect(*csocket,
1027 (struct sockaddr *) psin_server,
1028 sizeof (struct sockaddr_in),0);
1034 /* save original port so we can retry user specified port
1035 later if fall back ports fail this time */
1036 orig_port = psin_server->sin_port;
1038 /* do not retry on the same port we just failed on */
1039 if(psin_server->sin_port != htons(CIFS_PORT)) {
1040 psin_server->sin_port = htons(CIFS_PORT);
1042 rc = (*csocket)->ops->connect(*csocket,
1043 (struct sockaddr *) psin_server,
1044 sizeof (struct sockaddr_in),0);
1050 psin_server->sin_port = htons(RFC1001_PORT);
1051 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1052 psin_server, sizeof (struct sockaddr_in),0);
1057 /* give up here - unless we want to retry on different
1058 protocol families some day */
1061 psin_server->sin_port = orig_port;
1062 cFYI(1,("Error %d connecting to server via ipv4",rc));
1063 sock_release(*csocket);
1067 /* Eventually check for other socket options to change from
1068 the default. sock_setsockopt not used because it expects
1069 user space buffer */
1070 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1072 /* send RFC1001 sessinit */
1074 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1075 /* some servers require RFC1001 sessinit before sending
1076 negprot - BB check reconnection in case where second
1077 sessinit is sent but no second negprot */
1078 struct rfc1002_session_packet * ses_init_buf;
1079 struct smb_hdr * smb_buf;
1080 ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1082 ses_init_buf->trailer.session_req.called_len = 32;
1083 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1084 DEFAULT_CIFS_CALLED_NAME,16);
1085 ses_init_buf->trailer.session_req.calling_len = 32;
1086 /* calling name ends in null (byte 16) from old smb
1088 if(netbios_name && (netbios_name[0] !=0)) {
1089 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1092 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1093 "LINUX_CIFS_CLNT",16);
1095 ses_init_buf->trailer.session_req.scope1 = 0;
1096 ses_init_buf->trailer.session_req.scope2 = 0;
1097 smb_buf = (struct smb_hdr *)ses_init_buf;
1098 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1099 smb_buf->smb_buf_length = 0x81000044;
1100 rc = smb_send(*csocket, smb_buf, 0x44,
1101 (struct sockaddr *)psin_server);
1102 kfree(ses_init_buf);
1104 /* else the negprot may still work without this
1105 even though malloc failed */
1113 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1117 __be16 orig_port = 0;
1119 if(*csocket == NULL) {
1120 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1122 cERROR(1, ("Error %d creating ipv6 socket",rc));
1126 /* BB other socket options to set KEEPALIVE, NODELAY? */
1127 cFYI(1,("ipv6 Socket created"));
1128 (*csocket)->sk->sk_allocation = GFP_NOFS;
1132 psin_server->sin6_family = AF_INET6;
1134 if(psin_server->sin6_port) { /* user overrode default port */
1135 rc = (*csocket)->ops->connect(*csocket,
1136 (struct sockaddr *) psin_server,
1137 sizeof (struct sockaddr_in6),0);
1143 /* save original port so we can retry user specified port
1144 later if fall back ports fail this time */
1146 orig_port = psin_server->sin6_port;
1147 /* do not retry on the same port we just failed on */
1148 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1149 psin_server->sin6_port = htons(CIFS_PORT);
1151 rc = (*csocket)->ops->connect(*csocket,
1152 (struct sockaddr *) psin_server,
1153 sizeof (struct sockaddr_in6),0);
1159 psin_server->sin6_port = htons(RFC1001_PORT);
1160 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1161 psin_server, sizeof (struct sockaddr_in6),0);
1166 /* give up here - unless we want to retry on different
1167 protocol families some day */
1170 psin_server->sin6_port = orig_port;
1171 cFYI(1,("Error %d connecting to server via ipv6",rc));
1172 sock_release(*csocket);
1176 /* Eventually check for other socket options to change from
1177 the default. sock_setsockopt not used because it expects
1178 user space buffer */
1179 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1185 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1186 char *mount_data, const char *devname)
1190 int address_type = AF_INET;
1191 struct socket *csocket = NULL;
1192 struct sockaddr_in sin_server;
1193 struct sockaddr_in6 sin_server6;
1194 struct smb_vol volume_info;
1195 struct cifsSesInfo *pSesInfo = NULL;
1196 struct cifsSesInfo *existingCifsSes = NULL;
1197 struct cifsTconInfo *tcon = NULL;
1198 struct TCP_Server_Info *srvTcp = NULL;
1202 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1204 memset(&volume_info,0,sizeof(struct smb_vol));
1205 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1207 kfree(volume_info.UNC);
1208 if(volume_info.password)
1209 kfree(volume_info.password);
1214 if (volume_info.username) {
1215 cFYI(1, ("Username: %s ", volume_info.username));
1218 cifserror("No username specified ");
1219 /* In userspace mount helper we can get user name from alternate
1220 locations such as env variables and files on disk */
1222 kfree(volume_info.UNC);
1223 if(volume_info.password)
1224 kfree(volume_info.password);
1229 if (volume_info.UNCip && volume_info.UNC) {
1230 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1233 /* not ipv4 address, try ipv6 */
1234 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1236 address_type = AF_INET6;
1238 address_type = AF_INET;
1242 /* we failed translating address */
1244 kfree(volume_info.UNC);
1245 if(volume_info.password)
1246 kfree(volume_info.password);
1251 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1254 } else if (volume_info.UNCip){
1255 /* BB using ip addr as server name connect to the DFS root below */
1256 cERROR(1,("Connecting to DFS root not implemented yet"));
1258 kfree(volume_info.UNC);
1259 if(volume_info.password)
1260 kfree(volume_info.password);
1263 } else /* which servers DFS root would we conect to */ {
1265 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1267 kfree(volume_info.UNC);
1268 if(volume_info.password)
1269 kfree(volume_info.password);
1274 /* this is needed for ASCII cp to Unicode converts */
1275 if(volume_info.iocharset == NULL) {
1276 cifs_sb->local_nls = load_nls_default();
1277 /* load_nls_default can not return null */
1279 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1280 if(cifs_sb->local_nls == NULL) {
1281 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1283 kfree(volume_info.UNC);
1284 if(volume_info.password)
1285 kfree(volume_info.password);
1291 if(address_type == AF_INET)
1292 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1293 NULL /* no ipv6 addr */,
1294 volume_info.username, &srvTcp);
1295 else if(address_type == AF_INET6)
1296 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1297 &sin_server6.sin6_addr,
1298 volume_info.username, &srvTcp);
1301 kfree(volume_info.UNC);
1302 if(volume_info.password)
1303 kfree(volume_info.password);
1310 cFYI(1, ("Existing tcp session with server found "));
1311 } else { /* create socket */
1312 if(volume_info.port)
1313 sin_server.sin_port = htons(volume_info.port);
1315 sin_server.sin_port = 0;
1316 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1319 ("Error connecting to IPv4 socket. Aborting operation"));
1321 sock_release(csocket);
1323 kfree(volume_info.UNC);
1324 if(volume_info.password)
1325 kfree(volume_info.password);
1330 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1331 if (srvTcp == NULL) {
1333 sock_release(csocket);
1335 kfree(volume_info.UNC);
1336 if(volume_info.password)
1337 kfree(volume_info.password);
1341 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1342 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1343 atomic_set(&srvTcp->inFlight,0);
1344 /* BB Add code for ipv6 case too */
1345 srvTcp->ssocket = csocket;
1346 srvTcp->protocolType = IPV4;
1347 init_waitqueue_head(&srvTcp->response_q);
1348 init_waitqueue_head(&srvTcp->request_q);
1349 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1350 /* at this point we are the only ones with the pointer
1351 to the struct since the kernel thread not created yet
1352 so no need to spinlock this init of tcpStatus */
1353 srvTcp->tcpStatus = CifsNew;
1354 init_MUTEX(&srvTcp->tcpSem);
1355 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1356 CLONE_FS | CLONE_FILES | CLONE_VM);
1359 sock_release(csocket);
1361 kfree(volume_info.UNC);
1362 if(volume_info.password)
1363 kfree(volume_info.password);
1368 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1372 if (existingCifsSes) {
1373 pSesInfo = existingCifsSes;
1374 cFYI(1, ("Existing smb sess found "));
1375 if(volume_info.password)
1376 kfree(volume_info.password);
1377 /* volume_info.UNC freed at end of function */
1379 cFYI(1, ("Existing smb sess not found "));
1380 pSesInfo = sesInfoAlloc();
1381 if (pSesInfo == NULL)
1384 pSesInfo->server = srvTcp;
1385 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1386 NIPQUAD(sin_server.sin_addr.s_addr));
1390 /* volume_info.password freed at unmount */
1391 if (volume_info.password)
1392 pSesInfo->password = volume_info.password;
1393 if (volume_info.username)
1394 strncpy(pSesInfo->userName,
1395 volume_info.username,MAX_USERNAME_SIZE);
1396 if (volume_info.domainname)
1397 strncpy(pSesInfo->domainName,
1398 volume_info.domainname,MAX_USERNAME_SIZE);
1399 pSesInfo->linux_uid = volume_info.linux_uid;
1400 down(&pSesInfo->sesSem);
1401 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1402 up(&pSesInfo->sesSem);
1404 atomic_inc(&srvTcp->socketUseCount);
1406 if(volume_info.password)
1407 kfree(volume_info.password);
1410 /* search for existing tcon to this server share */
1412 if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
1413 cifs_sb->rsize = volume_info.rsize;
1415 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1416 if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
1417 cifs_sb->wsize = volume_info.wsize;
1419 cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1420 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1421 cifs_sb->rsize = PAGE_CACHE_SIZE;
1422 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1424 cifs_sb->mnt_uid = volume_info.linux_uid;
1425 cifs_sb->mnt_gid = volume_info.linux_gid;
1426 cifs_sb->mnt_file_mode = volume_info.file_mode;
1427 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1428 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1430 if(volume_info.noperm)
1431 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1432 if(volume_info.setuids)
1433 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1434 if(volume_info.server_ino)
1435 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1436 if(volume_info.direct_io) {
1437 cERROR(1,("mounting share using direct i/o"));
1438 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1442 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1443 volume_info.username);
1445 cFYI(1, ("Found match on UNC path "));
1446 /* we can have only one retry value for a connection
1447 to a share so for resources mounted more than once
1448 to the same server share the last value passed in
1449 for the retry flag is used */
1450 tcon->retry = volume_info.retry;
1452 tcon = tconInfoAlloc();
1456 /* check for null share name ie connect to dfs root */
1458 /* BB check if this works for exactly length three strings */
1459 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1460 && (strchr(volume_info.UNC + 3, '/') ==
1462 rc = connect_to_dfs_path(xid,
1468 kfree(volume_info.UNC);
1472 rc = CIFSTCon(xid, pSesInfo,
1474 tcon, cifs_sb->local_nls);
1475 cFYI(1, ("CIFS Tcon rc = %d", rc));
1478 atomic_inc(&pSesInfo->inUse);
1479 tcon->retry = volume_info.retry;
1485 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1486 sb->s_maxbytes = (u64) 1 << 63;
1488 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1491 sb->s_time_gran = 100;
1493 /* on error free sesinfo and tcon struct if needed */
1495 /* if session setup failed, use count is zero but
1496 we still need to free cifsd thread */
1497 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1498 spin_lock(&GlobalMid_Lock);
1499 srvTcp->tcpStatus = CifsExiting;
1500 spin_unlock(&GlobalMid_Lock);
1502 send_sig(SIGKILL,srvTcp->tsk,1);
1504 /* If find_unc succeeded then rc == 0 so we can not end */
1505 if (tcon) /* up accidently freeing someone elses tcon struct */
1507 if (existingCifsSes == 0) {
1509 if ((pSesInfo->server) &&
1510 (pSesInfo->status == CifsGood)) {
1512 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1513 /* if the socketUseCount is now zero */
1514 if((temp_rc == -ESHUTDOWN) &&
1515 (pSesInfo->server->tsk))
1516 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1518 cFYI(1, ("No session or bad tcon"));
1519 sesInfoFree(pSesInfo);
1520 /* pSesInfo = NULL; */
1524 atomic_inc(&tcon->useCount);
1525 cifs_sb->tcon = tcon;
1526 tcon->ses = pSesInfo;
1528 /* do not care if following two calls succeed - informational only */
1529 CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
1530 CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
1531 if (tcon->ses->capabilities & CAP_UNIX) {
1532 if(!CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls)) {
1533 if(!volume_info.no_psx_acl) {
1534 if(CIFS_UNIX_POSIX_ACL_CAP &
1535 le64_to_cpu(tcon->fsUnixInfo.Capability))
1536 cFYI(1,("server negotiated posix acl support"));
1537 sb->s_flags |= MS_POSIXACL;
1543 /* volume_info.password is freed above when existing session found
1544 (in which case it is not needed anymore) but when new sesion is created
1545 the password ptr is put in the new session structure (in which case the
1546 password will be freed at unmount time) */
1548 kfree(volume_info.UNC);
1554 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1555 char session_key[CIFS_SESSION_KEY_SIZE],
1556 const struct nls_table *nls_codepage)
1558 struct smb_hdr *smb_buffer;
1559 struct smb_hdr *smb_buffer_response;
1560 SESSION_SETUP_ANDX *pSMB;
1561 SESSION_SETUP_ANDX *pSMBr;
1566 int remaining_words = 0;
1567 int bytes_returned = 0;
1572 cFYI(1, ("In sesssetup "));
1575 user = ses->userName;
1576 domain = ses->domainName;
1577 smb_buffer = cifs_buf_get();
1578 if (smb_buffer == 0) {
1581 smb_buffer_response = smb_buffer;
1582 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1584 /* send SMBsessionSetup here */
1585 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1586 NULL /* no tCon exists yet */ , 13 /* wct */ );
1588 pSMB->req_no_secext.AndXCommand = 0xFF;
1589 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1590 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1592 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1593 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1595 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
1596 if (ses->capabilities & CAP_UNICODE) {
1597 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1598 capabilities |= CAP_UNICODE;
1600 if (ses->capabilities & CAP_STATUS32) {
1601 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1602 capabilities |= CAP_STATUS32;
1604 if (ses->capabilities & CAP_DFS) {
1605 smb_buffer->Flags2 |= SMBFLG2_DFS;
1606 capabilities |= CAP_DFS;
1608 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1610 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1611 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1613 pSMB->req_no_secext.CaseSensitivePasswordLength =
1614 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1615 bcc_ptr = pByteArea(smb_buffer);
1616 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1617 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1618 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1619 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1621 if (ses->capabilities & CAP_UNICODE) {
1622 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1627 bytes_returned = 0; /* skill null user */
1630 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1632 bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
1633 bcc_ptr += 2; /* trailing null */
1636 cifs_strtoUCS((wchar_t *) bcc_ptr,
1637 "CIFS_LINUX_DOM", 32, nls_codepage);
1640 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1642 bcc_ptr += 2 * bytes_returned;
1645 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1647 bcc_ptr += 2 * bytes_returned;
1649 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
1651 bcc_ptr += 2 * bytes_returned;
1654 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1656 bcc_ptr += 2 * bytes_returned;
1660 strncpy(bcc_ptr, user, 200);
1661 bcc_ptr += strnlen(user, 200);
1665 if (domain == NULL) {
1666 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1667 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1669 strncpy(bcc_ptr, domain, 64);
1670 bcc_ptr += strnlen(domain, 64);
1674 strcpy(bcc_ptr, "Linux version ");
1675 bcc_ptr += strlen("Linux version ");
1676 strcpy(bcc_ptr, system_utsname.release);
1677 bcc_ptr += strlen(system_utsname.release) + 1;
1678 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1679 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1681 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1682 smb_buffer->smb_buf_length += count;
1683 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1685 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1686 &bytes_returned, 1);
1688 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1689 } else if ((smb_buffer_response->WordCount == 3)
1690 || (smb_buffer_response->WordCount == 4)) {
1691 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1692 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1693 if (action & GUEST_LOGIN)
1694 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1695 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1696 cFYI(1, ("UID = %d ", ses->Suid));
1697 /* response can have either 3 or 4 word count - Samba sends 3 */
1698 bcc_ptr = pByteArea(smb_buffer_response);
1699 if ((pSMBr->resp.hdr.WordCount == 3)
1700 || ((pSMBr->resp.hdr.WordCount == 4)
1701 && (blob_len < pSMBr->resp.ByteCount))) {
1702 if (pSMBr->resp.hdr.WordCount == 4)
1703 bcc_ptr += blob_len;
1705 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1706 if ((long) (bcc_ptr) % 2) {
1708 (BCC(smb_buffer_response) - 1) /2;
1709 bcc_ptr++; /* Unicode strings must be word aligned */
1712 BCC(smb_buffer_response) / 2;
1715 UniStrnlen((wchar_t *) bcc_ptr,
1716 remaining_words - 1);
1717 /* We look for obvious messed up bcc or strings in response so we do not go off
1718 the end since (at least) WIN2K and Windows XP have a major bug in not null
1719 terminating last Unicode string in response */
1720 ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1721 cifs_strfromUCS_le(ses->serverOS,
1722 (wchar_t *)bcc_ptr, len,nls_codepage);
1723 bcc_ptr += 2 * (len + 1);
1724 remaining_words -= len + 1;
1725 ses->serverOS[2 * len] = 0;
1726 ses->serverOS[1 + (2 * len)] = 0;
1727 if (remaining_words > 0) {
1728 len = UniStrnlen((wchar_t *)bcc_ptr,
1730 ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
1731 cifs_strfromUCS_le(ses->serverNOS,
1732 (wchar_t *)bcc_ptr,len,nls_codepage);
1733 bcc_ptr += 2 * (len + 1);
1734 ses->serverNOS[2 * len] = 0;
1735 ses->serverNOS[1 + (2 * len)] = 0;
1736 remaining_words -= len + 1;
1737 if (remaining_words > 0) {
1738 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1739 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1741 cifs_kcalloc(2*(len+1),GFP_KERNEL);
1742 cifs_strfromUCS_le(ses->serverDomain,
1743 (wchar_t *)bcc_ptr,len,nls_codepage);
1744 bcc_ptr += 2 * (len + 1);
1745 ses->serverDomain[2*len] = 0;
1746 ses->serverDomain[1+(2*len)] = 0;
1747 } /* else no more room so create dummy domain string */
1752 } else { /* no room so create dummy domain and NOS string */
1754 cifs_kcalloc(2, GFP_KERNEL);
1756 cifs_kcalloc(2, GFP_KERNEL);
1758 } else { /* ASCII */
1759 len = strnlen(bcc_ptr, 1024);
1760 if (((long) bcc_ptr + len) - (long)
1761 pByteArea(smb_buffer_response)
1762 <= BCC(smb_buffer_response)) {
1763 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1764 strncpy(ses->serverOS,bcc_ptr, len);
1767 bcc_ptr[0] = 0; /* null terminate the string */
1770 len = strnlen(bcc_ptr, 1024);
1771 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1772 strncpy(ses->serverNOS, bcc_ptr, len);
1777 len = strnlen(bcc_ptr, 1024);
1778 ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
1779 strncpy(ses->serverDomain, bcc_ptr, len);
1785 ("Variable field of length %d extends beyond end of smb ",
1790 (" Security Blob Length extends beyond end of SMB"));
1794 (" Invalid Word count %d: ",
1795 smb_buffer_response->WordCount));
1800 cifs_buf_release(smb_buffer);
1806 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1807 char *SecurityBlob,int SecurityBlobLength,
1808 const struct nls_table *nls_codepage)
1810 struct smb_hdr *smb_buffer;
1811 struct smb_hdr *smb_buffer_response;
1812 SESSION_SETUP_ANDX *pSMB;
1813 SESSION_SETUP_ANDX *pSMBr;
1818 int remaining_words = 0;
1819 int bytes_returned = 0;
1824 cFYI(1, ("In spnego sesssetup "));
1827 user = ses->userName;
1828 domain = ses->domainName;
1830 smb_buffer = cifs_buf_get();
1831 if (smb_buffer == 0) {
1834 smb_buffer_response = smb_buffer;
1835 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1837 /* send SMBsessionSetup here */
1838 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1839 NULL /* no tCon exists yet */ , 12 /* wct */ );
1840 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1841 pSMB->req.AndXCommand = 0xFF;
1842 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1843 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1845 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1846 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1848 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1849 CAP_EXTENDED_SECURITY;
1850 if (ses->capabilities & CAP_UNICODE) {
1851 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1852 capabilities |= CAP_UNICODE;
1854 if (ses->capabilities & CAP_STATUS32) {
1855 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1856 capabilities |= CAP_STATUS32;
1858 if (ses->capabilities & CAP_DFS) {
1859 smb_buffer->Flags2 |= SMBFLG2_DFS;
1860 capabilities |= CAP_DFS;
1862 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1864 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1865 bcc_ptr = pByteArea(smb_buffer);
1866 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1867 bcc_ptr += SecurityBlobLength;
1869 if (ses->capabilities & CAP_UNICODE) {
1870 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1875 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1876 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1877 bcc_ptr += 2; /* trailing null */
1880 cifs_strtoUCS((wchar_t *) bcc_ptr,
1881 "CIFS_LINUX_DOM", 32, nls_codepage);
1884 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1886 bcc_ptr += 2 * bytes_returned;
1889 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1891 bcc_ptr += 2 * bytes_returned;
1893 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
1895 bcc_ptr += 2 * bytes_returned;
1898 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1900 bcc_ptr += 2 * bytes_returned;
1903 strncpy(bcc_ptr, user, 200);
1904 bcc_ptr += strnlen(user, 200);
1907 if (domain == NULL) {
1908 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1909 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1911 strncpy(bcc_ptr, domain, 64);
1912 bcc_ptr += strnlen(domain, 64);
1916 strcpy(bcc_ptr, "Linux version ");
1917 bcc_ptr += strlen("Linux version ");
1918 strcpy(bcc_ptr, system_utsname.release);
1919 bcc_ptr += strlen(system_utsname.release) + 1;
1920 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1921 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1923 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1924 smb_buffer->smb_buf_length += count;
1925 pSMB->req.ByteCount = cpu_to_le16(count);
1927 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1928 &bytes_returned, 1);
1930 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1931 } else if ((smb_buffer_response->WordCount == 3)
1932 || (smb_buffer_response->WordCount == 4)) {
1933 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1935 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1936 if (action & GUEST_LOGIN)
1937 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1939 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1940 cFYI(1, ("UID = %d ", ses->Suid));
1941 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
1943 /* BB Fix below to make endian neutral !! */
1945 if ((pSMBr->resp.hdr.WordCount == 3)
1946 || ((pSMBr->resp.hdr.WordCount == 4)
1948 pSMBr->resp.ByteCount))) {
1949 if (pSMBr->resp.hdr.WordCount == 4) {
1953 ("Security Blob Length %d ",
1957 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1958 if ((long) (bcc_ptr) % 2) {
1960 (BCC(smb_buffer_response)
1962 bcc_ptr++; /* Unicode strings must be word aligned */
1966 (smb_buffer_response) / 2;
1969 UniStrnlen((wchar_t *) bcc_ptr,
1970 remaining_words - 1);
1971 /* We look for obvious messed up bcc or strings in response so we do not go off
1972 the end since (at least) WIN2K and Windows XP have a major bug in not null
1973 terminating last Unicode string in response */
1975 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1976 cifs_strfromUCS_le(ses->serverOS,
1980 bcc_ptr += 2 * (len + 1);
1981 remaining_words -= len + 1;
1982 ses->serverOS[2 * len] = 0;
1983 ses->serverOS[1 + (2 * len)] = 0;
1984 if (remaining_words > 0) {
1985 len = UniStrnlen((wchar_t *)bcc_ptr,
1989 cifs_kcalloc(2 * (len + 1),
1991 cifs_strfromUCS_le(ses->serverNOS,
1995 bcc_ptr += 2 * (len + 1);
1996 ses->serverNOS[2 * len] = 0;
1997 ses->serverNOS[1 + (2 * len)] = 0;
1998 remaining_words -= len + 1;
1999 if (remaining_words > 0) {
2000 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2001 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2002 ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
2003 cifs_strfromUCS_le(ses->serverDomain,
2007 bcc_ptr += 2*(len+1);
2008 ses->serverDomain[2*len] = 0;
2009 ses->serverDomain[1+(2*len)] = 0;
2010 } /* else no more room so create dummy domain string */
2013 cifs_kcalloc(2,GFP_KERNEL);
2014 } else { /* no room so create dummy domain and NOS string */
2015 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2016 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2018 } else { /* ASCII */
2020 len = strnlen(bcc_ptr, 1024);
2021 if (((long) bcc_ptr + len) - (long)
2022 pByteArea(smb_buffer_response)
2023 <= BCC(smb_buffer_response)) {
2024 ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
2025 strncpy(ses->serverOS, bcc_ptr, len);
2028 bcc_ptr[0] = 0; /* null terminate the string */
2031 len = strnlen(bcc_ptr, 1024);
2032 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2033 strncpy(ses->serverNOS, bcc_ptr, len);
2038 len = strnlen(bcc_ptr, 1024);
2039 ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
2040 strncpy(ses->serverDomain, bcc_ptr, len);
2046 ("Variable field of length %d extends beyond end of smb ",
2051 (" Security Blob Length extends beyond end of SMB"));
2054 cERROR(1, ("No session structure passed in."));
2058 (" Invalid Word count %d: ",
2059 smb_buffer_response->WordCount));
2064 cifs_buf_release(smb_buffer);
2070 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2071 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2072 const struct nls_table *nls_codepage)
2074 struct smb_hdr *smb_buffer;
2075 struct smb_hdr *smb_buffer_response;
2076 SESSION_SETUP_ANDX *pSMB;
2077 SESSION_SETUP_ANDX *pSMBr;
2081 int remaining_words = 0;
2082 int bytes_returned = 0;
2084 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2085 PNEGOTIATE_MESSAGE SecurityBlob;
2086 PCHALLENGE_MESSAGE SecurityBlob2;
2087 __u32 negotiate_flags, capabilities;
2090 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2093 domain = ses->domainName;
2094 *pNTLMv2_flag = FALSE;
2095 smb_buffer = cifs_buf_get();
2096 if (smb_buffer == 0) {
2099 smb_buffer_response = smb_buffer;
2100 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2101 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2103 /* send SMBsessionSetup here */
2104 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2105 NULL /* no tCon exists yet */ , 12 /* wct */ );
2106 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2107 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2109 pSMB->req.AndXCommand = 0xFF;
2110 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2111 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2113 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2114 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2116 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2117 CAP_EXTENDED_SECURITY;
2118 if (ses->capabilities & CAP_UNICODE) {
2119 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2120 capabilities |= CAP_UNICODE;
2122 if (ses->capabilities & CAP_STATUS32) {
2123 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2124 capabilities |= CAP_STATUS32;
2126 if (ses->capabilities & CAP_DFS) {
2127 smb_buffer->Flags2 |= SMBFLG2_DFS;
2128 capabilities |= CAP_DFS;
2130 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2132 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2133 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2134 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2135 SecurityBlob->MessageType = NtLmNegotiate;
2137 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2138 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2139 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2141 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2143 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2144 /* setup pointers to domain name and workstation name */
2145 bcc_ptr += SecurityBlobLength;
2147 SecurityBlob->WorkstationName.Buffer = 0;
2148 SecurityBlob->WorkstationName.Length = 0;
2149 SecurityBlob->WorkstationName.MaximumLength = 0;
2151 if (domain == NULL) {
2152 SecurityBlob->DomainName.Buffer = 0;
2153 SecurityBlob->DomainName.Length = 0;
2154 SecurityBlob->DomainName.MaximumLength = 0;
2157 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2158 strncpy(bcc_ptr, domain, 63);
2159 len = strnlen(domain, 64);
2160 SecurityBlob->DomainName.MaximumLength =
2162 SecurityBlob->DomainName.Buffer =
2163 cpu_to_le32((long) &SecurityBlob->
2165 (long) &SecurityBlob->Signature);
2167 SecurityBlobLength += len;
2168 SecurityBlob->DomainName.Length =
2171 if (ses->capabilities & CAP_UNICODE) {
2172 if ((long) bcc_ptr % 2) {
2178 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2180 bcc_ptr += 2 * bytes_returned;
2182 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2184 bcc_ptr += 2 * bytes_returned;
2185 bcc_ptr += 2; /* null terminate Linux version */
2187 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2189 bcc_ptr += 2 * bytes_returned;
2192 bcc_ptr += 2; /* null terminate network opsys string */
2195 bcc_ptr += 2; /* null domain */
2196 } else { /* ASCII */
2197 strcpy(bcc_ptr, "Linux version ");
2198 bcc_ptr += strlen("Linux version ");
2199 strcpy(bcc_ptr, system_utsname.release);
2200 bcc_ptr += strlen(system_utsname.release) + 1;
2201 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2202 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2203 bcc_ptr++; /* empty domain field */
2206 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2207 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2208 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2209 smb_buffer->smb_buf_length += count;
2210 pSMB->req.ByteCount = cpu_to_le16(count);
2212 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2213 &bytes_returned, 1);
2215 if (smb_buffer_response->Status.CifsError ==
2216 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2220 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2221 } else if ((smb_buffer_response->WordCount == 3)
2222 || (smb_buffer_response->WordCount == 4)) {
2223 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2224 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2226 if (action & GUEST_LOGIN)
2227 cFYI(1, (" Guest login"));
2228 /* Do we want to set anything in SesInfo struct when guest login? */
2230 bcc_ptr = pByteArea(smb_buffer_response);
2231 /* response can have either 3 or 4 word count - Samba sends 3 */
2233 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2234 if (SecurityBlob2->MessageType != NtLmChallenge) {
2236 ("Unexpected NTLMSSP message type received %d",
2237 SecurityBlob2->MessageType));
2239 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2240 cFYI(1, ("UID = %d ", ses->Suid));
2241 if ((pSMBr->resp.hdr.WordCount == 3)
2242 || ((pSMBr->resp.hdr.WordCount == 4)
2244 pSMBr->resp.ByteCount))) {
2246 if (pSMBr->resp.hdr.WordCount == 4) {
2247 bcc_ptr += blob_len;
2249 ("Security Blob Length %d ",
2253 cFYI(1, ("NTLMSSP Challenge rcvd "));
2255 memcpy(ses->server->cryptKey,
2256 SecurityBlob2->Challenge,
2257 CIFS_CRYPTO_KEY_SIZE);
2258 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2259 *pNTLMv2_flag = TRUE;
2261 if((SecurityBlob2->NegotiateFlags &
2262 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2263 || (sign_CIFS_PDUs > 1))
2264 ses->server->secMode |=
2265 SECMODE_SIGN_REQUIRED;
2266 if ((SecurityBlob2->NegotiateFlags &
2267 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2268 ses->server->secMode |=
2269 SECMODE_SIGN_ENABLED;
2271 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2272 if ((long) (bcc_ptr) % 2) {
2274 (BCC(smb_buffer_response)
2276 bcc_ptr++; /* Unicode strings must be word aligned */
2280 (smb_buffer_response) / 2;
2283 UniStrnlen((wchar_t *) bcc_ptr,
2284 remaining_words - 1);
2285 /* We look for obvious messed up bcc or strings in response so we do not go off
2286 the end since (at least) WIN2K and Windows XP have a major bug in not null
2287 terminating last Unicode string in response */
2289 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2290 cifs_strfromUCS_le(ses->serverOS,
2294 bcc_ptr += 2 * (len + 1);
2295 remaining_words -= len + 1;
2296 ses->serverOS[2 * len] = 0;
2297 ses->serverOS[1 + (2 * len)] = 0;
2298 if (remaining_words > 0) {
2299 len = UniStrnlen((wchar_t *)
2304 cifs_kcalloc(2 * (len + 1),
2306 cifs_strfromUCS_le(ses->
2312 bcc_ptr += 2 * (len + 1);
2313 ses->serverNOS[2 * len] = 0;
2316 remaining_words -= len + 1;
2317 if (remaining_words > 0) {
2318 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2319 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2344 } /* else no more room so create dummy domain string */
2349 } else { /* no room so create dummy domain and NOS string */
2351 cifs_kcalloc(2, GFP_KERNEL);
2353 cifs_kcalloc(2, GFP_KERNEL);
2355 } else { /* ASCII */
2356 len = strnlen(bcc_ptr, 1024);
2357 if (((long) bcc_ptr + len) - (long)
2358 pByteArea(smb_buffer_response)
2359 <= BCC(smb_buffer_response)) {
2361 cifs_kcalloc(len + 1,
2363 strncpy(ses->serverOS,
2367 bcc_ptr[0] = 0; /* null terminate string */
2370 len = strnlen(bcc_ptr, 1024);
2372 cifs_kcalloc(len + 1,
2374 strncpy(ses->serverNOS, bcc_ptr, len);
2379 len = strnlen(bcc_ptr, 1024);
2381 cifs_kcalloc(len + 1,
2383 strncpy(ses->serverDomain, bcc_ptr, len);
2389 ("Variable field of length %d extends beyond end of smb ",
2394 (" Security Blob Length extends beyond end of SMB"));
2397 cERROR(1, ("No session structure passed in."));
2401 (" Invalid Word count %d: ",
2402 smb_buffer_response->WordCount));
2407 cifs_buf_release(smb_buffer);
2412 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2413 char *ntlm_session_key, int ntlmv2_flag,
2414 const struct nls_table *nls_codepage)
2416 struct smb_hdr *smb_buffer;
2417 struct smb_hdr *smb_buffer_response;
2418 SESSION_SETUP_ANDX *pSMB;
2419 SESSION_SETUP_ANDX *pSMBr;
2424 int remaining_words = 0;
2425 int bytes_returned = 0;
2427 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2428 PAUTHENTICATE_MESSAGE SecurityBlob;
2429 __u32 negotiate_flags, capabilities;
2432 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2435 user = ses->userName;
2436 domain = ses->domainName;
2437 smb_buffer = cifs_buf_get();
2438 if (smb_buffer == 0) {
2441 smb_buffer_response = smb_buffer;
2442 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2443 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2445 /* send SMBsessionSetup here */
2446 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2447 NULL /* no tCon exists yet */ , 12 /* wct */ );
2448 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2449 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2450 pSMB->req.AndXCommand = 0xFF;
2451 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2452 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2454 pSMB->req.hdr.Uid = ses->Suid;
2456 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2457 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2459 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2460 CAP_EXTENDED_SECURITY;
2461 if (ses->capabilities & CAP_UNICODE) {
2462 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2463 capabilities |= CAP_UNICODE;
2465 if (ses->capabilities & CAP_STATUS32) {
2466 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2467 capabilities |= CAP_STATUS32;
2469 if (ses->capabilities & CAP_DFS) {
2470 smb_buffer->Flags2 |= SMBFLG2_DFS;
2471 capabilities |= CAP_DFS;
2473 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2475 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2476 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2477 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2478 SecurityBlob->MessageType = NtLmAuthenticate;
2479 bcc_ptr += SecurityBlobLength;
2481 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2482 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2483 0x80000000 | NTLMSSP_NEGOTIATE_128;
2485 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2487 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2489 /* setup pointers to domain name and workstation name */
2491 SecurityBlob->WorkstationName.Buffer = 0;
2492 SecurityBlob->WorkstationName.Length = 0;
2493 SecurityBlob->WorkstationName.MaximumLength = 0;
2494 SecurityBlob->SessionKey.Length = 0;
2495 SecurityBlob->SessionKey.MaximumLength = 0;
2496 SecurityBlob->SessionKey.Buffer = 0;
2498 SecurityBlob->LmChallengeResponse.Length = 0;
2499 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2500 SecurityBlob->LmChallengeResponse.Buffer = 0;
2502 SecurityBlob->NtChallengeResponse.Length =
2503 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2504 SecurityBlob->NtChallengeResponse.MaximumLength =
2505 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2506 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2507 SecurityBlob->NtChallengeResponse.Buffer =
2508 cpu_to_le32(SecurityBlobLength);
2509 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2510 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2512 if (ses->capabilities & CAP_UNICODE) {
2513 if (domain == NULL) {
2514 SecurityBlob->DomainName.Buffer = 0;
2515 SecurityBlob->DomainName.Length = 0;
2516 SecurityBlob->DomainName.MaximumLength = 0;
2519 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2522 SecurityBlob->DomainName.MaximumLength =
2524 SecurityBlob->DomainName.Buffer =
2525 cpu_to_le32(SecurityBlobLength);
2527 SecurityBlobLength += len;
2528 SecurityBlob->DomainName.Length =
2532 SecurityBlob->UserName.Buffer = 0;
2533 SecurityBlob->UserName.Length = 0;
2534 SecurityBlob->UserName.MaximumLength = 0;
2537 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2540 SecurityBlob->UserName.MaximumLength =
2542 SecurityBlob->UserName.Buffer =
2543 cpu_to_le32(SecurityBlobLength);
2545 SecurityBlobLength += len;
2546 SecurityBlob->UserName.Length =
2550 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2551 SecurityBlob->WorkstationName.Length *= 2;
2552 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2553 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2554 bcc_ptr += SecurityBlob->WorkstationName.Length;
2555 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2556 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2558 if ((long) bcc_ptr % 2) {
2563 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2565 bcc_ptr += 2 * bytes_returned;
2567 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2569 bcc_ptr += 2 * bytes_returned;
2570 bcc_ptr += 2; /* null term version string */
2572 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2574 bcc_ptr += 2 * bytes_returned;
2577 bcc_ptr += 2; /* null terminate network opsys string */
2580 bcc_ptr += 2; /* null domain */
2581 } else { /* ASCII */
2582 if (domain == NULL) {
2583 SecurityBlob->DomainName.Buffer = 0;
2584 SecurityBlob->DomainName.Length = 0;
2585 SecurityBlob->DomainName.MaximumLength = 0;
2588 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2589 strncpy(bcc_ptr, domain, 63);
2590 len = strnlen(domain, 64);
2591 SecurityBlob->DomainName.MaximumLength =
2593 SecurityBlob->DomainName.Buffer =
2594 cpu_to_le32(SecurityBlobLength);
2596 SecurityBlobLength += len;
2597 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2600 SecurityBlob->UserName.Buffer = 0;
2601 SecurityBlob->UserName.Length = 0;
2602 SecurityBlob->UserName.MaximumLength = 0;
2605 strncpy(bcc_ptr, user, 63);
2606 len = strnlen(user, 64);
2607 SecurityBlob->UserName.MaximumLength =
2609 SecurityBlob->UserName.Buffer =
2610 cpu_to_le32(SecurityBlobLength);
2612 SecurityBlobLength += len;
2613 SecurityBlob->UserName.Length = cpu_to_le16(len);
2615 /* BB fill in our workstation name if known BB */
2617 strcpy(bcc_ptr, "Linux version ");
2618 bcc_ptr += strlen("Linux version ");
2619 strcpy(bcc_ptr, system_utsname.release);
2620 bcc_ptr += strlen(system_utsname.release) + 1;
2621 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2622 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2623 bcc_ptr++; /* null domain */
2626 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2627 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2628 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2629 smb_buffer->smb_buf_length += count;
2630 pSMB->req.ByteCount = cpu_to_le16(count);
2632 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2633 &bytes_returned, 1);
2635 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2636 } else if ((smb_buffer_response->WordCount == 3)
2637 || (smb_buffer_response->WordCount == 4)) {
2638 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2640 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2641 if (action & GUEST_LOGIN)
2642 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2643 /* if(SecurityBlob2->MessageType != NtLm??){
2644 cFYI("Unexpected message type on auth response is %d "));
2648 ("Does UID on challenge %d match auth response UID %d ",
2649 ses->Suid, smb_buffer_response->Uid));
2650 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2651 bcc_ptr = pByteArea(smb_buffer_response);
2652 /* response can have either 3 or 4 word count - Samba sends 3 */
2653 if ((pSMBr->resp.hdr.WordCount == 3)
2654 || ((pSMBr->resp.hdr.WordCount == 4)
2656 pSMBr->resp.ByteCount))) {
2657 if (pSMBr->resp.hdr.WordCount == 4) {
2661 ("Security Blob Length %d ",
2666 ("NTLMSSP response to Authenticate "));
2668 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2669 if ((long) (bcc_ptr) % 2) {
2671 (BCC(smb_buffer_response)
2673 bcc_ptr++; /* Unicode strings must be word aligned */
2675 remaining_words = BCC(smb_buffer_response) / 2;
2678 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2679 /* We look for obvious messed up bcc or strings in response so we do not go off
2680 the end since (at least) WIN2K and Windows XP have a major bug in not null
2681 terminating last Unicode string in response */
2683 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2684 cifs_strfromUCS_le(ses->serverOS,
2688 bcc_ptr += 2 * (len + 1);
2689 remaining_words -= len + 1;
2690 ses->serverOS[2 * len] = 0;
2691 ses->serverOS[1 + (2 * len)] = 0;
2692 if (remaining_words > 0) {
2693 len = UniStrnlen((wchar_t *)
2698 cifs_kcalloc(2 * (len + 1),
2700 cifs_strfromUCS_le(ses->
2706 bcc_ptr += 2 * (len + 1);
2707 ses->serverNOS[2 * len] = 0;
2708 ses->serverNOS[1+(2*len)] = 0;
2709 remaining_words -= len + 1;
2710 if (remaining_words > 0) {
2711 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2712 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2737 } /* else no more room so create dummy domain string */
2739 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
2740 } else { /* no room so create dummy domain and NOS string */
2741 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2742 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2744 } else { /* ASCII */
2745 len = strnlen(bcc_ptr, 1024);
2746 if (((long) bcc_ptr + len) -
2747 (long) pByteArea(smb_buffer_response)
2748 <= BCC(smb_buffer_response)) {
2749 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2750 strncpy(ses->serverOS,bcc_ptr, len);
2753 bcc_ptr[0] = 0; /* null terminate the string */
2756 len = strnlen(bcc_ptr, 1024);
2757 ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
2758 strncpy(ses->serverNOS, bcc_ptr, len);
2763 len = strnlen(bcc_ptr, 1024);
2764 ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
2765 strncpy(ses->serverDomain, bcc_ptr, len);
2771 ("Variable field of length %d extends beyond end of smb ",
2776 (" Security Blob Length extends beyond end of SMB"));
2779 cERROR(1, ("No session structure passed in."));
2783 (" Invalid Word count %d: ",
2784 smb_buffer_response->WordCount));
2789 cifs_buf_release(smb_buffer);
2795 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2796 const char *tree, struct cifsTconInfo *tcon,
2797 const struct nls_table *nls_codepage)
2799 struct smb_hdr *smb_buffer;
2800 struct smb_hdr *smb_buffer_response;
2803 unsigned char *bcc_ptr;
2811 smb_buffer = cifs_buf_get();
2812 if (smb_buffer == 0) {
2815 smb_buffer_response = smb_buffer;
2817 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2818 NULL /*no tid */ , 4 /*wct */ );
2819 smb_buffer->Uid = ses->Suid;
2820 pSMB = (TCONX_REQ *) smb_buffer;
2821 pSMBr = (TCONX_RSP *) smb_buffer_response;
2823 pSMB->AndXCommand = 0xFF;
2824 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2825 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2826 bcc_ptr = &pSMB->Password[0];
2827 bcc_ptr++; /* skip password */
2829 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2830 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2832 if (ses->capabilities & CAP_STATUS32) {
2833 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2835 if (ses->capabilities & CAP_DFS) {
2836 smb_buffer->Flags2 |= SMBFLG2_DFS;
2838 if (ses->capabilities & CAP_UNICODE) {
2839 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2841 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2842 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2843 bcc_ptr += 2; /* skip trailing null */
2844 } else { /* ASCII */
2846 strcpy(bcc_ptr, tree);
2847 bcc_ptr += strlen(tree) + 1;
2849 strcpy(bcc_ptr, "?????");
2850 bcc_ptr += strlen("?????");
2852 count = bcc_ptr - &pSMB->Password[0];
2853 pSMB->hdr.smb_buf_length += count;
2854 pSMB->ByteCount = cpu_to_le16(count);
2856 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2858 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2859 /* above now done in SendReceive */
2860 if ((rc == 0) && (tcon != NULL)) {
2861 tcon->tidStatus = CifsGood;
2862 tcon->tid = smb_buffer_response->Tid;
2863 bcc_ptr = pByteArea(smb_buffer_response);
2864 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2865 /* skip service field (NB: this field is always ASCII) */
2866 bcc_ptr += length + 1;
2867 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2868 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2869 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2870 if ((bcc_ptr + (2 * length)) -
2871 pByteArea(smb_buffer_response) <=
2872 BCC(smb_buffer_response)) {
2873 if(tcon->nativeFileSystem)
2874 kfree(tcon->nativeFileSystem);
2875 tcon->nativeFileSystem =
2876 cifs_kcalloc(length + 2, GFP_KERNEL);
2877 cifs_strfromUCS_le(tcon->nativeFileSystem,
2878 (wchar_t *) bcc_ptr,
2879 length, nls_codepage);
2880 bcc_ptr += 2 * length;
2881 bcc_ptr[0] = 0; /* null terminate the string */
2885 /* else do not bother copying these informational fields */
2887 length = strnlen(bcc_ptr, 1024);
2888 if ((bcc_ptr + length) -
2889 pByteArea(smb_buffer_response) <=
2890 BCC(smb_buffer_response)) {
2891 if(tcon->nativeFileSystem)
2892 kfree(tcon->nativeFileSystem);
2893 tcon->nativeFileSystem =
2894 cifs_kcalloc(length + 1, GFP_KERNEL);
2895 strncpy(tcon->nativeFileSystem, bcc_ptr,
2898 /* else do not bother copying these informational fields */
2900 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2901 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2902 } else if ((rc == 0) && tcon == NULL) {
2903 /* all we need to save for IPC$ connection */
2904 ses->ipc_tid = smb_buffer_response->Tid;
2908 cifs_buf_release(smb_buffer);
2913 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
2917 struct cifsSesInfo *ses = NULL;
2918 struct task_struct *cifsd_task;
2922 if (cifs_sb->tcon) {
2923 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
2924 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
2929 tconInfoFree(cifs_sb->tcon);
2930 if ((ses) && (ses->server)) {
2931 /* save off task so we do not refer to ses later */
2932 cifsd_task = ses->server->tsk;
2933 cFYI(1, ("About to do SMBLogoff "));
2934 rc = CIFSSMBLogoff(xid, ses);
2938 } else if (rc == -ESHUTDOWN) {
2939 cFYI(1,("Waking up socket by sending it signal"));
2940 send_sig(SIGKILL,cifsd_task,1);
2942 } /* else - we have an smb session
2943 left on this socket do not kill cifsd */
2945 cFYI(1, ("No session or bad tcon"));
2948 cifs_sb->tcon = NULL;
2950 set_current_state(TASK_INTERRUPTIBLE);
2951 schedule_timeout(HZ / 2);
2957 return rc; /* BB check if we should always return zero here */
2960 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2961 struct nls_table * nls_info)
2964 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
2965 int ntlmv2_flag = FALSE;
2967 /* what if server changes its buffer size after dropping the session? */
2968 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
2969 rc = CIFSSMBNegotiate(xid, pSesInfo);
2970 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
2971 rc = CIFSSMBNegotiate(xid, pSesInfo);
2976 spin_lock(&GlobalMid_Lock);
2977 if(pSesInfo->server->tcpStatus != CifsExiting)
2978 pSesInfo->server->tcpStatus = CifsGood;
2981 spin_unlock(&GlobalMid_Lock);
2986 pSesInfo->capabilities = pSesInfo->server->capabilities;
2987 if(linuxExtEnabled == 0)
2988 pSesInfo->capabilities &= (~CAP_UNIX);
2989 pSesInfo->sequence_number = 0;
2990 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2991 pSesInfo->server->secMode,
2992 pSesInfo->server->capabilities,
2993 pSesInfo->server->timeZone));
2994 if (extended_security
2995 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
2996 && (pSesInfo->server->secType == NTLMSSP)) {
2997 cFYI(1, ("New style sesssetup "));
2998 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
2999 NULL /* security blob */,
3000 0 /* blob length */,
3002 } else if (extended_security
3003 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3004 && (pSesInfo->server->secType == RawNTLMSSP)) {
3005 cFYI(1, ("NTLMSSP sesssetup "));
3006 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3013 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3014 CalcNTLMv2_partial_mac_key(pSesInfo,
3016 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3018 CalcNTLMv2_response(pSesInfo,v2_response);
3019 /* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
3021 /* BB Put dummy sig in SessSetup PDU? */
3026 SMBNTencrypt(pSesInfo->password,
3027 pSesInfo->server->cryptKey,
3030 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
3032 pSesInfo->password);
3034 /* for better security the weaker lanman hash not sent
3035 in AuthSessSetup so we no longer calculate it */
3037 rc = CIFSNTLMSSPAuthSessSetup(xid,
3043 } else { /* old style NTLM 0.12 session setup */
3044 SMBNTencrypt(pSesInfo->password,
3045 pSesInfo->server->cryptKey,
3048 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
3049 ntlm_session_key, pSesInfo->password);
3050 rc = CIFSSessSetup(xid, pSesInfo,
3051 ntlm_session_key, nls_info);
3054 cERROR(1,("Send error in SessSetup = %d",rc));
3056 cFYI(1,("CIFS Session Established successfully"));
3057 pSesInfo->status = CifsGood;