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 *in6_addr; /* ipv6 address as human readable form of in6_addr */
62 char *iocharset; /* local code page for mapping to and from Unicode */
63 char source_rfc1001_name[16]; /* netbios name of client */
73 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
74 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
79 unsigned short int port;
82 static int ipv4_connect(struct sockaddr_in *psin_server,
83 struct socket **csocket,
85 static int ipv6_connect(struct sockaddr_in6 *psin_server,
86 struct socket **csocket);
90 * cifs tcp session reconnection
92 * mark tcp session as reconnecting so temporarily locked
93 * mark all smb sessions as reconnecting for tcp session
94 * reconnect tcp session
95 * wake up waiters on reconnection? - (not needed currently)
99 cifs_reconnect(struct TCP_Server_Info *server)
102 struct list_head *tmp;
103 struct cifsSesInfo *ses;
104 struct cifsTconInfo *tcon;
105 struct mid_q_entry * mid_entry;
107 spin_lock(&GlobalMid_Lock);
108 if(server->tcpStatus == CifsExiting) {
109 /* the demux thread will exit normally
110 next time through the loop */
111 spin_unlock(&GlobalMid_Lock);
114 server->tcpStatus = CifsNeedReconnect;
115 spin_unlock(&GlobalMid_Lock);
118 cFYI(1, ("Reconnecting tcp session "));
120 /* before reconnecting the tcp session, mark the smb session (uid)
121 and the tid bad so they are not used until reconnected */
122 read_lock(&GlobalSMBSeslock);
123 list_for_each(tmp, &GlobalSMBSessionList) {
124 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
126 if (ses->server == server) {
127 ses->status = CifsNeedReconnect;
131 /* else tcp and smb sessions need reconnection */
133 list_for_each(tmp, &GlobalTreeConnectionList) {
134 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
135 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
136 tcon->tidStatus = CifsNeedReconnect;
139 read_unlock(&GlobalSMBSeslock);
140 /* do not want to be sending data on a socket we are freeing */
141 down(&server->tcpSem);
142 if(server->ssocket) {
143 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
144 server->ssocket->flags));
145 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
146 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
147 server->ssocket->flags));
148 sock_release(server->ssocket);
149 server->ssocket = NULL;
152 spin_lock(&GlobalMid_Lock);
153 list_for_each(tmp, &server->pending_mid_q) {
154 mid_entry = list_entry(tmp, struct
158 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
159 /* Mark other intransit requests as needing retry so
160 we do not immediately mark the session bad again
161 (ie after we reconnect below) as they timeout too */
162 mid_entry->midState = MID_RETRY_NEEDED;
166 spin_unlock(&GlobalMid_Lock);
169 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
171 if(server->protocolType == IPV6) {
172 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
174 rc = ipv4_connect(&server->addr.sockAddr,
176 server->workstation_RFC1001_name);
179 set_current_state(TASK_INTERRUPTIBLE);
180 schedule_timeout(3 * HZ);
182 atomic_inc(&tcpSesReconnectCount);
183 spin_lock(&GlobalMid_Lock);
184 if(server->tcpStatus != CifsExiting)
185 server->tcpStatus = CifsGood;
186 spin_unlock(&GlobalMid_Lock);
187 /* atomic_set(&server->inFlight,0);*/
188 wake_up(&server->response_q);
195 cifs_demultiplex_thread(struct TCP_Server_Info *server)
198 unsigned int pdu_length, total_read;
199 struct smb_hdr *smb_buffer = NULL;
200 struct msghdr smb_msg;
202 struct socket *csocket = server->ssocket;
203 struct list_head *tmp;
204 struct cifsSesInfo *ses;
205 struct task_struct *task_to_wake = NULL;
206 struct mid_q_entry *mid_entry;
210 allow_signal(SIGKILL);
211 current->flags |= PF_MEMALLOC;
212 server->tsk = current; /* save process info to wake at shutdown */
213 cFYI(1, ("Demultiplex PID: %d", current->pid));
214 write_lock(&GlobalSMBSeslock);
215 atomic_inc(&tcpSesAllocCount);
216 length = tcpSesAllocCount.counter;
217 write_unlock(&GlobalSMBSeslock);
219 mempool_resize(cifs_req_poolp,
220 length + cifs_min_rcv,
224 while (server->tcpStatus != CifsExiting) {
225 if (smb_buffer == NULL)
226 smb_buffer = cifs_buf_get();
228 memset(smb_buffer, 0, sizeof (struct smb_hdr));
230 if (smb_buffer == NULL) {
231 cERROR(1,("Can not get memory for SMB response"));
232 set_current_state(TASK_INTERRUPTIBLE);
233 schedule_timeout(HZ * 3); /* give system time to free memory */
236 iov.iov_base = smb_buffer;
237 iov.iov_len = sizeof (struct smb_hdr) - 1;
238 /* 1 byte less above since wct is not always returned in error cases */
239 smb_msg.msg_control = NULL;
240 smb_msg.msg_controllen = 0;
243 kernel_recvmsg(csocket, &smb_msg,
245 sizeof (struct smb_hdr) -
246 1 /* RFC1001 header and SMB header */ ,
247 MSG_PEEK /* flags see socket.h */ );
249 if(server->tcpStatus == CifsExiting) {
251 } else if (server->tcpStatus == CifsNeedReconnect) {
252 cFYI(1,("Reconnecting after server stopped responding"));
253 cifs_reconnect(server);
254 cFYI(1,("call to reconnect done"));
255 csocket = server->ssocket;
257 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)
258 || ((length > 0) && (length <= 3)) ) {
259 set_current_state(TASK_INTERRUPTIBLE);
260 schedule_timeout(1); /* minimum sleep to prevent looping
261 allowing socket to clear and app threads to set
262 tcpStatus CifsNeedReconnect if server hung */
264 } else if (length <= 0) {
265 if(server->tcpStatus == CifsNew) {
266 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
267 /* some servers kill tcp session rather than returning
268 smb negprot error in which case reconnecting here is
269 not going to help - return error to mount */
272 if(length == -EINTR) {
273 cFYI(1,("cifsd thread killed"));
276 cFYI(1,("Reconnecting after unexpected peek error %d",length));
277 cifs_reconnect(server);
278 csocket = server->ssocket;
279 wake_up(&server->response_q);
283 pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
284 /* Only read pdu_length after below checks for too short (due
285 to e.g. int overflow) and too long ie beyond end of buf */
286 cFYI(1, ("Peek length rcvd: 0x%x beginning 0x%x)", length, pdu_length));
288 temp = (char *) smb_buffer;
290 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
291 iov.iov_base = smb_buffer;
293 length = kernel_recvmsg(csocket, &smb_msg,
295 cFYI(0,("Received 4 byte keep alive packet"));
296 } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
297 iov.iov_base = smb_buffer;
299 length = kernel_recvmsg(csocket, &smb_msg,
301 cFYI(1,("Good RFC 1002 session rsp"));
302 } else if ((temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE)
304 /* we get this from Windows 98 instead of error on SMB negprot response */
305 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
306 if(server->tcpStatus == CifsNew) {
307 /* if nack on negprot (rather than
308 ret of smb negprot error) reconnecting
309 not going to help, ret error to mount */
312 /* give server a second to
313 clean up before reconnect attempt */
314 set_current_state(TASK_INTERRUPTIBLE);
315 schedule_timeout(HZ);
316 /* always try 445 first on reconnect
317 since we get NACK on some if we ever
318 connected to port 139 (the NACK is
319 since we do not begin with RFC1001
320 session initialize frame) */
321 server->addr.sockAddr.sin_port = htons(CIFS_PORT);
322 cifs_reconnect(server);
323 csocket = server->ssocket;
324 wake_up(&server->response_q);
327 } else if (temp[0] != (char) 0) {
328 cERROR(1,("Unknown RFC 1002 frame"));
329 cifs_dump_mem(" Received Data: ", temp, length);
330 cifs_reconnect(server);
331 csocket = server->ssocket;
335 /* We can not validate the SMB unless
336 at least this much of SMB available
337 so give the socket time to copy
338 a few more bytes and retry */
339 set_current_state(TASK_INTERRUPTIBLE);
340 schedule_timeout(10);
342 } else if( (pdu_length >
343 CIFSMaxBufSize + MAX_CIFS_HDR_SIZE)
345 sizeof (struct smb_hdr) - 1)
347 (smb_buffer, smb_buffer->Mid))) {
349 ("Invalid size or format for SMB found with length %d and pdu_length %d",
350 length, pdu_length));
351 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)+3);
352 /* could we fix this network corruption by finding next
353 smb header (instead of killing the session) and
354 restart reading from next valid SMB found? */
355 cifs_reconnect(server);
356 csocket = server->ssocket;
358 } else { /* length ok */
361 iov.iov_base = smb_buffer;
362 iov.iov_len = pdu_length;
364 total_read < pdu_length;
365 total_read += length) {
366 length = kernel_recvmsg(csocket, &smb_msg,
368 pdu_length - total_read, 0);
371 ("Zero length receive when expecting %d ",
372 pdu_length - total_read));
373 cifs_reconnect(server);
374 csocket = server->ssocket;
380 dump_smb(smb_buffer, length);
382 (smb_buffer, smb_buffer->Mid, total_read)) {
383 cERROR(1, ("Bad SMB Received "));
388 spin_lock(&GlobalMid_Lock);
389 list_for_each(tmp, &server->pending_mid_q) {
390 mid_entry = list_entry(tmp, struct
394 if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
396 (" Mid 0x%x matched - waking up ",mid_entry->mid));
397 task_to_wake = mid_entry->tsk;
398 mid_entry->resp_buf =
400 mid_entry->midState =
401 MID_RESPONSE_RECEIVED;
404 spin_unlock(&GlobalMid_Lock);
406 smb_buffer = NULL; /* will be freed by users thread after he is done */
407 wake_up_process(task_to_wake);
408 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
409 cERROR(1, ("No task to wake, unknown frame rcvd!"));
410 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
415 ("Frame less than four bytes received %d bytes long.",
418 length = kernel_recvmsg(csocket, &smb_msg,
420 length, 0); /* throw away junk frame */
422 (" with junk 0x%x in it ",
423 *(__u32 *) smb_buffer));
427 spin_lock(&GlobalMid_Lock);
428 server->tcpStatus = CifsExiting;
430 atomic_set(&server->inFlight, 0);
431 spin_unlock(&GlobalMid_Lock);
432 /* Although there should not be any requests blocked on
433 this queue it can not hurt to be paranoid and try to wake up requests
434 that may haven been blocked when more than 50 at time were on the wire
435 to the same server - they now will see the session is in exit state
436 and get out of SendReceive. */
437 wake_up_all(&server->request_q);
438 /* give those requests time to exit */
439 set_current_state(TASK_INTERRUPTIBLE);
440 schedule_timeout(HZ/8);
442 if(server->ssocket) {
443 sock_release(csocket);
444 server->ssocket = NULL;
446 if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
447 cifs_buf_release(smb_buffer);
449 read_lock(&GlobalSMBSeslock);
450 if (list_empty(&server->pending_mid_q)) {
451 /* loop through server session structures attached to this and mark them dead */
452 list_for_each(tmp, &GlobalSMBSessionList) {
454 list_entry(tmp, struct cifsSesInfo,
456 if (ses->server == server) {
457 ses->status = CifsExiting;
461 read_unlock(&GlobalSMBSeslock);
463 spin_lock(&GlobalMid_Lock);
464 list_for_each(tmp, &server->pending_mid_q) {
465 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
466 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
468 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
469 task_to_wake = mid_entry->tsk;
471 wake_up_process(task_to_wake);
475 spin_unlock(&GlobalMid_Lock);
476 read_unlock(&GlobalSMBSeslock);
477 set_current_state(TASK_INTERRUPTIBLE);
478 /* 1/8th of sec is more than enough time for them to exit */
479 schedule_timeout(HZ/8);
482 if (list_empty(&server->pending_mid_q)) {
483 /* mpx threads have not exited yet give them
484 at least the smb send timeout time for long ops */
485 cFYI(1, ("Wait for exit from demultiplex thread"));
486 set_current_state(TASK_INTERRUPTIBLE);
487 schedule_timeout(46 * HZ);
488 /* if threads still have not exited they are probably never
489 coming home not much else we can do but free the memory */
493 write_lock(&GlobalSMBSeslock);
494 atomic_dec(&tcpSesAllocCount);
495 length = tcpSesAllocCount.counter;
496 write_unlock(&GlobalSMBSeslock);
498 mempool_resize(cifs_req_poolp,
499 length + cifs_min_rcv,
503 set_current_state(TASK_INTERRUPTIBLE);
504 schedule_timeout(HZ/4);
509 cifs_kcalloc(size_t size, int type)
512 addr = kmalloc(size, type);
514 memset(addr, 0, size);
519 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
523 unsigned int temp_len, i, j;
529 memset(vol->source_rfc1001_name,0x20,15);
530 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
531 /* does not have to be a perfect mapping since the field is
532 informational, only used for servers that do not support
533 port 445 and it can be overridden at mount time */
534 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
536 vol->source_rfc1001_name[15] = 0;
538 vol->linux_uid = current->uid; /* current->euid instead? */
539 vol->linux_gid = current->gid;
540 vol->dir_mode = S_IRWXUGO;
541 /* 2767 perms indicate mandatory locking support */
542 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
544 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
550 if(strncmp(options,"sep=",4) == 0) {
551 if(options[4] != 0) {
552 separator[0] = options[4];
555 cFYI(1,("Null separator not allowed"));
559 while ((data = strsep(&options, separator)) != NULL) {
562 if ((value = strchr(data, '=')) != NULL)
564 if (strnicmp(data, "user", 4) == 0) {
565 if (!value || !*value) {
567 "CIFS: invalid or missing username\n");
568 return 1; /* needs_arg; */
570 if (strnlen(value, 200) < 200) {
571 vol->username = value;
573 printk(KERN_WARNING "CIFS: username too long\n");
576 } else if (strnicmp(data, "pass", 4) == 0) {
577 if (!value || !*value) {
578 vol->password = NULL;
581 temp_len = strlen(value);
582 /* removed password length check, NTLM passwords
583 can be arbitrarily long */
585 /* if comma in password, the string will be
586 prematurely null terminated. Commas in password are
587 specified across the cifs mount interface by a double
588 comma ie ,, and a comma used as in other cases ie ','
589 as a parameter delimiter/separator is single and due
590 to the strsep above is temporarily zeroed. */
592 /* NB: password legally can have multiple commas and
593 the only illegal character in a password is null */
595 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
597 value[temp_len] = separator[0];
598 temp_len+=2; /* move after the second comma */
599 while(value[temp_len] != 0) {
600 if((value[temp_len] == separator[0]) && (value[temp_len+1] != separator[0])) {
601 /* single comma indicating start of next parm */
606 if(value[temp_len] == 0) {
610 /* move options to point to start of next parm */
611 options = value + temp_len + 1;
613 /* go from value to (value + temp_len) condensing double commas to singles */
614 vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
615 for(i=0,j=0;i<temp_len;i++,j++) {
616 vol->password[j] = value[i];
617 if(value[i] == separator[0] && value[i+1] == separator[0]) {
618 /* skip second comma */
622 /* value[temp_len] is zeroed above so
623 vol->password[temp_len] guaranteed to be null */
625 vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
626 strcpy(vol->password, value);
628 } else if (strnicmp(data, "ip", 2) == 0) {
629 if (!value || !*value) {
631 } else if (strnlen(value, 35) < 35) {
634 printk(KERN_WARNING "CIFS: ip address too long\n");
637 } else if ((strnicmp(data, "unc", 3) == 0)
638 || (strnicmp(data, "target", 6) == 0)
639 || (strnicmp(data, "path", 4) == 0)) {
640 if (!value || !*value) {
642 "CIFS: invalid path to network resource\n");
643 return 1; /* needs_arg; */
645 if ((temp_len = strnlen(value, 300)) < 300) {
646 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
649 strcpy(vol->UNC,value);
650 if (strncmp(vol->UNC, "//", 2) == 0) {
653 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
655 "CIFS: UNC Path does not begin with // or \\\\ \n");
659 printk(KERN_WARNING "CIFS: UNC name too long\n");
662 } else if ((strnicmp(data, "domain", 3) == 0)
663 || (strnicmp(data, "workgroup", 5) == 0)) {
664 if (!value || !*value) {
665 printk(KERN_WARNING "CIFS: invalid domain name\n");
666 return 1; /* needs_arg; */
668 /* BB are there cases in which a comma can be valid in
669 a domain name and need special handling? */
670 if (strnlen(value, 65) < 65) {
671 vol->domainname = value;
672 cFYI(1, ("Domain name set"));
674 printk(KERN_WARNING "CIFS: domain name too long\n");
677 } else if (strnicmp(data, "iocharset", 9) == 0) {
678 if (!value || !*value) {
679 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
680 return 1; /* needs_arg; */
682 if (strnlen(value, 65) < 65) {
683 if(strnicmp(value,"default",7))
684 vol->iocharset = value;
685 /* if iocharset not set load_nls_default used by caller */
686 cFYI(1, ("iocharset set to %s",value));
688 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
691 } else if (strnicmp(data, "uid", 3) == 0) {
692 if (value && *value) {
694 simple_strtoul(value, &value, 0);
696 } else if (strnicmp(data, "gid", 3) == 0) {
697 if (value && *value) {
699 simple_strtoul(value, &value, 0);
701 } else if (strnicmp(data, "file_mode", 4) == 0) {
702 if (value && *value) {
704 simple_strtoul(value, &value, 0);
706 } else if (strnicmp(data, "dir_mode", 4) == 0) {
707 if (value && *value) {
709 simple_strtoul(value, &value, 0);
711 } else if (strnicmp(data, "dirmode", 4) == 0) {
712 if (value && *value) {
714 simple_strtoul(value, &value, 0);
716 } else if (strnicmp(data, "port", 4) == 0) {
717 if (value && *value) {
719 simple_strtoul(value, &value, 0);
721 } else if (strnicmp(data, "rsize", 5) == 0) {
722 if (value && *value) {
724 simple_strtoul(value, &value, 0);
726 } else if (strnicmp(data, "wsize", 5) == 0) {
727 if (value && *value) {
729 simple_strtoul(value, &value, 0);
731 } else if (strnicmp(data, "sockopt", 5) == 0) {
732 if (value && *value) {
734 simple_strtoul(value, &value, 0);
736 } else if (strnicmp(data, "netbiosname", 4) == 0) {
737 if (!value || !*value || (*value == ' ')) {
738 cFYI(1,("invalid (empty) netbiosname specified"));
740 memset(vol->source_rfc1001_name,0x20,15);
742 /* BB are there cases in which a comma can be
743 valid in this workstation netbios name (and need
744 special handling)? */
746 /* We do not uppercase netbiosname for user */
750 vol->source_rfc1001_name[i] = value[i];
752 /* The string has 16th byte zero still from
753 set at top of the function */
754 if((i==15) && (value[i] != 0))
755 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
757 } else if (strnicmp(data, "credentials", 4) == 0) {
759 } else if (strnicmp(data, "version", 3) == 0) {
761 } else if (strnicmp(data, "guest",5) == 0) {
763 } else if (strnicmp(data, "rw", 2) == 0) {
765 } else if ((strnicmp(data, "suid", 4) == 0) ||
766 (strnicmp(data, "nosuid", 6) == 0) ||
767 (strnicmp(data, "exec", 4) == 0) ||
768 (strnicmp(data, "noexec", 6) == 0) ||
769 (strnicmp(data, "nodev", 5) == 0) ||
770 (strnicmp(data, "noauto", 6) == 0) ||
771 (strnicmp(data, "dev", 3) == 0)) {
772 /* The mount tool or mount.cifs helper (if present)
773 uses these opts to set flags, and the flags are read
774 by the kernel vfs layer before we get here (ie
775 before read super) so there is no point trying to
776 parse these options again and set anything and it
777 is ok to just ignore them */
779 } else if (strnicmp(data, "ro", 2) == 0) {
781 } else if (strnicmp(data, "hard", 4) == 0) {
783 } else if (strnicmp(data, "soft", 4) == 0) {
785 } else if (strnicmp(data, "perm", 4) == 0) {
787 } else if (strnicmp(data, "noperm", 6) == 0) {
789 } else if (strnicmp(data, "setuids", 7) == 0) {
791 } else if (strnicmp(data, "nosetuids", 9) == 0) {
793 } else if (strnicmp(data, "nohard", 6) == 0) {
795 } else if (strnicmp(data, "nosoft", 6) == 0) {
797 } else if (strnicmp(data, "nointr", 6) == 0) {
799 } else if (strnicmp(data, "intr", 4) == 0) {
801 } else if (strnicmp(data, "serverino",7) == 0) {
803 } else if (strnicmp(data, "noserverino",9) == 0) {
805 } else if (strnicmp(data, "acl",3) == 0) {
807 } else if (strnicmp(data, "noacl",5) == 0) {
809 } else if (strnicmp(data, "direct",6) == 0) {
811 } else if (strnicmp(data, "forcedirectio",13) == 0) {
813 } else if (strnicmp(data, "in6_addr",8) == 0) {
814 if (!value || !*value) {
815 vol->in6_addr = NULL;
816 } else if (strnlen(value, 49) == 48) {
817 vol->in6_addr = value;
819 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
822 } else if (strnicmp(data, "noac", 4) == 0) {
823 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
825 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
827 if (vol->UNC == NULL) {
828 if(devname == NULL) {
829 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
832 if ((temp_len = strnlen(devname, 300)) < 300) {
833 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
836 strcpy(vol->UNC,devname);
837 if (strncmp(vol->UNC, "//", 2) == 0) {
840 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
841 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
845 printk(KERN_WARNING "CIFS: UNC name too long\n");
850 vol->UNCip = &vol->UNC[2];
855 static struct cifsSesInfo *
856 cifs_find_tcp_session(struct in_addr * target_ip_addr,
857 struct in6_addr *target_ip6_addr,
858 char *userName, struct TCP_Server_Info **psrvTcp)
860 struct list_head *tmp;
861 struct cifsSesInfo *ses;
863 read_lock(&GlobalSMBSeslock);
865 list_for_each(tmp, &GlobalSMBSessionList) {
866 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
868 if((target_ip_addr &&
869 (ses->server->addr.sockAddr.sin_addr.s_addr
870 == target_ip_addr->s_addr)) || (target_ip6_addr
871 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
872 target_ip6_addr,sizeof(*target_ip6_addr)))){
873 /* BB lock server and tcp session and increment use count here?? */
874 *psrvTcp = ses->server; /* found a match on the TCP session */
875 /* BB check if reconnection needed */
877 (ses->userName, userName,
878 MAX_USERNAME_SIZE) == 0){
879 read_unlock(&GlobalSMBSeslock);
880 return ses; /* found exact match on both tcp and SMB sessions */
884 /* else tcp and smb sessions need reconnection */
886 read_unlock(&GlobalSMBSeslock);
890 static struct cifsTconInfo *
891 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
893 struct list_head *tmp;
894 struct cifsTconInfo *tcon;
896 read_lock(&GlobalSMBSeslock);
897 list_for_each(tmp, &GlobalTreeConnectionList) {
898 cFYI(1, ("Next tcon - "));
899 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
901 if (tcon->ses->server) {
903 (" old ip addr: %x == new ip %x ?",
904 tcon->ses->server->addr.sockAddr.sin_addr.
905 s_addr, new_target_ip_addr));
906 if (tcon->ses->server->addr.sockAddr.sin_addr.
907 s_addr == new_target_ip_addr) {
908 /* BB lock tcon and server and tcp session and increment use count here? */
909 /* found a match on the TCP session */
910 /* BB check if reconnection needed */
911 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
912 tcon->treeName, uncName));
914 (tcon->treeName, uncName,
915 MAX_TREE_SIZE) == 0) {
917 ("Matched UNC, old user: %s == new: %s ?",
918 tcon->treeName, uncName));
920 (tcon->ses->userName,
922 MAX_USERNAME_SIZE) == 0) {
923 read_unlock(&GlobalSMBSeslock);
924 return tcon;/* also matched user (smb session)*/
931 read_unlock(&GlobalSMBSeslock);
936 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
937 const char *old_path, const struct nls_table *nls_codepage)
939 unsigned char *referrals = NULL;
940 unsigned int num_referrals;
943 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
944 &num_referrals, &referrals);
946 /* BB Add in code to: if valid refrl, if not ip address contact
947 the helper that resolves tcp names, mount to it, try to
948 tcon to it unmount it if fail */
957 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
958 const char *old_path, const struct nls_table *nls_codepage,
959 unsigned int *pnum_referrals, unsigned char ** preferrals)
966 if (pSesInfo->ipc_tid == 0) {
967 temp_unc = kmalloc(2 /* for slashes */ +
968 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
969 + 1 + 4 /* slash IPC$ */ + 2,
971 if (temp_unc == NULL)
975 strcpy(temp_unc + 2, pSesInfo->serverName);
976 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
977 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
979 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
983 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
984 pnum_referrals, nls_codepage);
989 /* See RFC1001 section 14 on representation of Netbios names */
990 static void rfc1002mangle(char * target,char * source, unsigned int length)
994 for(i=0,j=0;i<(length);i++) {
995 /* mask a nibble at a time and encode */
996 target[j] = 'A' + (0x0F & (source[i] >> 4));
997 target[j+1] = 'A' + (0x0F & source[i]);
1005 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1006 char * netbios_name)
1010 __be16 orig_port = 0;
1012 if(*csocket == NULL) {
1013 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1015 cERROR(1, ("Error %d creating socket",rc));
1019 /* BB other socket options to set KEEPALIVE, NODELAY? */
1020 cFYI(1,("Socket created"));
1021 (*csocket)->sk->sk_allocation = GFP_NOFS;
1025 psin_server->sin_family = AF_INET;
1026 if(psin_server->sin_port) { /* user overrode default port */
1027 rc = (*csocket)->ops->connect(*csocket,
1028 (struct sockaddr *) psin_server,
1029 sizeof (struct sockaddr_in),0);
1035 /* save original port so we can retry user specified port
1036 later if fall back ports fail this time */
1037 orig_port = psin_server->sin_port;
1039 /* do not retry on the same port we just failed on */
1040 if(psin_server->sin_port != htons(CIFS_PORT)) {
1041 psin_server->sin_port = htons(CIFS_PORT);
1043 rc = (*csocket)->ops->connect(*csocket,
1044 (struct sockaddr *) psin_server,
1045 sizeof (struct sockaddr_in),0);
1051 psin_server->sin_port = htons(RFC1001_PORT);
1052 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1053 psin_server, sizeof (struct sockaddr_in),0);
1058 /* give up here - unless we want to retry on different
1059 protocol families some day */
1062 psin_server->sin_port = orig_port;
1063 cFYI(1,("Error %d connecting to server via ipv4",rc));
1064 sock_release(*csocket);
1068 /* Eventually check for other socket options to change from
1069 the default. sock_setsockopt not used because it expects
1070 user space buffer */
1071 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1073 /* send RFC1001 sessinit */
1075 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1076 /* some servers require RFC1001 sessinit before sending
1077 negprot - BB check reconnection in case where second
1078 sessinit is sent but no second negprot */
1079 struct rfc1002_session_packet * ses_init_buf;
1080 struct smb_hdr * smb_buf;
1081 ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1083 ses_init_buf->trailer.session_req.called_len = 32;
1084 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1085 DEFAULT_CIFS_CALLED_NAME,16);
1086 ses_init_buf->trailer.session_req.calling_len = 32;
1087 /* calling name ends in null (byte 16) from old smb
1089 if(netbios_name && (netbios_name[0] !=0)) {
1090 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1093 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1094 "LINUX_CIFS_CLNT",16);
1096 ses_init_buf->trailer.session_req.scope1 = 0;
1097 ses_init_buf->trailer.session_req.scope2 = 0;
1098 smb_buf = (struct smb_hdr *)ses_init_buf;
1099 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1100 smb_buf->smb_buf_length = 0x81000044;
1101 rc = smb_send(*csocket, smb_buf, 0x44,
1102 (struct sockaddr *)psin_server);
1103 kfree(ses_init_buf);
1105 /* else the negprot may still work without this
1106 even though malloc failed */
1114 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1118 __be16 orig_port = 0;
1120 if(*csocket == NULL) {
1121 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1123 cERROR(1, ("Error %d creating ipv6 socket",rc));
1127 /* BB other socket options to set KEEPALIVE, NODELAY? */
1128 cFYI(1,("ipv6 Socket created"));
1129 (*csocket)->sk->sk_allocation = GFP_NOFS;
1133 psin_server->sin6_family = AF_INET6;
1135 if(psin_server->sin6_port) { /* user overrode default port */
1136 rc = (*csocket)->ops->connect(*csocket,
1137 (struct sockaddr *) psin_server,
1138 sizeof (struct sockaddr_in6),0);
1144 /* save original port so we can retry user specified port
1145 later if fall back ports fail this time */
1147 orig_port = psin_server->sin6_port;
1148 /* do not retry on the same port we just failed on */
1149 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1150 psin_server->sin6_port = htons(CIFS_PORT);
1152 rc = (*csocket)->ops->connect(*csocket,
1153 (struct sockaddr *) psin_server,
1154 sizeof (struct sockaddr_in6),0);
1160 psin_server->sin6_port = htons(RFC1001_PORT);
1161 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1162 psin_server, sizeof (struct sockaddr_in6),0);
1167 /* give up here - unless we want to retry on different
1168 protocol families some day */
1171 psin_server->sin6_port = orig_port;
1172 cFYI(1,("Error %d connecting to server via ipv6",rc));
1173 sock_release(*csocket);
1177 /* Eventually check for other socket options to change from
1178 the default. sock_setsockopt not used because it expects
1179 user space buffer */
1180 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1186 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1187 char *mount_data, const char *devname)
1191 int address_type = AF_INET;
1192 struct socket *csocket = NULL;
1193 struct sockaddr_in sin_server;
1194 struct sockaddr_in6 sin_server6;
1195 struct smb_vol volume_info;
1196 struct cifsSesInfo *pSesInfo = NULL;
1197 struct cifsSesInfo *existingCifsSes = NULL;
1198 struct cifsTconInfo *tcon = NULL;
1199 struct TCP_Server_Info *srvTcp = NULL;
1203 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1205 memset(&volume_info,0,sizeof(struct smb_vol));
1206 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1208 kfree(volume_info.UNC);
1209 if(volume_info.password)
1210 kfree(volume_info.password);
1215 if (volume_info.username) {
1216 cFYI(1, ("Username: %s ", volume_info.username));
1219 cifserror("No username specified ");
1220 /* In userspace mount helper we can get user name from alternate
1221 locations such as env variables and files on disk */
1223 kfree(volume_info.UNC);
1224 if(volume_info.password)
1225 kfree(volume_info.password);
1230 if (volume_info.UNCip && volume_info.UNC) {
1231 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1234 /* not ipv4 address, try ipv6 */
1235 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1237 address_type = AF_INET6;
1239 address_type = AF_INET;
1243 /* we failed translating address */
1245 kfree(volume_info.UNC);
1246 if(volume_info.password)
1247 kfree(volume_info.password);
1252 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1255 } else if (volume_info.UNCip){
1256 /* BB using ip addr as server name connect to the DFS root below */
1257 cERROR(1,("Connecting to DFS root not implemented yet"));
1259 kfree(volume_info.UNC);
1260 if(volume_info.password)
1261 kfree(volume_info.password);
1264 } else /* which servers DFS root would we conect to */ {
1266 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1268 kfree(volume_info.UNC);
1269 if(volume_info.password)
1270 kfree(volume_info.password);
1275 /* this is needed for ASCII cp to Unicode converts */
1276 if(volume_info.iocharset == NULL) {
1277 cifs_sb->local_nls = load_nls_default();
1278 /* load_nls_default can not return null */
1280 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1281 if(cifs_sb->local_nls == NULL) {
1282 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1284 kfree(volume_info.UNC);
1285 if(volume_info.password)
1286 kfree(volume_info.password);
1292 if(address_type == AF_INET)
1293 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1294 NULL /* no ipv6 addr */,
1295 volume_info.username, &srvTcp);
1296 else if(address_type == AF_INET6)
1297 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1298 &sin_server6.sin6_addr,
1299 volume_info.username, &srvTcp);
1302 kfree(volume_info.UNC);
1303 if(volume_info.password)
1304 kfree(volume_info.password);
1311 cFYI(1, ("Existing tcp session with server found "));
1312 } else { /* create socket */
1313 if(volume_info.port)
1314 sin_server.sin_port = htons(volume_info.port);
1316 sin_server.sin_port = 0;
1317 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1320 ("Error connecting to IPv4 socket. Aborting operation"));
1322 sock_release(csocket);
1324 kfree(volume_info.UNC);
1325 if(volume_info.password)
1326 kfree(volume_info.password);
1331 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1332 if (srvTcp == NULL) {
1334 sock_release(csocket);
1336 kfree(volume_info.UNC);
1337 if(volume_info.password)
1338 kfree(volume_info.password);
1342 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1343 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1344 atomic_set(&srvTcp->inFlight,0);
1345 /* BB Add code for ipv6 case too */
1346 srvTcp->ssocket = csocket;
1347 srvTcp->protocolType = IPV4;
1348 init_waitqueue_head(&srvTcp->response_q);
1349 init_waitqueue_head(&srvTcp->request_q);
1350 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1351 /* at this point we are the only ones with the pointer
1352 to the struct since the kernel thread not created yet
1353 so no need to spinlock this init of tcpStatus */
1354 srvTcp->tcpStatus = CifsNew;
1355 init_MUTEX(&srvTcp->tcpSem);
1356 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1357 CLONE_FS | CLONE_FILES | CLONE_VM);
1360 sock_release(csocket);
1362 kfree(volume_info.UNC);
1363 if(volume_info.password)
1364 kfree(volume_info.password);
1369 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1373 if (existingCifsSes) {
1374 pSesInfo = existingCifsSes;
1375 cFYI(1, ("Existing smb sess found "));
1376 if(volume_info.password)
1377 kfree(volume_info.password);
1378 /* volume_info.UNC freed at end of function */
1380 cFYI(1, ("Existing smb sess not found "));
1381 pSesInfo = sesInfoAlloc();
1382 if (pSesInfo == NULL)
1385 pSesInfo->server = srvTcp;
1386 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1387 NIPQUAD(sin_server.sin_addr.s_addr));
1391 /* volume_info.password freed at unmount */
1392 if (volume_info.password)
1393 pSesInfo->password = volume_info.password;
1394 if (volume_info.username)
1395 strncpy(pSesInfo->userName,
1396 volume_info.username,MAX_USERNAME_SIZE);
1397 if (volume_info.domainname)
1398 strncpy(pSesInfo->domainName,
1399 volume_info.domainname,MAX_USERNAME_SIZE);
1400 pSesInfo->linux_uid = volume_info.linux_uid;
1401 down(&pSesInfo->sesSem);
1402 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1403 up(&pSesInfo->sesSem);
1405 atomic_inc(&srvTcp->socketUseCount);
1407 if(volume_info.password)
1408 kfree(volume_info.password);
1411 /* search for existing tcon to this server share */
1413 if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
1414 cifs_sb->rsize = volume_info.rsize;
1416 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1417 if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf))
1418 cifs_sb->wsize = volume_info.wsize;
1420 cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1421 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1422 cifs_sb->rsize = PAGE_CACHE_SIZE;
1423 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1425 cifs_sb->mnt_uid = volume_info.linux_uid;
1426 cifs_sb->mnt_gid = volume_info.linux_gid;
1427 cifs_sb->mnt_file_mode = volume_info.file_mode;
1428 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1429 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1431 if(volume_info.noperm)
1432 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1433 if(volume_info.setuids)
1434 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1435 if(volume_info.server_ino)
1436 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1437 if(volume_info.direct_io) {
1438 cERROR(1,("mounting share using direct i/o"));
1439 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1443 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1444 volume_info.username);
1446 cFYI(1, ("Found match on UNC path "));
1447 /* we can have only one retry value for a connection
1448 to a share so for resources mounted more than once
1449 to the same server share the last value passed in
1450 for the retry flag is used */
1451 tcon->retry = volume_info.retry;
1453 tcon = tconInfoAlloc();
1457 /* check for null share name ie connect to dfs root */
1459 /* BB check if this works for exactly length three strings */
1460 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1461 && (strchr(volume_info.UNC + 3, '/') ==
1463 rc = connect_to_dfs_path(xid,
1469 kfree(volume_info.UNC);
1473 rc = CIFSTCon(xid, pSesInfo,
1475 tcon, cifs_sb->local_nls);
1476 cFYI(1, ("CIFS Tcon rc = %d", rc));
1479 atomic_inc(&pSesInfo->inUse);
1480 tcon->retry = volume_info.retry;
1486 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1487 sb->s_maxbytes = (u64) 1 << 63;
1489 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1492 /* on error free sesinfo and tcon struct if needed */
1494 /* if session setup failed, use count is zero but
1495 we still need to free cifsd thread */
1496 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1497 spin_lock(&GlobalMid_Lock);
1498 srvTcp->tcpStatus = CifsExiting;
1499 spin_unlock(&GlobalMid_Lock);
1501 send_sig(SIGKILL,srvTcp->tsk,1);
1503 /* If find_unc succeeded then rc == 0 so we can not end */
1504 if (tcon) /* up accidently freeing someone elses tcon struct */
1506 if (existingCifsSes == 0) {
1508 if ((pSesInfo->server) &&
1509 (pSesInfo->status == CifsGood)) {
1511 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1512 /* if the socketUseCount is now zero */
1513 if((temp_rc == -ESHUTDOWN) &&
1514 (pSesInfo->server->tsk))
1515 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1517 cFYI(1, ("No session or bad tcon"));
1518 sesInfoFree(pSesInfo);
1519 /* pSesInfo = NULL; */
1523 atomic_inc(&tcon->useCount);
1524 cifs_sb->tcon = tcon;
1525 tcon->ses = pSesInfo;
1527 /* do not care if following two calls succeed - informational only */
1528 CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
1529 CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
1530 if (tcon->ses->capabilities & CAP_UNIX) {
1531 if(!CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls)) {
1532 if(!volume_info.no_psx_acl) {
1533 if(CIFS_UNIX_POSIX_ACL_CAP &
1534 le64_to_cpu(tcon->fsUnixInfo.Capability))
1535 cFYI(1,("server negotiated posix acl support"));
1536 sb->s_flags |= MS_POSIXACL;
1542 /* volume_info.password is freed above when existing session found
1543 (in which case it is not needed anymore) but when new sesion is created
1544 the password ptr is put in the new session structure (in which case the
1545 password will be freed at unmount time) */
1547 kfree(volume_info.UNC);
1553 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1554 char session_key[CIFS_SESSION_KEY_SIZE],
1555 const struct nls_table *nls_codepage)
1557 struct smb_hdr *smb_buffer;
1558 struct smb_hdr *smb_buffer_response;
1559 SESSION_SETUP_ANDX *pSMB;
1560 SESSION_SETUP_ANDX *pSMBr;
1565 int remaining_words = 0;
1566 int bytes_returned = 0;
1571 cFYI(1, ("In sesssetup "));
1574 user = ses->userName;
1575 domain = ses->domainName;
1576 smb_buffer = cifs_buf_get();
1577 if (smb_buffer == 0) {
1580 smb_buffer_response = smb_buffer;
1581 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1583 /* send SMBsessionSetup here */
1584 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1585 NULL /* no tCon exists yet */ , 13 /* wct */ );
1587 pSMB->req_no_secext.AndXCommand = 0xFF;
1588 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1589 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1591 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1592 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1594 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS;
1595 if (ses->capabilities & CAP_UNICODE) {
1596 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1597 capabilities |= CAP_UNICODE;
1599 if (ses->capabilities & CAP_STATUS32) {
1600 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1601 capabilities |= CAP_STATUS32;
1603 if (ses->capabilities & CAP_DFS) {
1604 smb_buffer->Flags2 |= SMBFLG2_DFS;
1605 capabilities |= CAP_DFS;
1607 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1609 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1610 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1612 pSMB->req_no_secext.CaseSensitivePasswordLength =
1613 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1614 bcc_ptr = pByteArea(smb_buffer);
1615 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1616 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1617 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1618 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1620 if (ses->capabilities & CAP_UNICODE) {
1621 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1626 bytes_returned = 0; /* skill null user */
1629 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1631 bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
1632 bcc_ptr += 2; /* trailing null */
1635 cifs_strtoUCS((wchar_t *) bcc_ptr,
1636 "CIFS_LINUX_DOM", 32, nls_codepage);
1639 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1641 bcc_ptr += 2 * bytes_returned;
1644 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1646 bcc_ptr += 2 * bytes_returned;
1648 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
1650 bcc_ptr += 2 * bytes_returned;
1653 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1655 bcc_ptr += 2 * bytes_returned;
1659 strncpy(bcc_ptr, user, 200);
1660 bcc_ptr += strnlen(user, 200);
1664 if (domain == NULL) {
1665 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1666 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1668 strncpy(bcc_ptr, domain, 64);
1669 bcc_ptr += strnlen(domain, 64);
1673 strcpy(bcc_ptr, "Linux version ");
1674 bcc_ptr += strlen("Linux version ");
1675 strcpy(bcc_ptr, UTS_RELEASE);
1676 bcc_ptr += strlen(UTS_RELEASE) + 1;
1677 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1678 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1680 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1681 smb_buffer->smb_buf_length += count;
1682 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1684 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1685 &bytes_returned, 1);
1687 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1688 } else if ((smb_buffer_response->WordCount == 3)
1689 || (smb_buffer_response->WordCount == 4)) {
1690 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1691 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1692 if (action & GUEST_LOGIN)
1693 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1694 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1695 cFYI(1, ("UID = %d ", ses->Suid));
1696 /* response can have either 3 or 4 word count - Samba sends 3 */
1697 bcc_ptr = pByteArea(smb_buffer_response);
1698 if ((pSMBr->resp.hdr.WordCount == 3)
1699 || ((pSMBr->resp.hdr.WordCount == 4)
1700 && (blob_len < pSMBr->resp.ByteCount))) {
1701 if (pSMBr->resp.hdr.WordCount == 4)
1702 bcc_ptr += blob_len;
1704 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1705 if ((long) (bcc_ptr) % 2) {
1707 (BCC(smb_buffer_response) - 1) /2;
1708 bcc_ptr++; /* Unicode strings must be word aligned */
1711 BCC(smb_buffer_response) / 2;
1714 UniStrnlen((wchar_t *) bcc_ptr,
1715 remaining_words - 1);
1716 /* We look for obvious messed up bcc or strings in response so we do not go off
1717 the end since (at least) WIN2K and Windows XP have a major bug in not null
1718 terminating last Unicode string in response */
1719 ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1720 cifs_strfromUCS_le(ses->serverOS,
1721 (wchar_t *)bcc_ptr, len,nls_codepage);
1722 bcc_ptr += 2 * (len + 1);
1723 remaining_words -= len + 1;
1724 ses->serverOS[2 * len] = 0;
1725 ses->serverOS[1 + (2 * len)] = 0;
1726 if (remaining_words > 0) {
1727 len = UniStrnlen((wchar_t *)bcc_ptr,
1729 ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
1730 cifs_strfromUCS_le(ses->serverNOS,
1731 (wchar_t *)bcc_ptr,len,nls_codepage);
1732 bcc_ptr += 2 * (len + 1);
1733 ses->serverNOS[2 * len] = 0;
1734 ses->serverNOS[1 + (2 * len)] = 0;
1735 remaining_words -= len + 1;
1736 if (remaining_words > 0) {
1737 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1738 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1740 cifs_kcalloc(2*(len+1),GFP_KERNEL);
1741 cifs_strfromUCS_le(ses->serverDomain,
1742 (wchar_t *)bcc_ptr,len,nls_codepage);
1743 bcc_ptr += 2 * (len + 1);
1744 ses->serverDomain[2*len] = 0;
1745 ses->serverDomain[1+(2*len)] = 0;
1746 } /* else no more room so create dummy domain string */
1751 } else { /* no room so create dummy domain and NOS string */
1753 cifs_kcalloc(2, GFP_KERNEL);
1755 cifs_kcalloc(2, GFP_KERNEL);
1757 } else { /* ASCII */
1758 len = strnlen(bcc_ptr, 1024);
1759 if (((long) bcc_ptr + len) - (long)
1760 pByteArea(smb_buffer_response)
1761 <= BCC(smb_buffer_response)) {
1762 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1763 strncpy(ses->serverOS,bcc_ptr, len);
1766 bcc_ptr[0] = 0; /* null terminate the string */
1769 len = strnlen(bcc_ptr, 1024);
1770 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1771 strncpy(ses->serverNOS, bcc_ptr, len);
1776 len = strnlen(bcc_ptr, 1024);
1777 ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
1778 strncpy(ses->serverDomain, bcc_ptr, len);
1784 ("Variable field of length %d extends beyond end of smb ",
1789 (" Security Blob Length extends beyond end of SMB"));
1793 (" Invalid Word count %d: ",
1794 smb_buffer_response->WordCount));
1799 cifs_buf_release(smb_buffer);
1805 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1806 char *SecurityBlob,int SecurityBlobLength,
1807 const struct nls_table *nls_codepage)
1809 struct smb_hdr *smb_buffer;
1810 struct smb_hdr *smb_buffer_response;
1811 SESSION_SETUP_ANDX *pSMB;
1812 SESSION_SETUP_ANDX *pSMBr;
1817 int remaining_words = 0;
1818 int bytes_returned = 0;
1823 cFYI(1, ("In spnego sesssetup "));
1826 user = ses->userName;
1827 domain = ses->domainName;
1829 smb_buffer = cifs_buf_get();
1830 if (smb_buffer == 0) {
1833 smb_buffer_response = smb_buffer;
1834 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1836 /* send SMBsessionSetup here */
1837 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1838 NULL /* no tCon exists yet */ , 12 /* wct */ );
1839 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1840 pSMB->req.AndXCommand = 0xFF;
1841 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1842 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1844 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1845 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1847 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1848 CAP_EXTENDED_SECURITY;
1849 if (ses->capabilities & CAP_UNICODE) {
1850 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1851 capabilities |= CAP_UNICODE;
1853 if (ses->capabilities & CAP_STATUS32) {
1854 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1855 capabilities |= CAP_STATUS32;
1857 if (ses->capabilities & CAP_DFS) {
1858 smb_buffer->Flags2 |= SMBFLG2_DFS;
1859 capabilities |= CAP_DFS;
1861 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1863 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1864 bcc_ptr = pByteArea(smb_buffer);
1865 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1866 bcc_ptr += SecurityBlobLength;
1868 if (ses->capabilities & CAP_UNICODE) {
1869 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1874 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1875 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1876 bcc_ptr += 2; /* trailing null */
1879 cifs_strtoUCS((wchar_t *) bcc_ptr,
1880 "CIFS_LINUX_DOM", 32, nls_codepage);
1883 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1885 bcc_ptr += 2 * bytes_returned;
1888 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1890 bcc_ptr += 2 * bytes_returned;
1892 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
1894 bcc_ptr += 2 * bytes_returned;
1897 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1899 bcc_ptr += 2 * bytes_returned;
1902 strncpy(bcc_ptr, user, 200);
1903 bcc_ptr += strnlen(user, 200);
1906 if (domain == NULL) {
1907 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1908 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1910 strncpy(bcc_ptr, domain, 64);
1911 bcc_ptr += strnlen(domain, 64);
1915 strcpy(bcc_ptr, "Linux version ");
1916 bcc_ptr += strlen("Linux version ");
1917 strcpy(bcc_ptr, UTS_RELEASE);
1918 bcc_ptr += strlen(UTS_RELEASE) + 1;
1919 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1920 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1922 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1923 smb_buffer->smb_buf_length += count;
1924 pSMB->req.ByteCount = cpu_to_le16(count);
1926 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1927 &bytes_returned, 1);
1929 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1930 } else if ((smb_buffer_response->WordCount == 3)
1931 || (smb_buffer_response->WordCount == 4)) {
1932 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1934 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1935 if (action & GUEST_LOGIN)
1936 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1938 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1939 cFYI(1, ("UID = %d ", ses->Suid));
1940 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
1942 /* BB Fix below to make endian neutral !! */
1944 if ((pSMBr->resp.hdr.WordCount == 3)
1945 || ((pSMBr->resp.hdr.WordCount == 4)
1947 pSMBr->resp.ByteCount))) {
1948 if (pSMBr->resp.hdr.WordCount == 4) {
1952 ("Security Blob Length %d ",
1956 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1957 if ((long) (bcc_ptr) % 2) {
1959 (BCC(smb_buffer_response)
1961 bcc_ptr++; /* Unicode strings must be word aligned */
1965 (smb_buffer_response) / 2;
1968 UniStrnlen((wchar_t *) bcc_ptr,
1969 remaining_words - 1);
1970 /* We look for obvious messed up bcc or strings in response so we do not go off
1971 the end since (at least) WIN2K and Windows XP have a major bug in not null
1972 terminating last Unicode string in response */
1974 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1975 cifs_strfromUCS_le(ses->serverOS,
1979 bcc_ptr += 2 * (len + 1);
1980 remaining_words -= len + 1;
1981 ses->serverOS[2 * len] = 0;
1982 ses->serverOS[1 + (2 * len)] = 0;
1983 if (remaining_words > 0) {
1984 len = UniStrnlen((wchar_t *)bcc_ptr,
1988 cifs_kcalloc(2 * (len + 1),
1990 cifs_strfromUCS_le(ses->serverNOS,
1994 bcc_ptr += 2 * (len + 1);
1995 ses->serverNOS[2 * len] = 0;
1996 ses->serverNOS[1 + (2 * len)] = 0;
1997 remaining_words -= len + 1;
1998 if (remaining_words > 0) {
1999 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2000 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2001 ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
2002 cifs_strfromUCS_le(ses->serverDomain,
2006 bcc_ptr += 2*(len+1);
2007 ses->serverDomain[2*len] = 0;
2008 ses->serverDomain[1+(2*len)] = 0;
2009 } /* else no more room so create dummy domain string */
2012 cifs_kcalloc(2,GFP_KERNEL);
2013 } else { /* no room so create dummy domain and NOS string */
2014 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2015 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2017 } else { /* ASCII */
2019 len = strnlen(bcc_ptr, 1024);
2020 if (((long) bcc_ptr + len) - (long)
2021 pByteArea(smb_buffer_response)
2022 <= BCC(smb_buffer_response)) {
2023 ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
2024 strncpy(ses->serverOS, bcc_ptr, len);
2027 bcc_ptr[0] = 0; /* null terminate the string */
2030 len = strnlen(bcc_ptr, 1024);
2031 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2032 strncpy(ses->serverNOS, bcc_ptr, len);
2037 len = strnlen(bcc_ptr, 1024);
2038 ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
2039 strncpy(ses->serverDomain, bcc_ptr, len);
2045 ("Variable field of length %d extends beyond end of smb ",
2050 (" Security Blob Length extends beyond end of SMB"));
2053 cERROR(1, ("No session structure passed in."));
2057 (" Invalid Word count %d: ",
2058 smb_buffer_response->WordCount));
2063 cifs_buf_release(smb_buffer);
2069 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2070 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2071 const struct nls_table *nls_codepage)
2073 struct smb_hdr *smb_buffer;
2074 struct smb_hdr *smb_buffer_response;
2075 SESSION_SETUP_ANDX *pSMB;
2076 SESSION_SETUP_ANDX *pSMBr;
2080 int remaining_words = 0;
2081 int bytes_returned = 0;
2083 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2084 PNEGOTIATE_MESSAGE SecurityBlob;
2085 PCHALLENGE_MESSAGE SecurityBlob2;
2086 __u32 negotiate_flags, capabilities;
2089 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2092 domain = ses->domainName;
2093 *pNTLMv2_flag = FALSE;
2094 smb_buffer = cifs_buf_get();
2095 if (smb_buffer == 0) {
2098 smb_buffer_response = smb_buffer;
2099 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2100 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2102 /* send SMBsessionSetup here */
2103 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2104 NULL /* no tCon exists yet */ , 12 /* wct */ );
2105 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2106 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2108 pSMB->req.AndXCommand = 0xFF;
2109 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2110 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2112 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2113 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2115 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2116 CAP_EXTENDED_SECURITY;
2117 if (ses->capabilities & CAP_UNICODE) {
2118 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2119 capabilities |= CAP_UNICODE;
2121 if (ses->capabilities & CAP_STATUS32) {
2122 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2123 capabilities |= CAP_STATUS32;
2125 if (ses->capabilities & CAP_DFS) {
2126 smb_buffer->Flags2 |= SMBFLG2_DFS;
2127 capabilities |= CAP_DFS;
2129 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2131 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2132 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2133 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2134 SecurityBlob->MessageType = NtLmNegotiate;
2136 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2137 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2138 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2140 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2142 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2143 /* setup pointers to domain name and workstation name */
2144 bcc_ptr += SecurityBlobLength;
2146 SecurityBlob->WorkstationName.Buffer = 0;
2147 SecurityBlob->WorkstationName.Length = 0;
2148 SecurityBlob->WorkstationName.MaximumLength = 0;
2150 if (domain == NULL) {
2151 SecurityBlob->DomainName.Buffer = 0;
2152 SecurityBlob->DomainName.Length = 0;
2153 SecurityBlob->DomainName.MaximumLength = 0;
2156 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2157 strncpy(bcc_ptr, domain, 63);
2158 len = strnlen(domain, 64);
2159 SecurityBlob->DomainName.MaximumLength =
2161 SecurityBlob->DomainName.Buffer =
2162 cpu_to_le32((long) &SecurityBlob->
2164 (long) &SecurityBlob->Signature);
2166 SecurityBlobLength += len;
2167 SecurityBlob->DomainName.Length =
2170 if (ses->capabilities & CAP_UNICODE) {
2171 if ((long) bcc_ptr % 2) {
2177 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2179 bcc_ptr += 2 * bytes_returned;
2181 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
2183 bcc_ptr += 2 * bytes_returned;
2184 bcc_ptr += 2; /* null terminate Linux version */
2186 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2188 bcc_ptr += 2 * bytes_returned;
2191 bcc_ptr += 2; /* null terminate network opsys string */
2194 bcc_ptr += 2; /* null domain */
2195 } else { /* ASCII */
2196 strcpy(bcc_ptr, "Linux version ");
2197 bcc_ptr += strlen("Linux version ");
2198 strcpy(bcc_ptr, UTS_RELEASE);
2199 bcc_ptr += strlen(UTS_RELEASE) + 1;
2200 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2201 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2202 bcc_ptr++; /* empty domain field */
2205 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2206 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2207 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2208 smb_buffer->smb_buf_length += count;
2209 pSMB->req.ByteCount = cpu_to_le16(count);
2211 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2212 &bytes_returned, 1);
2214 if (smb_buffer_response->Status.CifsError ==
2215 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2219 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2220 } else if ((smb_buffer_response->WordCount == 3)
2221 || (smb_buffer_response->WordCount == 4)) {
2222 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2223 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2225 if (action & GUEST_LOGIN)
2226 cFYI(1, (" Guest login"));
2227 /* Do we want to set anything in SesInfo struct when guest login? */
2229 bcc_ptr = pByteArea(smb_buffer_response);
2230 /* response can have either 3 or 4 word count - Samba sends 3 */
2232 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2233 if (SecurityBlob2->MessageType != NtLmChallenge) {
2235 ("Unexpected NTLMSSP message type received %d",
2236 SecurityBlob2->MessageType));
2238 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2239 cFYI(1, ("UID = %d ", ses->Suid));
2240 if ((pSMBr->resp.hdr.WordCount == 3)
2241 || ((pSMBr->resp.hdr.WordCount == 4)
2243 pSMBr->resp.ByteCount))) {
2245 if (pSMBr->resp.hdr.WordCount == 4) {
2246 bcc_ptr += blob_len;
2248 ("Security Blob Length %d ",
2252 cFYI(1, ("NTLMSSP Challenge rcvd "));
2254 memcpy(ses->server->cryptKey,
2255 SecurityBlob2->Challenge,
2256 CIFS_CRYPTO_KEY_SIZE);
2257 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2258 *pNTLMv2_flag = TRUE;
2260 if((SecurityBlob2->NegotiateFlags &
2261 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2262 || (sign_CIFS_PDUs > 1))
2263 ses->server->secMode |=
2264 SECMODE_SIGN_REQUIRED;
2265 if ((SecurityBlob2->NegotiateFlags &
2266 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2267 ses->server->secMode |=
2268 SECMODE_SIGN_ENABLED;
2270 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2271 if ((long) (bcc_ptr) % 2) {
2273 (BCC(smb_buffer_response)
2275 bcc_ptr++; /* Unicode strings must be word aligned */
2279 (smb_buffer_response) / 2;
2282 UniStrnlen((wchar_t *) bcc_ptr,
2283 remaining_words - 1);
2284 /* We look for obvious messed up bcc or strings in response so we do not go off
2285 the end since (at least) WIN2K and Windows XP have a major bug in not null
2286 terminating last Unicode string in response */
2288 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2289 cifs_strfromUCS_le(ses->serverOS,
2293 bcc_ptr += 2 * (len + 1);
2294 remaining_words -= len + 1;
2295 ses->serverOS[2 * len] = 0;
2296 ses->serverOS[1 + (2 * len)] = 0;
2297 if (remaining_words > 0) {
2298 len = UniStrnlen((wchar_t *)
2303 cifs_kcalloc(2 * (len + 1),
2305 cifs_strfromUCS_le(ses->
2311 bcc_ptr += 2 * (len + 1);
2312 ses->serverNOS[2 * len] = 0;
2315 remaining_words -= len + 1;
2316 if (remaining_words > 0) {
2317 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2318 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2343 } /* else no more room so create dummy domain string */
2348 } else { /* no room so create dummy domain and NOS string */
2350 cifs_kcalloc(2, GFP_KERNEL);
2352 cifs_kcalloc(2, GFP_KERNEL);
2354 } else { /* ASCII */
2355 len = strnlen(bcc_ptr, 1024);
2356 if (((long) bcc_ptr + len) - (long)
2357 pByteArea(smb_buffer_response)
2358 <= BCC(smb_buffer_response)) {
2360 cifs_kcalloc(len + 1,
2362 strncpy(ses->serverOS,
2366 bcc_ptr[0] = 0; /* null terminate string */
2369 len = strnlen(bcc_ptr, 1024);
2371 cifs_kcalloc(len + 1,
2373 strncpy(ses->serverNOS, bcc_ptr, len);
2378 len = strnlen(bcc_ptr, 1024);
2380 cifs_kcalloc(len + 1,
2382 strncpy(ses->serverDomain, bcc_ptr, len);
2388 ("Variable field of length %d extends beyond end of smb ",
2393 (" Security Blob Length extends beyond end of SMB"));
2396 cERROR(1, ("No session structure passed in."));
2400 (" Invalid Word count %d: ",
2401 smb_buffer_response->WordCount));
2406 cifs_buf_release(smb_buffer);
2411 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2412 char *ntlm_session_key, int ntlmv2_flag,
2413 const struct nls_table *nls_codepage)
2415 struct smb_hdr *smb_buffer;
2416 struct smb_hdr *smb_buffer_response;
2417 SESSION_SETUP_ANDX *pSMB;
2418 SESSION_SETUP_ANDX *pSMBr;
2423 int remaining_words = 0;
2424 int bytes_returned = 0;
2426 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2427 PAUTHENTICATE_MESSAGE SecurityBlob;
2428 __u32 negotiate_flags, capabilities;
2431 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2434 user = ses->userName;
2435 domain = ses->domainName;
2436 smb_buffer = cifs_buf_get();
2437 if (smb_buffer == 0) {
2440 smb_buffer_response = smb_buffer;
2441 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2442 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2444 /* send SMBsessionSetup here */
2445 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2446 NULL /* no tCon exists yet */ , 12 /* wct */ );
2447 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2448 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2449 pSMB->req.AndXCommand = 0xFF;
2450 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2451 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2453 pSMB->req.hdr.Uid = ses->Suid;
2455 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2456 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2458 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2459 CAP_EXTENDED_SECURITY;
2460 if (ses->capabilities & CAP_UNICODE) {
2461 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2462 capabilities |= CAP_UNICODE;
2464 if (ses->capabilities & CAP_STATUS32) {
2465 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2466 capabilities |= CAP_STATUS32;
2468 if (ses->capabilities & CAP_DFS) {
2469 smb_buffer->Flags2 |= SMBFLG2_DFS;
2470 capabilities |= CAP_DFS;
2472 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2474 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2475 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2476 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2477 SecurityBlob->MessageType = NtLmAuthenticate;
2478 bcc_ptr += SecurityBlobLength;
2480 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2481 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2482 0x80000000 | NTLMSSP_NEGOTIATE_128;
2484 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2486 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2488 /* setup pointers to domain name and workstation name */
2490 SecurityBlob->WorkstationName.Buffer = 0;
2491 SecurityBlob->WorkstationName.Length = 0;
2492 SecurityBlob->WorkstationName.MaximumLength = 0;
2493 SecurityBlob->SessionKey.Length = 0;
2494 SecurityBlob->SessionKey.MaximumLength = 0;
2495 SecurityBlob->SessionKey.Buffer = 0;
2497 SecurityBlob->LmChallengeResponse.Length = 0;
2498 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2499 SecurityBlob->LmChallengeResponse.Buffer = 0;
2501 SecurityBlob->NtChallengeResponse.Length =
2502 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2503 SecurityBlob->NtChallengeResponse.MaximumLength =
2504 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2505 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2506 SecurityBlob->NtChallengeResponse.Buffer =
2507 cpu_to_le32(SecurityBlobLength);
2508 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2509 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2511 if (ses->capabilities & CAP_UNICODE) {
2512 if (domain == NULL) {
2513 SecurityBlob->DomainName.Buffer = 0;
2514 SecurityBlob->DomainName.Length = 0;
2515 SecurityBlob->DomainName.MaximumLength = 0;
2518 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2521 SecurityBlob->DomainName.MaximumLength =
2523 SecurityBlob->DomainName.Buffer =
2524 cpu_to_le32(SecurityBlobLength);
2526 SecurityBlobLength += len;
2527 SecurityBlob->DomainName.Length =
2531 SecurityBlob->UserName.Buffer = 0;
2532 SecurityBlob->UserName.Length = 0;
2533 SecurityBlob->UserName.MaximumLength = 0;
2536 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2539 SecurityBlob->UserName.MaximumLength =
2541 SecurityBlob->UserName.Buffer =
2542 cpu_to_le32(SecurityBlobLength);
2544 SecurityBlobLength += len;
2545 SecurityBlob->UserName.Length =
2549 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2550 SecurityBlob->WorkstationName.Length *= 2;
2551 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2552 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2553 bcc_ptr += SecurityBlob->WorkstationName.Length;
2554 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2555 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2557 if ((long) bcc_ptr % 2) {
2562 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2564 bcc_ptr += 2 * bytes_returned;
2566 cifs_strtoUCS((wchar_t *) bcc_ptr, UTS_RELEASE, 32,
2568 bcc_ptr += 2 * bytes_returned;
2569 bcc_ptr += 2; /* null term version string */
2571 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2573 bcc_ptr += 2 * bytes_returned;
2576 bcc_ptr += 2; /* null terminate network opsys string */
2579 bcc_ptr += 2; /* null domain */
2580 } else { /* ASCII */
2581 if (domain == NULL) {
2582 SecurityBlob->DomainName.Buffer = 0;
2583 SecurityBlob->DomainName.Length = 0;
2584 SecurityBlob->DomainName.MaximumLength = 0;
2587 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2588 strncpy(bcc_ptr, domain, 63);
2589 len = strnlen(domain, 64);
2590 SecurityBlob->DomainName.MaximumLength =
2592 SecurityBlob->DomainName.Buffer =
2593 cpu_to_le32(SecurityBlobLength);
2595 SecurityBlobLength += len;
2596 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2599 SecurityBlob->UserName.Buffer = 0;
2600 SecurityBlob->UserName.Length = 0;
2601 SecurityBlob->UserName.MaximumLength = 0;
2604 strncpy(bcc_ptr, user, 63);
2605 len = strnlen(user, 64);
2606 SecurityBlob->UserName.MaximumLength =
2608 SecurityBlob->UserName.Buffer =
2609 cpu_to_le32(SecurityBlobLength);
2611 SecurityBlobLength += len;
2612 SecurityBlob->UserName.Length = cpu_to_le16(len);
2614 /* BB fill in our workstation name if known BB */
2616 strcpy(bcc_ptr, "Linux version ");
2617 bcc_ptr += strlen("Linux version ");
2618 strcpy(bcc_ptr, UTS_RELEASE);
2619 bcc_ptr += strlen(UTS_RELEASE) + 1;
2620 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2621 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2622 bcc_ptr++; /* null domain */
2625 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2626 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2627 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2628 smb_buffer->smb_buf_length += count;
2629 pSMB->req.ByteCount = cpu_to_le16(count);
2631 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2632 &bytes_returned, 1);
2634 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2635 } else if ((smb_buffer_response->WordCount == 3)
2636 || (smb_buffer_response->WordCount == 4)) {
2637 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2639 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2640 if (action & GUEST_LOGIN)
2641 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2642 /* if(SecurityBlob2->MessageType != NtLm??){
2643 cFYI("Unexpected message type on auth response is %d "));
2647 ("Does UID on challenge %d match auth response UID %d ",
2648 ses->Suid, smb_buffer_response->Uid));
2649 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2650 bcc_ptr = pByteArea(smb_buffer_response);
2651 /* response can have either 3 or 4 word count - Samba sends 3 */
2652 if ((pSMBr->resp.hdr.WordCount == 3)
2653 || ((pSMBr->resp.hdr.WordCount == 4)
2655 pSMBr->resp.ByteCount))) {
2656 if (pSMBr->resp.hdr.WordCount == 4) {
2660 ("Security Blob Length %d ",
2665 ("NTLMSSP response to Authenticate "));
2667 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2668 if ((long) (bcc_ptr) % 2) {
2670 (BCC(smb_buffer_response)
2672 bcc_ptr++; /* Unicode strings must be word aligned */
2674 remaining_words = BCC(smb_buffer_response) / 2;
2677 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2678 /* We look for obvious messed up bcc or strings in response so we do not go off
2679 the end since (at least) WIN2K and Windows XP have a major bug in not null
2680 terminating last Unicode string in response */
2682 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2683 cifs_strfromUCS_le(ses->serverOS,
2687 bcc_ptr += 2 * (len + 1);
2688 remaining_words -= len + 1;
2689 ses->serverOS[2 * len] = 0;
2690 ses->serverOS[1 + (2 * len)] = 0;
2691 if (remaining_words > 0) {
2692 len = UniStrnlen((wchar_t *)
2697 cifs_kcalloc(2 * (len + 1),
2699 cifs_strfromUCS_le(ses->
2705 bcc_ptr += 2 * (len + 1);
2706 ses->serverNOS[2 * len] = 0;
2707 ses->serverNOS[1+(2*len)] = 0;
2708 remaining_words -= len + 1;
2709 if (remaining_words > 0) {
2710 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2711 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2736 } /* else no more room so create dummy domain string */
2738 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
2739 } else { /* no room so create dummy domain and NOS string */
2740 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2741 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2743 } else { /* ASCII */
2744 len = strnlen(bcc_ptr, 1024);
2745 if (((long) bcc_ptr + len) -
2746 (long) pByteArea(smb_buffer_response)
2747 <= BCC(smb_buffer_response)) {
2748 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2749 strncpy(ses->serverOS,bcc_ptr, len);
2752 bcc_ptr[0] = 0; /* null terminate the string */
2755 len = strnlen(bcc_ptr, 1024);
2756 ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
2757 strncpy(ses->serverNOS, bcc_ptr, len);
2762 len = strnlen(bcc_ptr, 1024);
2763 ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
2764 strncpy(ses->serverDomain, bcc_ptr, len);
2770 ("Variable field of length %d extends beyond end of smb ",
2775 (" Security Blob Length extends beyond end of SMB"));
2778 cERROR(1, ("No session structure passed in."));
2782 (" Invalid Word count %d: ",
2783 smb_buffer_response->WordCount));
2788 cifs_buf_release(smb_buffer);
2794 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2795 const char *tree, struct cifsTconInfo *tcon,
2796 const struct nls_table *nls_codepage)
2798 struct smb_hdr *smb_buffer;
2799 struct smb_hdr *smb_buffer_response;
2802 unsigned char *bcc_ptr;
2810 smb_buffer = cifs_buf_get();
2811 if (smb_buffer == 0) {
2814 smb_buffer_response = smb_buffer;
2816 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2817 NULL /*no tid */ , 4 /*wct */ );
2818 smb_buffer->Uid = ses->Suid;
2819 pSMB = (TCONX_REQ *) smb_buffer;
2820 pSMBr = (TCONX_RSP *) smb_buffer_response;
2822 pSMB->AndXCommand = 0xFF;
2823 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2824 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2825 bcc_ptr = &pSMB->Password[0];
2826 bcc_ptr++; /* skip password */
2828 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2829 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2831 if (ses->capabilities & CAP_STATUS32) {
2832 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2834 if (ses->capabilities & CAP_DFS) {
2835 smb_buffer->Flags2 |= SMBFLG2_DFS;
2837 if (ses->capabilities & CAP_UNICODE) {
2838 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2840 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2841 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2842 bcc_ptr += 2; /* skip trailing null */
2843 } else { /* ASCII */
2845 strcpy(bcc_ptr, tree);
2846 bcc_ptr += strlen(tree) + 1;
2848 strcpy(bcc_ptr, "?????");
2849 bcc_ptr += strlen("?????");
2851 count = bcc_ptr - &pSMB->Password[0];
2852 pSMB->hdr.smb_buf_length += count;
2853 pSMB->ByteCount = cpu_to_le16(count);
2855 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2857 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2858 /* above now done in SendReceive */
2859 if ((rc == 0) && (tcon != NULL)) {
2860 tcon->tidStatus = CifsGood;
2861 tcon->tid = smb_buffer_response->Tid;
2862 bcc_ptr = pByteArea(smb_buffer_response);
2863 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2864 /* skip service field (NB: this field is always ASCII) */
2865 bcc_ptr += length + 1;
2866 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2867 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2868 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2869 if ((bcc_ptr + (2 * length)) -
2870 pByteArea(smb_buffer_response) <=
2871 BCC(smb_buffer_response)) {
2872 if(tcon->nativeFileSystem)
2873 kfree(tcon->nativeFileSystem);
2874 tcon->nativeFileSystem =
2875 cifs_kcalloc(length + 2, GFP_KERNEL);
2876 cifs_strfromUCS_le(tcon->nativeFileSystem,
2877 (wchar_t *) bcc_ptr,
2878 length, nls_codepage);
2879 bcc_ptr += 2 * length;
2880 bcc_ptr[0] = 0; /* null terminate the string */
2884 /* else do not bother copying these informational fields */
2886 length = strnlen(bcc_ptr, 1024);
2887 if ((bcc_ptr + length) -
2888 pByteArea(smb_buffer_response) <=
2889 BCC(smb_buffer_response)) {
2890 if(tcon->nativeFileSystem)
2891 kfree(tcon->nativeFileSystem);
2892 tcon->nativeFileSystem =
2893 cifs_kcalloc(length + 1, GFP_KERNEL);
2894 strncpy(tcon->nativeFileSystem, bcc_ptr,
2897 /* else do not bother copying these informational fields */
2899 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2900 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2901 } else if ((rc == 0) && tcon == NULL) {
2902 /* all we need to save for IPC$ connection */
2903 ses->ipc_tid = smb_buffer_response->Tid;
2907 cifs_buf_release(smb_buffer);
2912 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
2916 struct cifsSesInfo *ses = NULL;
2917 struct task_struct *cifsd_task;
2921 if (cifs_sb->tcon) {
2922 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
2923 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
2928 tconInfoFree(cifs_sb->tcon);
2929 if ((ses) && (ses->server)) {
2930 /* save off task so we do not refer to ses later */
2931 cifsd_task = ses->server->tsk;
2932 cFYI(1, ("About to do SMBLogoff "));
2933 rc = CIFSSMBLogoff(xid, ses);
2937 } else if (rc == -ESHUTDOWN) {
2938 cFYI(1,("Waking up socket by sending it signal"));
2939 send_sig(SIGKILL,cifsd_task,1);
2941 } /* else - we have an smb session
2942 left on this socket do not kill cifsd */
2944 cFYI(1, ("No session or bad tcon"));
2947 cifs_sb->tcon = NULL;
2949 set_current_state(TASK_INTERRUPTIBLE);
2950 schedule_timeout(HZ / 2);
2956 return rc; /* BB check if we should always return zero here */
2959 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2960 struct nls_table * nls_info)
2963 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
2964 int ntlmv2_flag = FALSE;
2966 /* what if server changes its buffer size after dropping the session? */
2967 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
2968 rc = CIFSSMBNegotiate(xid, pSesInfo);
2969 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
2970 rc = CIFSSMBNegotiate(xid, pSesInfo);
2975 spin_lock(&GlobalMid_Lock);
2976 if(pSesInfo->server->tcpStatus != CifsExiting)
2977 pSesInfo->server->tcpStatus = CifsGood;
2980 spin_unlock(&GlobalMid_Lock);
2985 pSesInfo->capabilities = pSesInfo->server->capabilities;
2986 if(linuxExtEnabled == 0)
2987 pSesInfo->capabilities &= (~CAP_UNIX);
2988 pSesInfo->sequence_number = 0;
2989 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2990 pSesInfo->server->secMode,
2991 pSesInfo->server->capabilities,
2992 pSesInfo->server->timeZone));
2993 if (extended_security
2994 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
2995 && (pSesInfo->server->secType == NTLMSSP)) {
2996 cFYI(1, ("New style sesssetup "));
2997 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
2998 NULL /* security blob */,
2999 0 /* blob length */,
3001 } else if (extended_security
3002 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3003 && (pSesInfo->server->secType == RawNTLMSSP)) {
3004 cFYI(1, ("NTLMSSP sesssetup "));
3005 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3012 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3013 CalcNTLMv2_partial_mac_key(pSesInfo,
3015 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3017 CalcNTLMv2_response(pSesInfo,v2_response);
3018 /* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */
3020 /* BB Put dummy sig in SessSetup PDU? */
3025 SMBNTencrypt(pSesInfo->password,
3026 pSesInfo->server->cryptKey,
3029 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
3031 pSesInfo->password);
3033 /* for better security the weaker lanman hash not sent
3034 in AuthSessSetup so we no longer calculate it */
3036 rc = CIFSNTLMSSPAuthSessSetup(xid,
3042 } else { /* old style NTLM 0.12 session setup */
3043 SMBNTencrypt(pSesInfo->password,
3044 pSesInfo->server->cryptKey,
3047 cifs_calculate_mac_key(pSesInfo->mac_signing_key,
3048 ntlm_session_key, pSesInfo->password);
3049 rc = CIFSSessSetup(xid, pSesInfo,
3050 ntlm_session_key, nls_info);
3053 cERROR(1,("Send error in SessSetup = %d",rc));
3055 cFYI(1,("CIFS Session Established successfully"));
3056 pSesInfo->status = CifsGood;