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,
51 extern mempool_t *cifs_req_poolp;
59 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
60 char *iocharset; /* local code page for mapping to and from Unicode */
61 char source_rfc1001_name[16]; /* netbios name of client */
71 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
72 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
73 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
75 unsigned remap:1; /* set to remap seven reserved chars in filenames */
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 server->sequence_number = 0;
187 spin_unlock(&GlobalMid_Lock);
188 /* atomic_set(&server->inFlight,0);*/
189 wake_up(&server->response_q);
196 cifs_demultiplex_thread(struct TCP_Server_Info *server)
199 unsigned int pdu_length, total_read;
200 struct smb_hdr *smb_buffer = NULL;
201 struct msghdr smb_msg;
203 struct socket *csocket = server->ssocket;
204 struct list_head *tmp;
205 struct cifsSesInfo *ses;
206 struct task_struct *task_to_wake = NULL;
207 struct mid_q_entry *mid_entry;
211 allow_signal(SIGKILL);
212 current->flags |= PF_MEMALLOC;
213 server->tsk = current; /* save process info to wake at shutdown */
214 cFYI(1, ("Demultiplex PID: %d", current->pid));
215 write_lock(&GlobalSMBSeslock);
216 atomic_inc(&tcpSesAllocCount);
217 length = tcpSesAllocCount.counter;
218 write_unlock(&GlobalSMBSeslock);
220 mempool_resize(cifs_req_poolp,
221 length + cifs_min_rcv,
225 while (server->tcpStatus != CifsExiting) {
226 if (smb_buffer == NULL)
227 smb_buffer = cifs_buf_get();
229 memset(smb_buffer, 0, sizeof (struct smb_hdr));
231 if (smb_buffer == NULL) {
232 cERROR(1,("Can not get memory for SMB response"));
233 set_current_state(TASK_INTERRUPTIBLE);
234 schedule_timeout(HZ * 3); /* give system time to free memory */
237 iov.iov_base = smb_buffer;
239 smb_msg.msg_control = NULL;
240 smb_msg.msg_controllen = 0;
242 kernel_recvmsg(csocket, &smb_msg,
243 &iov, 1, 4, 0 /* BB see socket.h flags */);
245 if(server->tcpStatus == CifsExiting) {
247 } else if (server->tcpStatus == CifsNeedReconnect) {
248 cFYI(1,("Reconnecting after server stopped responding"));
249 cifs_reconnect(server);
250 cFYI(1,("call to reconnect done"));
251 csocket = server->ssocket;
253 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
254 set_current_state(TASK_INTERRUPTIBLE);
255 schedule_timeout(1); /* minimum sleep to prevent looping
256 allowing socket to clear and app threads to set
257 tcpStatus CifsNeedReconnect if server hung */
259 } else if (length <= 0) {
260 if(server->tcpStatus == CifsNew) {
261 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
262 /* some servers kill tcp session rather than returning
263 smb negprot error in which case reconnecting here is
264 not going to help - return error to mount */
267 if(length == -EINTR) {
268 cFYI(1,("cifsd thread killed"));
271 cFYI(1,("Reconnecting after unexpected peek error %d",length));
272 cifs_reconnect(server);
273 csocket = server->ssocket;
274 wake_up(&server->response_q);
276 } else if (length > 3) {
277 pdu_length = ntohl(smb_buffer->smb_buf_length);
278 /* Only read pdu_length after below checks for too short (due
279 to e.g. int overflow) and too long ie beyond end of buf */
280 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
282 temp = (char *) smb_buffer;
283 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
284 cFYI(0,("Received 4 byte keep alive packet"));
285 } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
286 cFYI(1,("Good RFC 1002 session rsp"));
287 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
288 /* we get this from Windows 98 instead of error on SMB negprot response */
289 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
290 if(server->tcpStatus == CifsNew) {
291 /* if nack on negprot (rather than
292 ret of smb negprot error) reconnecting
293 not going to help, ret error to mount */
296 /* give server a second to
297 clean up before reconnect attempt */
298 set_current_state(TASK_INTERRUPTIBLE);
299 schedule_timeout(HZ);
300 /* always try 445 first on reconnect
301 since we get NACK on some if we ever
302 connected to port 139 (the NACK is
303 since we do not begin with RFC1001
304 session initialize frame) */
305 server->addr.sockAddr.sin_port = htons(CIFS_PORT);
306 cifs_reconnect(server);
307 csocket = server->ssocket;
308 wake_up(&server->response_q);
311 } else if (temp[0] != (char) 0) {
312 cERROR(1,("Unknown RFC 1002 frame"));
313 cifs_dump_mem(" Received Data: ", temp, length);
314 cifs_reconnect(server);
315 csocket = server->ssocket;
318 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
319 || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
321 ("Invalid size SMB length %d and pdu_length %d",
322 length, pdu_length+4));
323 cifs_reconnect(server);
324 csocket = server->ssocket;
325 wake_up(&server->response_q);
327 } else { /* length ok */
329 iov.iov_base = 4 + (char *)smb_buffer;
330 iov.iov_len = pdu_length;
332 total_read < pdu_length;
333 total_read += length) {
334 length = kernel_recvmsg(csocket, &smb_msg,
336 pdu_length - total_read, 0);
339 ("Zero length receive when expecting %d ",
340 pdu_length - total_read));
341 cifs_reconnect(server);
342 csocket = server->ssocket;
343 wake_up(&server->response_q);
347 length += 4; /* account for rfc1002 hdr */
350 dump_smb(smb_buffer, length);
352 (smb_buffer, smb_buffer->Mid, total_read+4)) {
353 cERROR(1, ("Bad SMB Received "));
358 spin_lock(&GlobalMid_Lock);
359 list_for_each(tmp, &server->pending_mid_q) {
360 mid_entry = list_entry(tmp, struct
364 if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
366 (" Mid 0x%x matched - waking up ",mid_entry->mid));
367 task_to_wake = mid_entry->tsk;
368 mid_entry->resp_buf =
370 mid_entry->midState =
371 MID_RESPONSE_RECEIVED;
374 spin_unlock(&GlobalMid_Lock);
376 smb_buffer = NULL; /* will be freed by users thread after he is done */
377 wake_up_process(task_to_wake);
378 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
379 cERROR(1, ("No task to wake, unknown frame rcvd!"));
380 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
385 ("Frame less than four bytes received %d bytes long.",
387 cifs_reconnect(server);
388 csocket = server->ssocket;
389 wake_up(&server->response_q);
393 spin_lock(&GlobalMid_Lock);
394 server->tcpStatus = CifsExiting;
396 atomic_set(&server->inFlight, 0);
397 spin_unlock(&GlobalMid_Lock);
398 /* Although there should not be any requests blocked on
399 this queue it can not hurt to be paranoid and try to wake up requests
400 that may haven been blocked when more than 50 at time were on the wire
401 to the same server - they now will see the session is in exit state
402 and get out of SendReceive. */
403 wake_up_all(&server->request_q);
404 /* give those requests time to exit */
405 set_current_state(TASK_INTERRUPTIBLE);
406 schedule_timeout(HZ/8);
408 if(server->ssocket) {
409 sock_release(csocket);
410 server->ssocket = NULL;
412 if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */
413 cifs_buf_release(smb_buffer);
415 read_lock(&GlobalSMBSeslock);
416 if (list_empty(&server->pending_mid_q)) {
417 /* loop through server session structures attached to this and mark them dead */
418 list_for_each(tmp, &GlobalSMBSessionList) {
420 list_entry(tmp, struct cifsSesInfo,
422 if (ses->server == server) {
423 ses->status = CifsExiting;
427 read_unlock(&GlobalSMBSeslock);
429 spin_lock(&GlobalMid_Lock);
430 list_for_each(tmp, &server->pending_mid_q) {
431 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
432 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
434 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
435 task_to_wake = mid_entry->tsk;
437 wake_up_process(task_to_wake);
441 spin_unlock(&GlobalMid_Lock);
442 read_unlock(&GlobalSMBSeslock);
443 set_current_state(TASK_INTERRUPTIBLE);
444 /* 1/8th of sec is more than enough time for them to exit */
445 schedule_timeout(HZ/8);
448 if (list_empty(&server->pending_mid_q)) {
449 /* mpx threads have not exited yet give them
450 at least the smb send timeout time for long ops */
451 cFYI(1, ("Wait for exit from demultiplex thread"));
452 set_current_state(TASK_INTERRUPTIBLE);
453 schedule_timeout(46 * HZ);
454 /* if threads still have not exited they are probably never
455 coming home not much else we can do but free the memory */
459 write_lock(&GlobalSMBSeslock);
460 atomic_dec(&tcpSesAllocCount);
461 length = tcpSesAllocCount.counter;
462 write_unlock(&GlobalSMBSeslock);
464 mempool_resize(cifs_req_poolp,
465 length + cifs_min_rcv,
469 set_current_state(TASK_INTERRUPTIBLE);
470 schedule_timeout(HZ/4);
475 cifs_kcalloc(size_t size, unsigned int __nocast type)
478 addr = kmalloc(size, type);
480 memset(addr, 0, size);
485 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
489 unsigned int temp_len, i, j;
495 memset(vol->source_rfc1001_name,0x20,15);
496 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
497 /* does not have to be a perfect mapping since the field is
498 informational, only used for servers that do not support
499 port 445 and it can be overridden at mount time */
500 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
502 vol->source_rfc1001_name[15] = 0;
504 vol->linux_uid = current->uid; /* current->euid instead? */
505 vol->linux_gid = current->gid;
506 vol->dir_mode = S_IRWXUGO;
507 /* 2767 perms indicate mandatory locking support */
508 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
510 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
516 if(strncmp(options,"sep=",4) == 0) {
517 if(options[4] != 0) {
518 separator[0] = options[4];
521 cFYI(1,("Null separator not allowed"));
525 while ((data = strsep(&options, separator)) != NULL) {
528 if ((value = strchr(data, '=')) != NULL)
531 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
533 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
535 } else if (strnicmp(data, "user", 4) == 0) {
536 if (!value || !*value) {
538 "CIFS: invalid or missing username\n");
539 return 1; /* needs_arg; */
541 if (strnlen(value, 200) < 200) {
542 vol->username = value;
544 printk(KERN_WARNING "CIFS: username too long\n");
547 } else if (strnicmp(data, "pass", 4) == 0) {
549 vol->password = NULL;
551 } else if(value[0] == 0) {
552 /* check if string begins with double comma
553 since that would mean the password really
554 does start with a comma, and would not
555 indicate an empty string */
556 if(value[1] != separator[0]) {
557 vol->password = NULL;
561 temp_len = strlen(value);
562 /* removed password length check, NTLM passwords
563 can be arbitrarily long */
565 /* if comma in password, the string will be
566 prematurely null terminated. Commas in password are
567 specified across the cifs mount interface by a double
568 comma ie ,, and a comma used as in other cases ie ','
569 as a parameter delimiter/separator is single and due
570 to the strsep above is temporarily zeroed. */
572 /* NB: password legally can have multiple commas and
573 the only illegal character in a password is null */
575 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
577 value[temp_len] = separator[0];
578 temp_len+=2; /* move after the second comma */
579 while(value[temp_len] != 0) {
580 if (value[temp_len] == separator[0]) {
581 if (value[temp_len+1] == separator[0]) {
582 temp_len++; /* skip second comma */
584 /* single comma indicating start
591 if(value[temp_len] == 0) {
595 /* point option to start of next parm */
596 options = value + temp_len + 1;
598 /* go from value to value + temp_len condensing
599 double commas to singles. Note that this ends up
600 allocating a few bytes too many, which is ok */
601 vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
602 for(i=0,j=0;i<temp_len;i++,j++) {
603 vol->password[j] = value[i];
604 if(value[i] == separator[0] && value[i+1] == separator[0]) {
605 /* skip second comma */
609 vol->password[j] = 0;
611 vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
612 strcpy(vol->password, value);
614 } else if (strnicmp(data, "ip", 2) == 0) {
615 if (!value || !*value) {
617 } else if (strnlen(value, 35) < 35) {
620 printk(KERN_WARNING "CIFS: ip address too long\n");
623 } else if ((strnicmp(data, "unc", 3) == 0)
624 || (strnicmp(data, "target", 6) == 0)
625 || (strnicmp(data, "path", 4) == 0)) {
626 if (!value || !*value) {
628 "CIFS: invalid path to network resource\n");
629 return 1; /* needs_arg; */
631 if ((temp_len = strnlen(value, 300)) < 300) {
632 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
635 strcpy(vol->UNC,value);
636 if (strncmp(vol->UNC, "//", 2) == 0) {
639 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
641 "CIFS: UNC Path does not begin with // or \\\\ \n");
645 printk(KERN_WARNING "CIFS: UNC name too long\n");
648 } else if ((strnicmp(data, "domain", 3) == 0)
649 || (strnicmp(data, "workgroup", 5) == 0)) {
650 if (!value || !*value) {
651 printk(KERN_WARNING "CIFS: invalid domain name\n");
652 return 1; /* needs_arg; */
654 /* BB are there cases in which a comma can be valid in
655 a domain name and need special handling? */
656 if (strnlen(value, 65) < 65) {
657 vol->domainname = value;
658 cFYI(1, ("Domain name set"));
660 printk(KERN_WARNING "CIFS: domain name too long\n");
663 } else if (strnicmp(data, "iocharset", 9) == 0) {
664 if (!value || !*value) {
665 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
666 return 1; /* needs_arg; */
668 if (strnlen(value, 65) < 65) {
669 if(strnicmp(value,"default",7))
670 vol->iocharset = value;
671 /* if iocharset not set load_nls_default used by caller */
672 cFYI(1, ("iocharset set to %s",value));
674 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
677 } else if (strnicmp(data, "uid", 3) == 0) {
678 if (value && *value) {
680 simple_strtoul(value, &value, 0);
682 } else if (strnicmp(data, "gid", 3) == 0) {
683 if (value && *value) {
685 simple_strtoul(value, &value, 0);
687 } else if (strnicmp(data, "file_mode", 4) == 0) {
688 if (value && *value) {
690 simple_strtoul(value, &value, 0);
692 } else if (strnicmp(data, "dir_mode", 4) == 0) {
693 if (value && *value) {
695 simple_strtoul(value, &value, 0);
697 } else if (strnicmp(data, "dirmode", 4) == 0) {
698 if (value && *value) {
700 simple_strtoul(value, &value, 0);
702 } else if (strnicmp(data, "port", 4) == 0) {
703 if (value && *value) {
705 simple_strtoul(value, &value, 0);
707 } else if (strnicmp(data, "rsize", 5) == 0) {
708 if (value && *value) {
710 simple_strtoul(value, &value, 0);
712 } else if (strnicmp(data, "wsize", 5) == 0) {
713 if (value && *value) {
715 simple_strtoul(value, &value, 0);
717 } else if (strnicmp(data, "sockopt", 5) == 0) {
718 if (value && *value) {
720 simple_strtoul(value, &value, 0);
722 } else if (strnicmp(data, "netbiosname", 4) == 0) {
723 if (!value || !*value || (*value == ' ')) {
724 cFYI(1,("invalid (empty) netbiosname specified"));
726 memset(vol->source_rfc1001_name,0x20,15);
728 /* BB are there cases in which a comma can be
729 valid in this workstation netbios name (and need
730 special handling)? */
732 /* We do not uppercase netbiosname for user */
736 vol->source_rfc1001_name[i] = value[i];
738 /* The string has 16th byte zero still from
739 set at top of the function */
740 if((i==15) && (value[i] != 0))
741 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
743 } else if (strnicmp(data, "credentials", 4) == 0) {
745 } else if (strnicmp(data, "version", 3) == 0) {
747 } else if (strnicmp(data, "guest",5) == 0) {
749 } else if (strnicmp(data, "rw", 2) == 0) {
751 } else if ((strnicmp(data, "suid", 4) == 0) ||
752 (strnicmp(data, "nosuid", 6) == 0) ||
753 (strnicmp(data, "exec", 4) == 0) ||
754 (strnicmp(data, "noexec", 6) == 0) ||
755 (strnicmp(data, "nodev", 5) == 0) ||
756 (strnicmp(data, "noauto", 6) == 0) ||
757 (strnicmp(data, "dev", 3) == 0)) {
758 /* The mount tool or mount.cifs helper (if present)
759 uses these opts to set flags, and the flags are read
760 by the kernel vfs layer before we get here (ie
761 before read super) so there is no point trying to
762 parse these options again and set anything and it
763 is ok to just ignore them */
765 } else if (strnicmp(data, "ro", 2) == 0) {
767 } else if (strnicmp(data, "hard", 4) == 0) {
769 } else if (strnicmp(data, "soft", 4) == 0) {
771 } else if (strnicmp(data, "perm", 4) == 0) {
773 } else if (strnicmp(data, "noperm", 6) == 0) {
775 } else if (strnicmp(data, "mapchars", 8) == 0) {
777 } else if (strnicmp(data, "nomapchars", 10) == 0) {
779 } else if (strnicmp(data, "setuids", 7) == 0) {
781 } else if (strnicmp(data, "nosetuids", 9) == 0) {
783 } else if (strnicmp(data, "nohard", 6) == 0) {
785 } else if (strnicmp(data, "nosoft", 6) == 0) {
787 } else if (strnicmp(data, "nointr", 6) == 0) {
789 } else if (strnicmp(data, "intr", 4) == 0) {
791 } else if (strnicmp(data, "serverino",7) == 0) {
793 } else if (strnicmp(data, "noserverino",9) == 0) {
795 } else if (strnicmp(data, "acl",3) == 0) {
797 } else if (strnicmp(data, "noacl",5) == 0) {
799 } else if (strnicmp(data, "direct",6) == 0) {
801 } else if (strnicmp(data, "forcedirectio",13) == 0) {
803 } else if (strnicmp(data, "in6_addr",8) == 0) {
804 if (!value || !*value) {
805 vol->in6_addr = NULL;
806 } else if (strnlen(value, 49) == 48) {
807 vol->in6_addr = value;
809 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
812 } else if (strnicmp(data, "noac", 4) == 0) {
813 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
815 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
817 if (vol->UNC == NULL) {
818 if(devname == NULL) {
819 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
822 if ((temp_len = strnlen(devname, 300)) < 300) {
823 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
826 strcpy(vol->UNC,devname);
827 if (strncmp(vol->UNC, "//", 2) == 0) {
830 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
831 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
835 printk(KERN_WARNING "CIFS: UNC name too long\n");
839 if(vol->UNCip == NULL)
840 vol->UNCip = &vol->UNC[2];
845 static struct cifsSesInfo *
846 cifs_find_tcp_session(struct in_addr * target_ip_addr,
847 struct in6_addr *target_ip6_addr,
848 char *userName, struct TCP_Server_Info **psrvTcp)
850 struct list_head *tmp;
851 struct cifsSesInfo *ses;
853 read_lock(&GlobalSMBSeslock);
855 list_for_each(tmp, &GlobalSMBSessionList) {
856 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
858 if((target_ip_addr &&
859 (ses->server->addr.sockAddr.sin_addr.s_addr
860 == target_ip_addr->s_addr)) || (target_ip6_addr
861 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
862 target_ip6_addr,sizeof(*target_ip6_addr)))){
863 /* BB lock server and tcp session and increment use count here?? */
864 *psrvTcp = ses->server; /* found a match on the TCP session */
865 /* BB check if reconnection needed */
867 (ses->userName, userName,
868 MAX_USERNAME_SIZE) == 0){
869 read_unlock(&GlobalSMBSeslock);
870 return ses; /* found exact match on both tcp and SMB sessions */
874 /* else tcp and smb sessions need reconnection */
876 read_unlock(&GlobalSMBSeslock);
880 static struct cifsTconInfo *
881 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
883 struct list_head *tmp;
884 struct cifsTconInfo *tcon;
886 read_lock(&GlobalSMBSeslock);
887 list_for_each(tmp, &GlobalTreeConnectionList) {
888 cFYI(1, ("Next tcon - "));
889 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
891 if (tcon->ses->server) {
893 (" old ip addr: %x == new ip %x ?",
894 tcon->ses->server->addr.sockAddr.sin_addr.
895 s_addr, new_target_ip_addr));
896 if (tcon->ses->server->addr.sockAddr.sin_addr.
897 s_addr == new_target_ip_addr) {
898 /* BB lock tcon and server and tcp session and increment use count here? */
899 /* found a match on the TCP session */
900 /* BB check if reconnection needed */
901 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
902 tcon->treeName, uncName));
904 (tcon->treeName, uncName,
905 MAX_TREE_SIZE) == 0) {
907 ("Matched UNC, old user: %s == new: %s ?",
908 tcon->treeName, uncName));
910 (tcon->ses->userName,
912 MAX_USERNAME_SIZE) == 0) {
913 read_unlock(&GlobalSMBSeslock);
914 return tcon;/* also matched user (smb session)*/
921 read_unlock(&GlobalSMBSeslock);
926 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
927 const char *old_path, const struct nls_table *nls_codepage,
930 unsigned char *referrals = NULL;
931 unsigned int num_referrals;
934 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
935 &num_referrals, &referrals, remap);
937 /* BB Add in code to: if valid refrl, if not ip address contact
938 the helper that resolves tcp names, mount to it, try to
939 tcon to it unmount it if fail */
948 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
949 const char *old_path, const struct nls_table *nls_codepage,
950 unsigned int *pnum_referrals,
951 unsigned char ** preferrals, int remap)
958 if (pSesInfo->ipc_tid == 0) {
959 temp_unc = kmalloc(2 /* for slashes */ +
960 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
961 + 1 + 4 /* slash IPC$ */ + 2,
963 if (temp_unc == NULL)
967 strcpy(temp_unc + 2, pSesInfo->serverName);
968 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
969 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
971 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
975 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
976 pnum_referrals, nls_codepage, remap);
981 /* See RFC1001 section 14 on representation of Netbios names */
982 static void rfc1002mangle(char * target,char * source, unsigned int length)
986 for(i=0,j=0;i<(length);i++) {
987 /* mask a nibble at a time and encode */
988 target[j] = 'A' + (0x0F & (source[i] >> 4));
989 target[j+1] = 'A' + (0x0F & source[i]);
997 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1002 __be16 orig_port = 0;
1004 if(*csocket == NULL) {
1005 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1007 cERROR(1, ("Error %d creating socket",rc));
1011 /* BB other socket options to set KEEPALIVE, NODELAY? */
1012 cFYI(1,("Socket created"));
1013 (*csocket)->sk->sk_allocation = GFP_NOFS;
1017 psin_server->sin_family = AF_INET;
1018 if(psin_server->sin_port) { /* user overrode default port */
1019 rc = (*csocket)->ops->connect(*csocket,
1020 (struct sockaddr *) psin_server,
1021 sizeof (struct sockaddr_in),0);
1027 /* save original port so we can retry user specified port
1028 later if fall back ports fail this time */
1029 orig_port = psin_server->sin_port;
1031 /* do not retry on the same port we just failed on */
1032 if(psin_server->sin_port != htons(CIFS_PORT)) {
1033 psin_server->sin_port = htons(CIFS_PORT);
1035 rc = (*csocket)->ops->connect(*csocket,
1036 (struct sockaddr *) psin_server,
1037 sizeof (struct sockaddr_in),0);
1043 psin_server->sin_port = htons(RFC1001_PORT);
1044 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1045 psin_server, sizeof (struct sockaddr_in),0);
1050 /* give up here - unless we want to retry on different
1051 protocol families some day */
1054 psin_server->sin_port = orig_port;
1055 cFYI(1,("Error %d connecting to server via ipv4",rc));
1056 sock_release(*csocket);
1060 /* Eventually check for other socket options to change from
1061 the default. sock_setsockopt not used because it expects
1062 user space buffer */
1063 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1065 /* send RFC1001 sessinit */
1067 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1068 /* some servers require RFC1001 sessinit before sending
1069 negprot - BB check reconnection in case where second
1070 sessinit is sent but no second negprot */
1071 struct rfc1002_session_packet * ses_init_buf;
1072 struct smb_hdr * smb_buf;
1073 ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1075 ses_init_buf->trailer.session_req.called_len = 32;
1076 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1077 DEFAULT_CIFS_CALLED_NAME,16);
1078 ses_init_buf->trailer.session_req.calling_len = 32;
1079 /* calling name ends in null (byte 16) from old smb
1081 if(netbios_name && (netbios_name[0] !=0)) {
1082 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1085 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1086 "LINUX_CIFS_CLNT",16);
1088 ses_init_buf->trailer.session_req.scope1 = 0;
1089 ses_init_buf->trailer.session_req.scope2 = 0;
1090 smb_buf = (struct smb_hdr *)ses_init_buf;
1091 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1092 smb_buf->smb_buf_length = 0x81000044;
1093 rc = smb_send(*csocket, smb_buf, 0x44,
1094 (struct sockaddr *)psin_server);
1095 kfree(ses_init_buf);
1097 /* else the negprot may still work without this
1098 even though malloc failed */
1106 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1110 __be16 orig_port = 0;
1112 if(*csocket == NULL) {
1113 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1115 cERROR(1, ("Error %d creating ipv6 socket",rc));
1119 /* BB other socket options to set KEEPALIVE, NODELAY? */
1120 cFYI(1,("ipv6 Socket created"));
1121 (*csocket)->sk->sk_allocation = GFP_NOFS;
1125 psin_server->sin6_family = AF_INET6;
1127 if(psin_server->sin6_port) { /* user overrode default port */
1128 rc = (*csocket)->ops->connect(*csocket,
1129 (struct sockaddr *) psin_server,
1130 sizeof (struct sockaddr_in6),0);
1136 /* save original port so we can retry user specified port
1137 later if fall back ports fail this time */
1139 orig_port = psin_server->sin6_port;
1140 /* do not retry on the same port we just failed on */
1141 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1142 psin_server->sin6_port = htons(CIFS_PORT);
1144 rc = (*csocket)->ops->connect(*csocket,
1145 (struct sockaddr *) psin_server,
1146 sizeof (struct sockaddr_in6),0);
1152 psin_server->sin6_port = htons(RFC1001_PORT);
1153 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1154 psin_server, sizeof (struct sockaddr_in6),0);
1159 /* give up here - unless we want to retry on different
1160 protocol families some day */
1163 psin_server->sin6_port = orig_port;
1164 cFYI(1,("Error %d connecting to server via ipv6",rc));
1165 sock_release(*csocket);
1169 /* Eventually check for other socket options to change from
1170 the default. sock_setsockopt not used because it expects
1171 user space buffer */
1172 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1178 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1179 char *mount_data, const char *devname)
1183 int address_type = AF_INET;
1184 struct socket *csocket = NULL;
1185 struct sockaddr_in sin_server;
1186 struct sockaddr_in6 sin_server6;
1187 struct smb_vol volume_info;
1188 struct cifsSesInfo *pSesInfo = NULL;
1189 struct cifsSesInfo *existingCifsSes = NULL;
1190 struct cifsTconInfo *tcon = NULL;
1191 struct TCP_Server_Info *srvTcp = NULL;
1195 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1197 memset(&volume_info,0,sizeof(struct smb_vol));
1198 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1200 kfree(volume_info.UNC);
1201 if(volume_info.password)
1202 kfree(volume_info.password);
1207 if (volume_info.username) {
1208 /* BB fixme parse for domain name here */
1209 cFYI(1, ("Username: %s ", volume_info.username));
1212 cifserror("No username specified ");
1213 /* In userspace mount helper we can get user name from alternate
1214 locations such as env variables and files on disk */
1216 kfree(volume_info.UNC);
1217 if(volume_info.password)
1218 kfree(volume_info.password);
1223 if (volume_info.UNCip && volume_info.UNC) {
1224 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1227 /* not ipv4 address, try ipv6 */
1228 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1230 address_type = AF_INET6;
1232 address_type = AF_INET;
1236 /* we failed translating address */
1238 kfree(volume_info.UNC);
1239 if(volume_info.password)
1240 kfree(volume_info.password);
1245 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1248 } else if (volume_info.UNCip){
1249 /* BB using ip addr as server name connect to the DFS root below */
1250 cERROR(1,("Connecting to DFS root not implemented yet"));
1252 kfree(volume_info.UNC);
1253 if(volume_info.password)
1254 kfree(volume_info.password);
1257 } else /* which servers DFS root would we conect to */ {
1259 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1261 kfree(volume_info.UNC);
1262 if(volume_info.password)
1263 kfree(volume_info.password);
1268 /* this is needed for ASCII cp to Unicode converts */
1269 if(volume_info.iocharset == NULL) {
1270 cifs_sb->local_nls = load_nls_default();
1271 /* load_nls_default can not return null */
1273 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1274 if(cifs_sb->local_nls == NULL) {
1275 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1277 kfree(volume_info.UNC);
1278 if(volume_info.password)
1279 kfree(volume_info.password);
1285 if(address_type == AF_INET)
1286 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1287 NULL /* no ipv6 addr */,
1288 volume_info.username, &srvTcp);
1289 else if(address_type == AF_INET6)
1290 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1291 &sin_server6.sin6_addr,
1292 volume_info.username, &srvTcp);
1295 kfree(volume_info.UNC);
1296 if(volume_info.password)
1297 kfree(volume_info.password);
1304 cFYI(1, ("Existing tcp session with server found "));
1305 } else { /* create socket */
1306 if(volume_info.port)
1307 sin_server.sin_port = htons(volume_info.port);
1309 sin_server.sin_port = 0;
1310 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1313 ("Error connecting to IPv4 socket. Aborting operation"));
1315 sock_release(csocket);
1317 kfree(volume_info.UNC);
1318 if(volume_info.password)
1319 kfree(volume_info.password);
1324 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1325 if (srvTcp == NULL) {
1327 sock_release(csocket);
1329 kfree(volume_info.UNC);
1330 if(volume_info.password)
1331 kfree(volume_info.password);
1335 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1336 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1337 atomic_set(&srvTcp->inFlight,0);
1338 /* BB Add code for ipv6 case too */
1339 srvTcp->ssocket = csocket;
1340 srvTcp->protocolType = IPV4;
1341 init_waitqueue_head(&srvTcp->response_q);
1342 init_waitqueue_head(&srvTcp->request_q);
1343 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1344 /* at this point we are the only ones with the pointer
1345 to the struct since the kernel thread not created yet
1346 so no need to spinlock this init of tcpStatus */
1347 srvTcp->tcpStatus = CifsNew;
1348 init_MUTEX(&srvTcp->tcpSem);
1349 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1350 CLONE_FS | CLONE_FILES | CLONE_VM);
1353 sock_release(csocket);
1355 kfree(volume_info.UNC);
1356 if(volume_info.password)
1357 kfree(volume_info.password);
1362 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1363 srvTcp->sequence_number = 0;
1367 if (existingCifsSes) {
1368 pSesInfo = existingCifsSes;
1369 cFYI(1, ("Existing smb sess found "));
1370 if(volume_info.password)
1371 kfree(volume_info.password);
1372 /* volume_info.UNC freed at end of function */
1374 cFYI(1, ("Existing smb sess not found "));
1375 pSesInfo = sesInfoAlloc();
1376 if (pSesInfo == NULL)
1379 pSesInfo->server = srvTcp;
1380 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1381 NIPQUAD(sin_server.sin_addr.s_addr));
1385 /* volume_info.password freed at unmount */
1386 if (volume_info.password)
1387 pSesInfo->password = volume_info.password;
1388 if (volume_info.username)
1389 strncpy(pSesInfo->userName,
1390 volume_info.username,MAX_USERNAME_SIZE);
1391 if (volume_info.domainname)
1392 strncpy(pSesInfo->domainName,
1393 volume_info.domainname,MAX_USERNAME_SIZE);
1394 pSesInfo->linux_uid = volume_info.linux_uid;
1395 down(&pSesInfo->sesSem);
1396 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1397 up(&pSesInfo->sesSem);
1399 atomic_inc(&srvTcp->socketUseCount);
1401 if(volume_info.password)
1402 kfree(volume_info.password);
1405 /* search for existing tcon to this server share */
1407 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1408 cifs_sb->rsize = volume_info.rsize;
1410 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1411 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1412 cifs_sb->wsize = volume_info.wsize;
1414 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1415 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1416 cifs_sb->rsize = PAGE_CACHE_SIZE;
1417 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1419 cifs_sb->mnt_uid = volume_info.linux_uid;
1420 cifs_sb->mnt_gid = volume_info.linux_gid;
1421 cifs_sb->mnt_file_mode = volume_info.file_mode;
1422 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1423 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1425 if(volume_info.noperm)
1426 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1427 if(volume_info.setuids)
1428 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1429 if(volume_info.server_ino)
1430 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1431 if(volume_info.remap)
1432 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1433 if(volume_info.no_xattr)
1434 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1435 if(volume_info.direct_io) {
1436 cERROR(1,("mounting share using direct i/o"));
1437 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1441 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1442 volume_info.username);
1444 cFYI(1, ("Found match on UNC path "));
1445 /* we can have only one retry value for a connection
1446 to a share so for resources mounted more than once
1447 to the same server share the last value passed in
1448 for the retry flag is used */
1449 tcon->retry = volume_info.retry;
1451 tcon = tconInfoAlloc();
1455 /* check for null share name ie connect to dfs root */
1457 /* BB check if this works for exactly length three strings */
1458 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1459 && (strchr(volume_info.UNC + 3, '/') ==
1461 rc = connect_to_dfs_path(xid, pSesInfo,
1462 "", cifs_sb->local_nls,
1463 cifs_sb->mnt_cifs_flags &
1464 CIFS_MOUNT_MAP_SPECIAL_CHR);
1466 kfree(volume_info.UNC);
1470 rc = CIFSTCon(xid, pSesInfo,
1472 tcon, cifs_sb->local_nls);
1473 cFYI(1, ("CIFS Tcon rc = %d", rc));
1476 atomic_inc(&pSesInfo->inUse);
1477 tcon->retry = volume_info.retry;
1483 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1484 sb->s_maxbytes = (u64) 1 << 63;
1486 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1489 sb->s_time_gran = 100;
1491 /* on error free sesinfo and tcon struct if needed */
1493 /* if session setup failed, use count is zero but
1494 we still need to free cifsd thread */
1495 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1496 spin_lock(&GlobalMid_Lock);
1497 srvTcp->tcpStatus = CifsExiting;
1498 spin_unlock(&GlobalMid_Lock);
1500 send_sig(SIGKILL,srvTcp->tsk,1);
1502 /* If find_unc succeeded then rc == 0 so we can not end */
1503 if (tcon) /* up accidently freeing someone elses tcon struct */
1505 if (existingCifsSes == NULL) {
1507 if ((pSesInfo->server) &&
1508 (pSesInfo->status == CifsGood)) {
1510 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1511 /* if the socketUseCount is now zero */
1512 if((temp_rc == -ESHUTDOWN) &&
1513 (pSesInfo->server->tsk))
1514 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1516 cFYI(1, ("No session or bad tcon"));
1517 sesInfoFree(pSesInfo);
1518 /* pSesInfo = NULL; */
1522 atomic_inc(&tcon->useCount);
1523 cifs_sb->tcon = tcon;
1524 tcon->ses = pSesInfo;
1526 /* do not care if following two calls succeed - informational only */
1527 CIFSSMBQFSDeviceInfo(xid, tcon);
1528 CIFSSMBQFSAttributeInfo(xid, tcon);
1529 if (tcon->ses->capabilities & CAP_UNIX) {
1530 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1531 if(!volume_info.no_psx_acl) {
1532 if(CIFS_UNIX_POSIX_ACL_CAP &
1533 le64_to_cpu(tcon->fsUnixInfo.Capability))
1534 cFYI(1,("server negotiated posix acl support"));
1535 sb->s_flags |= MS_POSIXACL;
1541 /* volume_info.password is freed above when existing session found
1542 (in which case it is not needed anymore) but when new sesion is created
1543 the password ptr is put in the new session structure (in which case the
1544 password will be freed at unmount time) */
1546 kfree(volume_info.UNC);
1552 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1553 char session_key[CIFS_SESSION_KEY_SIZE],
1554 const struct nls_table *nls_codepage)
1556 struct smb_hdr *smb_buffer;
1557 struct smb_hdr *smb_buffer_response;
1558 SESSION_SETUP_ANDX *pSMB;
1559 SESSION_SETUP_ANDX *pSMBr;
1564 int remaining_words = 0;
1565 int bytes_returned = 0;
1570 cFYI(1, ("In sesssetup "));
1573 user = ses->userName;
1574 domain = ses->domainName;
1575 smb_buffer = cifs_buf_get();
1576 if (smb_buffer == NULL) {
1579 smb_buffer_response = smb_buffer;
1580 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1582 /* send SMBsessionSetup here */
1583 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1584 NULL /* no tCon exists yet */ , 13 /* wct */ );
1586 pSMB->req_no_secext.AndXCommand = 0xFF;
1587 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1588 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1590 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1591 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1593 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1594 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
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 /* convert number of 16 bit words to bytes */
1632 bcc_ptr += 2 * bytes_returned;
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,
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 if(strncmp(ses->serverNOS,
1737 "NT LAN Manager 4",16) == 0) {
1738 cFYI(1,("NT4 server"));
1739 ses->flags |= CIFS_SES_NT4;
1741 remaining_words -= len + 1;
1742 if (remaining_words > 0) {
1743 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1744 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1746 cifs_kcalloc(2*(len+1),GFP_KERNEL);
1747 cifs_strfromUCS_le(ses->serverDomain,
1748 (wchar_t *)bcc_ptr,len,nls_codepage);
1749 bcc_ptr += 2 * (len + 1);
1750 ses->serverDomain[2*len] = 0;
1751 ses->serverDomain[1+(2*len)] = 0;
1752 } /* else no more room so create dummy domain string */
1757 } else { /* no room so create dummy domain and NOS string */
1759 cifs_kcalloc(2, GFP_KERNEL);
1761 cifs_kcalloc(2, GFP_KERNEL);
1763 } else { /* ASCII */
1764 len = strnlen(bcc_ptr, 1024);
1765 if (((long) bcc_ptr + len) - (long)
1766 pByteArea(smb_buffer_response)
1767 <= BCC(smb_buffer_response)) {
1768 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1769 strncpy(ses->serverOS,bcc_ptr, len);
1772 bcc_ptr[0] = 0; /* null terminate the string */
1775 len = strnlen(bcc_ptr, 1024);
1776 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1777 strncpy(ses->serverNOS, bcc_ptr, len);
1782 len = strnlen(bcc_ptr, 1024);
1783 ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
1784 strncpy(ses->serverDomain, bcc_ptr, len);
1790 ("Variable field of length %d extends beyond end of smb ",
1795 (" Security Blob Length extends beyond end of SMB"));
1799 (" Invalid Word count %d: ",
1800 smb_buffer_response->WordCount));
1805 cifs_buf_release(smb_buffer);
1811 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1812 char *SecurityBlob,int SecurityBlobLength,
1813 const struct nls_table *nls_codepage)
1815 struct smb_hdr *smb_buffer;
1816 struct smb_hdr *smb_buffer_response;
1817 SESSION_SETUP_ANDX *pSMB;
1818 SESSION_SETUP_ANDX *pSMBr;
1823 int remaining_words = 0;
1824 int bytes_returned = 0;
1829 cFYI(1, ("In spnego sesssetup "));
1832 user = ses->userName;
1833 domain = ses->domainName;
1835 smb_buffer = cifs_buf_get();
1836 if (smb_buffer == NULL) {
1839 smb_buffer_response = smb_buffer;
1840 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1842 /* send SMBsessionSetup here */
1843 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1844 NULL /* no tCon exists yet */ , 12 /* wct */ );
1845 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1846 pSMB->req.AndXCommand = 0xFF;
1847 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1848 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1850 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1851 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1853 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1854 CAP_EXTENDED_SECURITY;
1855 if (ses->capabilities & CAP_UNICODE) {
1856 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1857 capabilities |= CAP_UNICODE;
1859 if (ses->capabilities & CAP_STATUS32) {
1860 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1861 capabilities |= CAP_STATUS32;
1863 if (ses->capabilities & CAP_DFS) {
1864 smb_buffer->Flags2 |= SMBFLG2_DFS;
1865 capabilities |= CAP_DFS;
1867 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1869 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1870 bcc_ptr = pByteArea(smb_buffer);
1871 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1872 bcc_ptr += SecurityBlobLength;
1874 if (ses->capabilities & CAP_UNICODE) {
1875 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1880 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1881 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1882 bcc_ptr += 2; /* trailing null */
1885 cifs_strtoUCS((wchar_t *) bcc_ptr,
1886 "CIFS_LINUX_DOM", 32, nls_codepage);
1889 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1891 bcc_ptr += 2 * bytes_returned;
1894 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1896 bcc_ptr += 2 * bytes_returned;
1898 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
1900 bcc_ptr += 2 * bytes_returned;
1903 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1905 bcc_ptr += 2 * bytes_returned;
1908 strncpy(bcc_ptr, user, 200);
1909 bcc_ptr += strnlen(user, 200);
1912 if (domain == NULL) {
1913 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1914 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1916 strncpy(bcc_ptr, domain, 64);
1917 bcc_ptr += strnlen(domain, 64);
1921 strcpy(bcc_ptr, "Linux version ");
1922 bcc_ptr += strlen("Linux version ");
1923 strcpy(bcc_ptr, system_utsname.release);
1924 bcc_ptr += strlen(system_utsname.release) + 1;
1925 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1926 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1928 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1929 smb_buffer->smb_buf_length += count;
1930 pSMB->req.ByteCount = cpu_to_le16(count);
1932 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1933 &bytes_returned, 1);
1935 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1936 } else if ((smb_buffer_response->WordCount == 3)
1937 || (smb_buffer_response->WordCount == 4)) {
1938 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1940 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1941 if (action & GUEST_LOGIN)
1942 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1944 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1945 cFYI(1, ("UID = %d ", ses->Suid));
1946 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
1948 /* BB Fix below to make endian neutral !! */
1950 if ((pSMBr->resp.hdr.WordCount == 3)
1951 || ((pSMBr->resp.hdr.WordCount == 4)
1953 pSMBr->resp.ByteCount))) {
1954 if (pSMBr->resp.hdr.WordCount == 4) {
1958 ("Security Blob Length %d ",
1962 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1963 if ((long) (bcc_ptr) % 2) {
1965 (BCC(smb_buffer_response)
1967 bcc_ptr++; /* Unicode strings must be word aligned */
1971 (smb_buffer_response) / 2;
1974 UniStrnlen((wchar_t *) bcc_ptr,
1975 remaining_words - 1);
1976 /* We look for obvious messed up bcc or strings in response so we do not go off
1977 the end since (at least) WIN2K and Windows XP have a major bug in not null
1978 terminating last Unicode string in response */
1980 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1981 cifs_strfromUCS_le(ses->serverOS,
1985 bcc_ptr += 2 * (len + 1);
1986 remaining_words -= len + 1;
1987 ses->serverOS[2 * len] = 0;
1988 ses->serverOS[1 + (2 * len)] = 0;
1989 if (remaining_words > 0) {
1990 len = UniStrnlen((wchar_t *)bcc_ptr,
1994 cifs_kcalloc(2 * (len + 1),
1996 cifs_strfromUCS_le(ses->serverNOS,
2000 bcc_ptr += 2 * (len + 1);
2001 ses->serverNOS[2 * len] = 0;
2002 ses->serverNOS[1 + (2 * len)] = 0;
2003 remaining_words -= len + 1;
2004 if (remaining_words > 0) {
2005 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2006 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2007 ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
2008 cifs_strfromUCS_le(ses->serverDomain,
2012 bcc_ptr += 2*(len+1);
2013 ses->serverDomain[2*len] = 0;
2014 ses->serverDomain[1+(2*len)] = 0;
2015 } /* else no more room so create dummy domain string */
2018 cifs_kcalloc(2,GFP_KERNEL);
2019 } else { /* no room so create dummy domain and NOS string */
2020 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2021 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2023 } else { /* ASCII */
2025 len = strnlen(bcc_ptr, 1024);
2026 if (((long) bcc_ptr + len) - (long)
2027 pByteArea(smb_buffer_response)
2028 <= BCC(smb_buffer_response)) {
2029 ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
2030 strncpy(ses->serverOS, bcc_ptr, len);
2033 bcc_ptr[0] = 0; /* null terminate the string */
2036 len = strnlen(bcc_ptr, 1024);
2037 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2038 strncpy(ses->serverNOS, bcc_ptr, len);
2043 len = strnlen(bcc_ptr, 1024);
2044 ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
2045 strncpy(ses->serverDomain, bcc_ptr, len);
2051 ("Variable field of length %d extends beyond end of smb ",
2056 (" Security Blob Length extends beyond end of SMB"));
2059 cERROR(1, ("No session structure passed in."));
2063 (" Invalid Word count %d: ",
2064 smb_buffer_response->WordCount));
2069 cifs_buf_release(smb_buffer);
2075 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2076 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2077 const struct nls_table *nls_codepage)
2079 struct smb_hdr *smb_buffer;
2080 struct smb_hdr *smb_buffer_response;
2081 SESSION_SETUP_ANDX *pSMB;
2082 SESSION_SETUP_ANDX *pSMBr;
2086 int remaining_words = 0;
2087 int bytes_returned = 0;
2089 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2090 PNEGOTIATE_MESSAGE SecurityBlob;
2091 PCHALLENGE_MESSAGE SecurityBlob2;
2092 __u32 negotiate_flags, capabilities;
2095 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2098 domain = ses->domainName;
2099 *pNTLMv2_flag = FALSE;
2100 smb_buffer = cifs_buf_get();
2101 if (smb_buffer == NULL) {
2104 smb_buffer_response = smb_buffer;
2105 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2106 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2108 /* send SMBsessionSetup here */
2109 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2110 NULL /* no tCon exists yet */ , 12 /* wct */ );
2111 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2112 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2114 pSMB->req.AndXCommand = 0xFF;
2115 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2116 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2118 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2119 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2121 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2122 CAP_EXTENDED_SECURITY;
2123 if (ses->capabilities & CAP_UNICODE) {
2124 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2125 capabilities |= CAP_UNICODE;
2127 if (ses->capabilities & CAP_STATUS32) {
2128 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2129 capabilities |= CAP_STATUS32;
2131 if (ses->capabilities & CAP_DFS) {
2132 smb_buffer->Flags2 |= SMBFLG2_DFS;
2133 capabilities |= CAP_DFS;
2135 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2137 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2138 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2139 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2140 SecurityBlob->MessageType = NtLmNegotiate;
2142 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2143 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2144 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2146 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2148 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2149 /* setup pointers to domain name and workstation name */
2150 bcc_ptr += SecurityBlobLength;
2152 SecurityBlob->WorkstationName.Buffer = 0;
2153 SecurityBlob->WorkstationName.Length = 0;
2154 SecurityBlob->WorkstationName.MaximumLength = 0;
2156 if (domain == NULL) {
2157 SecurityBlob->DomainName.Buffer = 0;
2158 SecurityBlob->DomainName.Length = 0;
2159 SecurityBlob->DomainName.MaximumLength = 0;
2162 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2163 strncpy(bcc_ptr, domain, 63);
2164 len = strnlen(domain, 64);
2165 SecurityBlob->DomainName.MaximumLength =
2167 SecurityBlob->DomainName.Buffer =
2168 cpu_to_le32((long) &SecurityBlob->
2170 (long) &SecurityBlob->Signature);
2172 SecurityBlobLength += len;
2173 SecurityBlob->DomainName.Length =
2176 if (ses->capabilities & CAP_UNICODE) {
2177 if ((long) bcc_ptr % 2) {
2183 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2185 bcc_ptr += 2 * bytes_returned;
2187 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2189 bcc_ptr += 2 * bytes_returned;
2190 bcc_ptr += 2; /* null terminate Linux version */
2192 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2194 bcc_ptr += 2 * bytes_returned;
2197 bcc_ptr += 2; /* null terminate network opsys string */
2200 bcc_ptr += 2; /* null domain */
2201 } else { /* ASCII */
2202 strcpy(bcc_ptr, "Linux version ");
2203 bcc_ptr += strlen("Linux version ");
2204 strcpy(bcc_ptr, system_utsname.release);
2205 bcc_ptr += strlen(system_utsname.release) + 1;
2206 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2207 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2208 bcc_ptr++; /* empty domain field */
2211 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2212 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2213 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2214 smb_buffer->smb_buf_length += count;
2215 pSMB->req.ByteCount = cpu_to_le16(count);
2217 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2218 &bytes_returned, 1);
2220 if (smb_buffer_response->Status.CifsError ==
2221 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2225 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2226 } else if ((smb_buffer_response->WordCount == 3)
2227 || (smb_buffer_response->WordCount == 4)) {
2228 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2229 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2231 if (action & GUEST_LOGIN)
2232 cFYI(1, (" Guest login"));
2233 /* Do we want to set anything in SesInfo struct when guest login? */
2235 bcc_ptr = pByteArea(smb_buffer_response);
2236 /* response can have either 3 or 4 word count - Samba sends 3 */
2238 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2239 if (SecurityBlob2->MessageType != NtLmChallenge) {
2241 ("Unexpected NTLMSSP message type received %d",
2242 SecurityBlob2->MessageType));
2244 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2245 cFYI(1, ("UID = %d ", ses->Suid));
2246 if ((pSMBr->resp.hdr.WordCount == 3)
2247 || ((pSMBr->resp.hdr.WordCount == 4)
2249 pSMBr->resp.ByteCount))) {
2251 if (pSMBr->resp.hdr.WordCount == 4) {
2252 bcc_ptr += blob_len;
2254 ("Security Blob Length %d ",
2258 cFYI(1, ("NTLMSSP Challenge rcvd "));
2260 memcpy(ses->server->cryptKey,
2261 SecurityBlob2->Challenge,
2262 CIFS_CRYPTO_KEY_SIZE);
2263 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2264 *pNTLMv2_flag = TRUE;
2266 if((SecurityBlob2->NegotiateFlags &
2267 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2268 || (sign_CIFS_PDUs > 1))
2269 ses->server->secMode |=
2270 SECMODE_SIGN_REQUIRED;
2271 if ((SecurityBlob2->NegotiateFlags &
2272 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2273 ses->server->secMode |=
2274 SECMODE_SIGN_ENABLED;
2276 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2277 if ((long) (bcc_ptr) % 2) {
2279 (BCC(smb_buffer_response)
2281 bcc_ptr++; /* Unicode strings must be word aligned */
2285 (smb_buffer_response) / 2;
2288 UniStrnlen((wchar_t *) bcc_ptr,
2289 remaining_words - 1);
2290 /* We look for obvious messed up bcc or strings in response so we do not go off
2291 the end since (at least) WIN2K and Windows XP have a major bug in not null
2292 terminating last Unicode string in response */
2294 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2295 cifs_strfromUCS_le(ses->serverOS,
2299 bcc_ptr += 2 * (len + 1);
2300 remaining_words -= len + 1;
2301 ses->serverOS[2 * len] = 0;
2302 ses->serverOS[1 + (2 * len)] = 0;
2303 if (remaining_words > 0) {
2304 len = UniStrnlen((wchar_t *)
2309 cifs_kcalloc(2 * (len + 1),
2311 cifs_strfromUCS_le(ses->
2317 bcc_ptr += 2 * (len + 1);
2318 ses->serverNOS[2 * len] = 0;
2321 remaining_words -= len + 1;
2322 if (remaining_words > 0) {
2323 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2324 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2349 } /* else no more room so create dummy domain string */
2354 } else { /* no room so create dummy domain and NOS string */
2356 cifs_kcalloc(2, GFP_KERNEL);
2358 cifs_kcalloc(2, GFP_KERNEL);
2360 } else { /* ASCII */
2361 len = strnlen(bcc_ptr, 1024);
2362 if (((long) bcc_ptr + len) - (long)
2363 pByteArea(smb_buffer_response)
2364 <= BCC(smb_buffer_response)) {
2366 cifs_kcalloc(len + 1,
2368 strncpy(ses->serverOS,
2372 bcc_ptr[0] = 0; /* null terminate string */
2375 len = strnlen(bcc_ptr, 1024);
2377 cifs_kcalloc(len + 1,
2379 strncpy(ses->serverNOS, bcc_ptr, len);
2384 len = strnlen(bcc_ptr, 1024);
2386 cifs_kcalloc(len + 1,
2388 strncpy(ses->serverDomain, bcc_ptr, len);
2394 ("Variable field of length %d extends beyond end of smb ",
2399 (" Security Blob Length extends beyond end of SMB"));
2402 cERROR(1, ("No session structure passed in."));
2406 (" Invalid Word count %d: ",
2407 smb_buffer_response->WordCount));
2412 cifs_buf_release(smb_buffer);
2417 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2418 char *ntlm_session_key, int ntlmv2_flag,
2419 const struct nls_table *nls_codepage)
2421 struct smb_hdr *smb_buffer;
2422 struct smb_hdr *smb_buffer_response;
2423 SESSION_SETUP_ANDX *pSMB;
2424 SESSION_SETUP_ANDX *pSMBr;
2429 int remaining_words = 0;
2430 int bytes_returned = 0;
2432 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2433 PAUTHENTICATE_MESSAGE SecurityBlob;
2434 __u32 negotiate_flags, capabilities;
2437 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2440 user = ses->userName;
2441 domain = ses->domainName;
2442 smb_buffer = cifs_buf_get();
2443 if (smb_buffer == NULL) {
2446 smb_buffer_response = smb_buffer;
2447 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2448 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2450 /* send SMBsessionSetup here */
2451 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2452 NULL /* no tCon exists yet */ , 12 /* wct */ );
2453 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2454 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2455 pSMB->req.AndXCommand = 0xFF;
2456 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2457 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2459 pSMB->req.hdr.Uid = ses->Suid;
2461 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2462 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2464 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2465 CAP_EXTENDED_SECURITY;
2466 if (ses->capabilities & CAP_UNICODE) {
2467 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2468 capabilities |= CAP_UNICODE;
2470 if (ses->capabilities & CAP_STATUS32) {
2471 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2472 capabilities |= CAP_STATUS32;
2474 if (ses->capabilities & CAP_DFS) {
2475 smb_buffer->Flags2 |= SMBFLG2_DFS;
2476 capabilities |= CAP_DFS;
2478 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2480 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2481 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2482 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2483 SecurityBlob->MessageType = NtLmAuthenticate;
2484 bcc_ptr += SecurityBlobLength;
2486 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2487 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2488 0x80000000 | NTLMSSP_NEGOTIATE_128;
2490 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2492 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2494 /* setup pointers to domain name and workstation name */
2496 SecurityBlob->WorkstationName.Buffer = 0;
2497 SecurityBlob->WorkstationName.Length = 0;
2498 SecurityBlob->WorkstationName.MaximumLength = 0;
2499 SecurityBlob->SessionKey.Length = 0;
2500 SecurityBlob->SessionKey.MaximumLength = 0;
2501 SecurityBlob->SessionKey.Buffer = 0;
2503 SecurityBlob->LmChallengeResponse.Length = 0;
2504 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2505 SecurityBlob->LmChallengeResponse.Buffer = 0;
2507 SecurityBlob->NtChallengeResponse.Length =
2508 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2509 SecurityBlob->NtChallengeResponse.MaximumLength =
2510 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2511 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2512 SecurityBlob->NtChallengeResponse.Buffer =
2513 cpu_to_le32(SecurityBlobLength);
2514 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2515 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2517 if (ses->capabilities & CAP_UNICODE) {
2518 if (domain == NULL) {
2519 SecurityBlob->DomainName.Buffer = 0;
2520 SecurityBlob->DomainName.Length = 0;
2521 SecurityBlob->DomainName.MaximumLength = 0;
2524 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2527 SecurityBlob->DomainName.MaximumLength =
2529 SecurityBlob->DomainName.Buffer =
2530 cpu_to_le32(SecurityBlobLength);
2532 SecurityBlobLength += len;
2533 SecurityBlob->DomainName.Length =
2537 SecurityBlob->UserName.Buffer = 0;
2538 SecurityBlob->UserName.Length = 0;
2539 SecurityBlob->UserName.MaximumLength = 0;
2542 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2545 SecurityBlob->UserName.MaximumLength =
2547 SecurityBlob->UserName.Buffer =
2548 cpu_to_le32(SecurityBlobLength);
2550 SecurityBlobLength += len;
2551 SecurityBlob->UserName.Length =
2555 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2556 SecurityBlob->WorkstationName.Length *= 2;
2557 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2558 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2559 bcc_ptr += SecurityBlob->WorkstationName.Length;
2560 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2561 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2563 if ((long) bcc_ptr % 2) {
2568 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2570 bcc_ptr += 2 * bytes_returned;
2572 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2574 bcc_ptr += 2 * bytes_returned;
2575 bcc_ptr += 2; /* null term version string */
2577 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2579 bcc_ptr += 2 * bytes_returned;
2582 bcc_ptr += 2; /* null terminate network opsys string */
2585 bcc_ptr += 2; /* null domain */
2586 } else { /* ASCII */
2587 if (domain == NULL) {
2588 SecurityBlob->DomainName.Buffer = 0;
2589 SecurityBlob->DomainName.Length = 0;
2590 SecurityBlob->DomainName.MaximumLength = 0;
2593 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2594 strncpy(bcc_ptr, domain, 63);
2595 len = strnlen(domain, 64);
2596 SecurityBlob->DomainName.MaximumLength =
2598 SecurityBlob->DomainName.Buffer =
2599 cpu_to_le32(SecurityBlobLength);
2601 SecurityBlobLength += len;
2602 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2605 SecurityBlob->UserName.Buffer = 0;
2606 SecurityBlob->UserName.Length = 0;
2607 SecurityBlob->UserName.MaximumLength = 0;
2610 strncpy(bcc_ptr, user, 63);
2611 len = strnlen(user, 64);
2612 SecurityBlob->UserName.MaximumLength =
2614 SecurityBlob->UserName.Buffer =
2615 cpu_to_le32(SecurityBlobLength);
2617 SecurityBlobLength += len;
2618 SecurityBlob->UserName.Length = cpu_to_le16(len);
2620 /* BB fill in our workstation name if known BB */
2622 strcpy(bcc_ptr, "Linux version ");
2623 bcc_ptr += strlen("Linux version ");
2624 strcpy(bcc_ptr, system_utsname.release);
2625 bcc_ptr += strlen(system_utsname.release) + 1;
2626 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2627 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2628 bcc_ptr++; /* null domain */
2631 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2632 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2633 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2634 smb_buffer->smb_buf_length += count;
2635 pSMB->req.ByteCount = cpu_to_le16(count);
2637 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2638 &bytes_returned, 1);
2640 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2641 } else if ((smb_buffer_response->WordCount == 3)
2642 || (smb_buffer_response->WordCount == 4)) {
2643 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2645 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2646 if (action & GUEST_LOGIN)
2647 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2648 /* if(SecurityBlob2->MessageType != NtLm??){
2649 cFYI("Unexpected message type on auth response is %d "));
2653 ("Does UID on challenge %d match auth response UID %d ",
2654 ses->Suid, smb_buffer_response->Uid));
2655 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2656 bcc_ptr = pByteArea(smb_buffer_response);
2657 /* response can have either 3 or 4 word count - Samba sends 3 */
2658 if ((pSMBr->resp.hdr.WordCount == 3)
2659 || ((pSMBr->resp.hdr.WordCount == 4)
2661 pSMBr->resp.ByteCount))) {
2662 if (pSMBr->resp.hdr.WordCount == 4) {
2666 ("Security Blob Length %d ",
2671 ("NTLMSSP response to Authenticate "));
2673 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2674 if ((long) (bcc_ptr) % 2) {
2676 (BCC(smb_buffer_response)
2678 bcc_ptr++; /* Unicode strings must be word aligned */
2680 remaining_words = BCC(smb_buffer_response) / 2;
2683 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2684 /* We look for obvious messed up bcc or strings in response so we do not go off
2685 the end since (at least) WIN2K and Windows XP have a major bug in not null
2686 terminating last Unicode string in response */
2688 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2689 cifs_strfromUCS_le(ses->serverOS,
2693 bcc_ptr += 2 * (len + 1);
2694 remaining_words -= len + 1;
2695 ses->serverOS[2 * len] = 0;
2696 ses->serverOS[1 + (2 * len)] = 0;
2697 if (remaining_words > 0) {
2698 len = UniStrnlen((wchar_t *)
2703 cifs_kcalloc(2 * (len + 1),
2705 cifs_strfromUCS_le(ses->
2711 bcc_ptr += 2 * (len + 1);
2712 ses->serverNOS[2 * len] = 0;
2713 ses->serverNOS[1+(2*len)] = 0;
2714 remaining_words -= len + 1;
2715 if (remaining_words > 0) {
2716 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2717 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2742 } /* else no more room so create dummy domain string */
2744 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
2745 } else { /* no room so create dummy domain and NOS string */
2746 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2747 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2749 } else { /* ASCII */
2750 len = strnlen(bcc_ptr, 1024);
2751 if (((long) bcc_ptr + len) -
2752 (long) pByteArea(smb_buffer_response)
2753 <= BCC(smb_buffer_response)) {
2754 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2755 strncpy(ses->serverOS,bcc_ptr, len);
2758 bcc_ptr[0] = 0; /* null terminate the string */
2761 len = strnlen(bcc_ptr, 1024);
2762 ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
2763 strncpy(ses->serverNOS, bcc_ptr, len);
2768 len = strnlen(bcc_ptr, 1024);
2769 ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
2770 strncpy(ses->serverDomain, bcc_ptr, len);
2776 ("Variable field of length %d extends beyond end of smb ",
2781 (" Security Blob Length extends beyond end of SMB"));
2784 cERROR(1, ("No session structure passed in."));
2788 (" Invalid Word count %d: ",
2789 smb_buffer_response->WordCount));
2794 cifs_buf_release(smb_buffer);
2800 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2801 const char *tree, struct cifsTconInfo *tcon,
2802 const struct nls_table *nls_codepage)
2804 struct smb_hdr *smb_buffer;
2805 struct smb_hdr *smb_buffer_response;
2808 unsigned char *bcc_ptr;
2816 smb_buffer = cifs_buf_get();
2817 if (smb_buffer == NULL) {
2820 smb_buffer_response = smb_buffer;
2822 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2823 NULL /*no tid */ , 4 /*wct */ );
2824 smb_buffer->Uid = ses->Suid;
2825 pSMB = (TCONX_REQ *) smb_buffer;
2826 pSMBr = (TCONX_RSP *) smb_buffer_response;
2828 pSMB->AndXCommand = 0xFF;
2829 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2830 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2831 bcc_ptr = &pSMB->Password[0];
2832 bcc_ptr++; /* skip password */
2834 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2835 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2837 if (ses->capabilities & CAP_STATUS32) {
2838 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2840 if (ses->capabilities & CAP_DFS) {
2841 smb_buffer->Flags2 |= SMBFLG2_DFS;
2843 if (ses->capabilities & CAP_UNICODE) {
2844 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2846 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2847 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2848 bcc_ptr += 2; /* skip trailing null */
2849 } else { /* ASCII */
2851 strcpy(bcc_ptr, tree);
2852 bcc_ptr += strlen(tree) + 1;
2854 strcpy(bcc_ptr, "?????");
2855 bcc_ptr += strlen("?????");
2857 count = bcc_ptr - &pSMB->Password[0];
2858 pSMB->hdr.smb_buf_length += count;
2859 pSMB->ByteCount = cpu_to_le16(count);
2861 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2863 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2864 /* above now done in SendReceive */
2865 if ((rc == 0) && (tcon != NULL)) {
2866 tcon->tidStatus = CifsGood;
2867 tcon->tid = smb_buffer_response->Tid;
2868 bcc_ptr = pByteArea(smb_buffer_response);
2869 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2870 /* skip service field (NB: this field is always ASCII) */
2871 bcc_ptr += length + 1;
2872 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2873 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2874 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2875 if ((bcc_ptr + (2 * length)) -
2876 pByteArea(smb_buffer_response) <=
2877 BCC(smb_buffer_response)) {
2878 if(tcon->nativeFileSystem)
2879 kfree(tcon->nativeFileSystem);
2880 tcon->nativeFileSystem =
2881 cifs_kcalloc(length + 2, GFP_KERNEL);
2882 cifs_strfromUCS_le(tcon->nativeFileSystem,
2883 (wchar_t *) bcc_ptr,
2884 length, nls_codepage);
2885 bcc_ptr += 2 * length;
2886 bcc_ptr[0] = 0; /* null terminate the string */
2890 /* else do not bother copying these informational fields */
2892 length = strnlen(bcc_ptr, 1024);
2893 if ((bcc_ptr + length) -
2894 pByteArea(smb_buffer_response) <=
2895 BCC(smb_buffer_response)) {
2896 if(tcon->nativeFileSystem)
2897 kfree(tcon->nativeFileSystem);
2898 tcon->nativeFileSystem =
2899 cifs_kcalloc(length + 1, GFP_KERNEL);
2900 strncpy(tcon->nativeFileSystem, bcc_ptr,
2903 /* else do not bother copying these informational fields */
2905 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2906 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2907 } else if ((rc == 0) && tcon == NULL) {
2908 /* all we need to save for IPC$ connection */
2909 ses->ipc_tid = smb_buffer_response->Tid;
2913 cifs_buf_release(smb_buffer);
2918 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
2922 struct cifsSesInfo *ses = NULL;
2923 struct task_struct *cifsd_task;
2927 if (cifs_sb->tcon) {
2928 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
2929 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
2934 tconInfoFree(cifs_sb->tcon);
2935 if ((ses) && (ses->server)) {
2936 /* save off task so we do not refer to ses later */
2937 cifsd_task = ses->server->tsk;
2938 cFYI(1, ("About to do SMBLogoff "));
2939 rc = CIFSSMBLogoff(xid, ses);
2943 } else if (rc == -ESHUTDOWN) {
2944 cFYI(1,("Waking up socket by sending it signal"));
2946 send_sig(SIGKILL,cifsd_task,1);
2948 } /* else - we have an smb session
2949 left on this socket do not kill cifsd */
2951 cFYI(1, ("No session or bad tcon"));
2954 cifs_sb->tcon = NULL;
2956 set_current_state(TASK_INTERRUPTIBLE);
2957 schedule_timeout(HZ / 2);
2963 return rc; /* BB check if we should always return zero here */
2966 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2967 struct nls_table * nls_info)
2970 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
2971 int ntlmv2_flag = FALSE;
2974 /* what if server changes its buffer size after dropping the session? */
2975 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
2976 rc = CIFSSMBNegotiate(xid, pSesInfo);
2977 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
2978 rc = CIFSSMBNegotiate(xid, pSesInfo);
2983 spin_lock(&GlobalMid_Lock);
2984 if(pSesInfo->server->tcpStatus != CifsExiting)
2985 pSesInfo->server->tcpStatus = CifsGood;
2988 spin_unlock(&GlobalMid_Lock);
2994 pSesInfo->capabilities = pSesInfo->server->capabilities;
2995 if(linuxExtEnabled == 0)
2996 pSesInfo->capabilities &= (~CAP_UNIX);
2997 /* pSesInfo->sequence_number = 0;*/
2998 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2999 pSesInfo->server->secMode,
3000 pSesInfo->server->capabilities,
3001 pSesInfo->server->timeZone));
3002 if (extended_security
3003 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3004 && (pSesInfo->server->secType == NTLMSSP)) {
3005 cFYI(1, ("New style sesssetup "));
3006 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3007 NULL /* security blob */,
3008 0 /* blob length */,
3010 } else if (extended_security
3011 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3012 && (pSesInfo->server->secType == RawNTLMSSP)) {
3013 cFYI(1, ("NTLMSSP sesssetup "));
3014 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3021 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3022 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3027 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3029 CalcNTLMv2_response(pSesInfo,v2_response);
3031 cifs_calculate_ntlmv2_mac_key(
3032 pSesInfo->server->mac_signing_key,
3033 response, ntlm_session_key, */
3035 /* BB Put dummy sig in SessSetup PDU? */
3042 SMBNTencrypt(pSesInfo->password,
3043 pSesInfo->server->cryptKey,
3047 cifs_calculate_mac_key(
3048 pSesInfo->server->mac_signing_key,
3050 pSesInfo->password);
3052 /* for better security the weaker lanman hash not sent
3053 in AuthSessSetup so we no longer calculate it */
3055 rc = CIFSNTLMSSPAuthSessSetup(xid,
3061 } else { /* old style NTLM 0.12 session setup */
3062 SMBNTencrypt(pSesInfo->password,
3063 pSesInfo->server->cryptKey,
3067 cifs_calculate_mac_key(
3068 pSesInfo->server->mac_signing_key,
3069 ntlm_session_key, pSesInfo->password);
3071 rc = CIFSSessSetup(xid, pSesInfo,
3072 ntlm_session_key, nls_info);
3075 cERROR(1,("Send error in SessSetup = %d",rc));
3077 cFYI(1,("CIFS Session Established successfully"));
3078 pSesInfo->status = CifsGood;