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)
929 unsigned char *referrals = NULL;
930 unsigned int num_referrals;
933 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
934 &num_referrals, &referrals);
936 /* BB Add in code to: if valid refrl, if not ip address contact
937 the helper that resolves tcp names, mount to it, try to
938 tcon to it unmount it if fail */
947 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
948 const char *old_path, const struct nls_table *nls_codepage,
949 unsigned int *pnum_referrals, unsigned char ** preferrals)
956 if (pSesInfo->ipc_tid == 0) {
957 temp_unc = kmalloc(2 /* for slashes */ +
958 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
959 + 1 + 4 /* slash IPC$ */ + 2,
961 if (temp_unc == NULL)
965 strcpy(temp_unc + 2, pSesInfo->serverName);
966 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
967 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
969 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
973 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
974 pnum_referrals, nls_codepage);
979 /* See RFC1001 section 14 on representation of Netbios names */
980 static void rfc1002mangle(char * target,char * source, unsigned int length)
984 for(i=0,j=0;i<(length);i++) {
985 /* mask a nibble at a time and encode */
986 target[j] = 'A' + (0x0F & (source[i] >> 4));
987 target[j+1] = 'A' + (0x0F & source[i]);
995 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1000 __be16 orig_port = 0;
1002 if(*csocket == NULL) {
1003 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1005 cERROR(1, ("Error %d creating socket",rc));
1009 /* BB other socket options to set KEEPALIVE, NODELAY? */
1010 cFYI(1,("Socket created"));
1011 (*csocket)->sk->sk_allocation = GFP_NOFS;
1015 psin_server->sin_family = AF_INET;
1016 if(psin_server->sin_port) { /* user overrode default port */
1017 rc = (*csocket)->ops->connect(*csocket,
1018 (struct sockaddr *) psin_server,
1019 sizeof (struct sockaddr_in),0);
1025 /* save original port so we can retry user specified port
1026 later if fall back ports fail this time */
1027 orig_port = psin_server->sin_port;
1029 /* do not retry on the same port we just failed on */
1030 if(psin_server->sin_port != htons(CIFS_PORT)) {
1031 psin_server->sin_port = htons(CIFS_PORT);
1033 rc = (*csocket)->ops->connect(*csocket,
1034 (struct sockaddr *) psin_server,
1035 sizeof (struct sockaddr_in),0);
1041 psin_server->sin_port = htons(RFC1001_PORT);
1042 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1043 psin_server, sizeof (struct sockaddr_in),0);
1048 /* give up here - unless we want to retry on different
1049 protocol families some day */
1052 psin_server->sin_port = orig_port;
1053 cFYI(1,("Error %d connecting to server via ipv4",rc));
1054 sock_release(*csocket);
1058 /* Eventually check for other socket options to change from
1059 the default. sock_setsockopt not used because it expects
1060 user space buffer */
1061 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1063 /* send RFC1001 sessinit */
1065 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1066 /* some servers require RFC1001 sessinit before sending
1067 negprot - BB check reconnection in case where second
1068 sessinit is sent but no second negprot */
1069 struct rfc1002_session_packet * ses_init_buf;
1070 struct smb_hdr * smb_buf;
1071 ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1073 ses_init_buf->trailer.session_req.called_len = 32;
1074 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1075 DEFAULT_CIFS_CALLED_NAME,16);
1076 ses_init_buf->trailer.session_req.calling_len = 32;
1077 /* calling name ends in null (byte 16) from old smb
1079 if(netbios_name && (netbios_name[0] !=0)) {
1080 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1083 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1084 "LINUX_CIFS_CLNT",16);
1086 ses_init_buf->trailer.session_req.scope1 = 0;
1087 ses_init_buf->trailer.session_req.scope2 = 0;
1088 smb_buf = (struct smb_hdr *)ses_init_buf;
1089 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1090 smb_buf->smb_buf_length = 0x81000044;
1091 rc = smb_send(*csocket, smb_buf, 0x44,
1092 (struct sockaddr *)psin_server);
1093 kfree(ses_init_buf);
1095 /* else the negprot may still work without this
1096 even though malloc failed */
1104 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1108 __be16 orig_port = 0;
1110 if(*csocket == NULL) {
1111 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1113 cERROR(1, ("Error %d creating ipv6 socket",rc));
1117 /* BB other socket options to set KEEPALIVE, NODELAY? */
1118 cFYI(1,("ipv6 Socket created"));
1119 (*csocket)->sk->sk_allocation = GFP_NOFS;
1123 psin_server->sin6_family = AF_INET6;
1125 if(psin_server->sin6_port) { /* user overrode default port */
1126 rc = (*csocket)->ops->connect(*csocket,
1127 (struct sockaddr *) psin_server,
1128 sizeof (struct sockaddr_in6),0);
1134 /* save original port so we can retry user specified port
1135 later if fall back ports fail this time */
1137 orig_port = psin_server->sin6_port;
1138 /* do not retry on the same port we just failed on */
1139 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1140 psin_server->sin6_port = htons(CIFS_PORT);
1142 rc = (*csocket)->ops->connect(*csocket,
1143 (struct sockaddr *) psin_server,
1144 sizeof (struct sockaddr_in6),0);
1150 psin_server->sin6_port = htons(RFC1001_PORT);
1151 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1152 psin_server, sizeof (struct sockaddr_in6),0);
1157 /* give up here - unless we want to retry on different
1158 protocol families some day */
1161 psin_server->sin6_port = orig_port;
1162 cFYI(1,("Error %d connecting to server via ipv6",rc));
1163 sock_release(*csocket);
1167 /* Eventually check for other socket options to change from
1168 the default. sock_setsockopt not used because it expects
1169 user space buffer */
1170 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1176 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1177 char *mount_data, const char *devname)
1181 int address_type = AF_INET;
1182 struct socket *csocket = NULL;
1183 struct sockaddr_in sin_server;
1184 struct sockaddr_in6 sin_server6;
1185 struct smb_vol volume_info;
1186 struct cifsSesInfo *pSesInfo = NULL;
1187 struct cifsSesInfo *existingCifsSes = NULL;
1188 struct cifsTconInfo *tcon = NULL;
1189 struct TCP_Server_Info *srvTcp = NULL;
1193 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1195 memset(&volume_info,0,sizeof(struct smb_vol));
1196 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1198 kfree(volume_info.UNC);
1199 if(volume_info.password)
1200 kfree(volume_info.password);
1205 if (volume_info.username) {
1206 /* BB fixme parse for domain name here */
1207 cFYI(1, ("Username: %s ", volume_info.username));
1210 cifserror("No username specified ");
1211 /* In userspace mount helper we can get user name from alternate
1212 locations such as env variables and files on disk */
1214 kfree(volume_info.UNC);
1215 if(volume_info.password)
1216 kfree(volume_info.password);
1221 if (volume_info.UNCip && volume_info.UNC) {
1222 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1225 /* not ipv4 address, try ipv6 */
1226 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1228 address_type = AF_INET6;
1230 address_type = AF_INET;
1234 /* we failed translating address */
1236 kfree(volume_info.UNC);
1237 if(volume_info.password)
1238 kfree(volume_info.password);
1243 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1246 } else if (volume_info.UNCip){
1247 /* BB using ip addr as server name connect to the DFS root below */
1248 cERROR(1,("Connecting to DFS root not implemented yet"));
1250 kfree(volume_info.UNC);
1251 if(volume_info.password)
1252 kfree(volume_info.password);
1255 } else /* which servers DFS root would we conect to */ {
1257 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1259 kfree(volume_info.UNC);
1260 if(volume_info.password)
1261 kfree(volume_info.password);
1266 /* this is needed for ASCII cp to Unicode converts */
1267 if(volume_info.iocharset == NULL) {
1268 cifs_sb->local_nls = load_nls_default();
1269 /* load_nls_default can not return null */
1271 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1272 if(cifs_sb->local_nls == NULL) {
1273 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1275 kfree(volume_info.UNC);
1276 if(volume_info.password)
1277 kfree(volume_info.password);
1283 if(address_type == AF_INET)
1284 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1285 NULL /* no ipv6 addr */,
1286 volume_info.username, &srvTcp);
1287 else if(address_type == AF_INET6)
1288 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1289 &sin_server6.sin6_addr,
1290 volume_info.username, &srvTcp);
1293 kfree(volume_info.UNC);
1294 if(volume_info.password)
1295 kfree(volume_info.password);
1302 cFYI(1, ("Existing tcp session with server found "));
1303 } else { /* create socket */
1304 if(volume_info.port)
1305 sin_server.sin_port = htons(volume_info.port);
1307 sin_server.sin_port = 0;
1308 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1311 ("Error connecting to IPv4 socket. Aborting operation"));
1313 sock_release(csocket);
1315 kfree(volume_info.UNC);
1316 if(volume_info.password)
1317 kfree(volume_info.password);
1322 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1323 if (srvTcp == NULL) {
1325 sock_release(csocket);
1327 kfree(volume_info.UNC);
1328 if(volume_info.password)
1329 kfree(volume_info.password);
1333 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1334 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1335 atomic_set(&srvTcp->inFlight,0);
1336 /* BB Add code for ipv6 case too */
1337 srvTcp->ssocket = csocket;
1338 srvTcp->protocolType = IPV4;
1339 init_waitqueue_head(&srvTcp->response_q);
1340 init_waitqueue_head(&srvTcp->request_q);
1341 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1342 /* at this point we are the only ones with the pointer
1343 to the struct since the kernel thread not created yet
1344 so no need to spinlock this init of tcpStatus */
1345 srvTcp->tcpStatus = CifsNew;
1346 init_MUTEX(&srvTcp->tcpSem);
1347 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1348 CLONE_FS | CLONE_FILES | CLONE_VM);
1351 sock_release(csocket);
1353 kfree(volume_info.UNC);
1354 if(volume_info.password)
1355 kfree(volume_info.password);
1360 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1361 srvTcp->sequence_number = 0;
1365 if (existingCifsSes) {
1366 pSesInfo = existingCifsSes;
1367 cFYI(1, ("Existing smb sess found "));
1368 if(volume_info.password)
1369 kfree(volume_info.password);
1370 /* volume_info.UNC freed at end of function */
1372 cFYI(1, ("Existing smb sess not found "));
1373 pSesInfo = sesInfoAlloc();
1374 if (pSesInfo == NULL)
1377 pSesInfo->server = srvTcp;
1378 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1379 NIPQUAD(sin_server.sin_addr.s_addr));
1383 /* volume_info.password freed at unmount */
1384 if (volume_info.password)
1385 pSesInfo->password = volume_info.password;
1386 if (volume_info.username)
1387 strncpy(pSesInfo->userName,
1388 volume_info.username,MAX_USERNAME_SIZE);
1389 if (volume_info.domainname)
1390 strncpy(pSesInfo->domainName,
1391 volume_info.domainname,MAX_USERNAME_SIZE);
1392 pSesInfo->linux_uid = volume_info.linux_uid;
1393 down(&pSesInfo->sesSem);
1394 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1395 up(&pSesInfo->sesSem);
1397 atomic_inc(&srvTcp->socketUseCount);
1399 if(volume_info.password)
1400 kfree(volume_info.password);
1403 /* search for existing tcon to this server share */
1405 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1406 cifs_sb->rsize = volume_info.rsize;
1408 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1409 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1410 cifs_sb->wsize = volume_info.wsize;
1412 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1413 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1414 cifs_sb->rsize = PAGE_CACHE_SIZE;
1415 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1417 cifs_sb->mnt_uid = volume_info.linux_uid;
1418 cifs_sb->mnt_gid = volume_info.linux_gid;
1419 cifs_sb->mnt_file_mode = volume_info.file_mode;
1420 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1421 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1423 if(volume_info.noperm)
1424 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1425 if(volume_info.setuids)
1426 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1427 if(volume_info.server_ino)
1428 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1429 if(volume_info.remap)
1430 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1431 if(volume_info.no_xattr)
1432 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1433 if(volume_info.direct_io) {
1434 cERROR(1,("mounting share using direct i/o"));
1435 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1439 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1440 volume_info.username);
1442 cFYI(1, ("Found match on UNC path "));
1443 /* we can have only one retry value for a connection
1444 to a share so for resources mounted more than once
1445 to the same server share the last value passed in
1446 for the retry flag is used */
1447 tcon->retry = volume_info.retry;
1449 tcon = tconInfoAlloc();
1453 /* check for null share name ie connect to dfs root */
1455 /* BB check if this works for exactly length three strings */
1456 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1457 && (strchr(volume_info.UNC + 3, '/') ==
1459 rc = connect_to_dfs_path(xid,
1465 kfree(volume_info.UNC);
1469 rc = CIFSTCon(xid, pSesInfo,
1471 tcon, cifs_sb->local_nls);
1472 cFYI(1, ("CIFS Tcon rc = %d", rc));
1475 atomic_inc(&pSesInfo->inUse);
1476 tcon->retry = volume_info.retry;
1482 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1483 sb->s_maxbytes = (u64) 1 << 63;
1485 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1488 sb->s_time_gran = 100;
1490 /* on error free sesinfo and tcon struct if needed */
1492 /* if session setup failed, use count is zero but
1493 we still need to free cifsd thread */
1494 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1495 spin_lock(&GlobalMid_Lock);
1496 srvTcp->tcpStatus = CifsExiting;
1497 spin_unlock(&GlobalMid_Lock);
1499 send_sig(SIGKILL,srvTcp->tsk,1);
1501 /* If find_unc succeeded then rc == 0 so we can not end */
1502 if (tcon) /* up accidently freeing someone elses tcon struct */
1504 if (existingCifsSes == NULL) {
1506 if ((pSesInfo->server) &&
1507 (pSesInfo->status == CifsGood)) {
1509 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1510 /* if the socketUseCount is now zero */
1511 if((temp_rc == -ESHUTDOWN) &&
1512 (pSesInfo->server->tsk))
1513 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1515 cFYI(1, ("No session or bad tcon"));
1516 sesInfoFree(pSesInfo);
1517 /* pSesInfo = NULL; */
1521 atomic_inc(&tcon->useCount);
1522 cifs_sb->tcon = tcon;
1523 tcon->ses = pSesInfo;
1525 /* do not care if following two calls succeed - informational only */
1526 CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls);
1527 CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls);
1528 if (tcon->ses->capabilities & CAP_UNIX) {
1529 if(!CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls)) {
1530 if(!volume_info.no_psx_acl) {
1531 if(CIFS_UNIX_POSIX_ACL_CAP &
1532 le64_to_cpu(tcon->fsUnixInfo.Capability))
1533 cFYI(1,("server negotiated posix acl support"));
1534 sb->s_flags |= MS_POSIXACL;
1540 /* volume_info.password is freed above when existing session found
1541 (in which case it is not needed anymore) but when new sesion is created
1542 the password ptr is put in the new session structure (in which case the
1543 password will be freed at unmount time) */
1545 kfree(volume_info.UNC);
1551 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1552 char session_key[CIFS_SESSION_KEY_SIZE],
1553 const struct nls_table *nls_codepage)
1555 struct smb_hdr *smb_buffer;
1556 struct smb_hdr *smb_buffer_response;
1557 SESSION_SETUP_ANDX *pSMB;
1558 SESSION_SETUP_ANDX *pSMBr;
1563 int remaining_words = 0;
1564 int bytes_returned = 0;
1569 cFYI(1, ("In sesssetup "));
1572 user = ses->userName;
1573 domain = ses->domainName;
1574 smb_buffer = cifs_buf_get();
1575 if (smb_buffer == NULL) {
1578 smb_buffer_response = smb_buffer;
1579 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1581 /* send SMBsessionSetup here */
1582 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1583 NULL /* no tCon exists yet */ , 13 /* wct */ );
1585 pSMB->req_no_secext.AndXCommand = 0xFF;
1586 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1587 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1589 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1590 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1592 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1593 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1594 if (ses->capabilities & CAP_UNICODE) {
1595 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1596 capabilities |= CAP_UNICODE;
1598 if (ses->capabilities & CAP_STATUS32) {
1599 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1600 capabilities |= CAP_STATUS32;
1602 if (ses->capabilities & CAP_DFS) {
1603 smb_buffer->Flags2 |= SMBFLG2_DFS;
1604 capabilities |= CAP_DFS;
1606 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1608 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1609 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1611 pSMB->req_no_secext.CaseSensitivePasswordLength =
1612 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1613 bcc_ptr = pByteArea(smb_buffer);
1614 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1615 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1616 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1617 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1619 if (ses->capabilities & CAP_UNICODE) {
1620 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1625 bytes_returned = 0; /* skill null user */
1628 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1630 /* convert number of 16 bit words to bytes */
1631 bcc_ptr += 2 * bytes_returned;
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, system_utsname.release,
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, system_utsname.release);
1676 bcc_ptr += strlen(system_utsname.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 if(strncmp(ses->serverNOS,
1736 "NT LAN Manager 4",16) == 0) {
1737 cFYI(1,("NT4 server"));
1738 ses->flags |= CIFS_SES_NT4;
1740 remaining_words -= len + 1;
1741 if (remaining_words > 0) {
1742 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1743 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1745 cifs_kcalloc(2*(len+1),GFP_KERNEL);
1746 cifs_strfromUCS_le(ses->serverDomain,
1747 (wchar_t *)bcc_ptr,len,nls_codepage);
1748 bcc_ptr += 2 * (len + 1);
1749 ses->serverDomain[2*len] = 0;
1750 ses->serverDomain[1+(2*len)] = 0;
1751 } /* else no more room so create dummy domain string */
1756 } else { /* no room so create dummy domain and NOS string */
1758 cifs_kcalloc(2, GFP_KERNEL);
1760 cifs_kcalloc(2, GFP_KERNEL);
1762 } else { /* ASCII */
1763 len = strnlen(bcc_ptr, 1024);
1764 if (((long) bcc_ptr + len) - (long)
1765 pByteArea(smb_buffer_response)
1766 <= BCC(smb_buffer_response)) {
1767 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1768 strncpy(ses->serverOS,bcc_ptr, len);
1771 bcc_ptr[0] = 0; /* null terminate the string */
1774 len = strnlen(bcc_ptr, 1024);
1775 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1776 strncpy(ses->serverNOS, bcc_ptr, len);
1781 len = strnlen(bcc_ptr, 1024);
1782 ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
1783 strncpy(ses->serverDomain, bcc_ptr, len);
1789 ("Variable field of length %d extends beyond end of smb ",
1794 (" Security Blob Length extends beyond end of SMB"));
1798 (" Invalid Word count %d: ",
1799 smb_buffer_response->WordCount));
1804 cifs_buf_release(smb_buffer);
1810 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1811 char *SecurityBlob,int SecurityBlobLength,
1812 const struct nls_table *nls_codepage)
1814 struct smb_hdr *smb_buffer;
1815 struct smb_hdr *smb_buffer_response;
1816 SESSION_SETUP_ANDX *pSMB;
1817 SESSION_SETUP_ANDX *pSMBr;
1822 int remaining_words = 0;
1823 int bytes_returned = 0;
1828 cFYI(1, ("In spnego sesssetup "));
1831 user = ses->userName;
1832 domain = ses->domainName;
1834 smb_buffer = cifs_buf_get();
1835 if (smb_buffer == NULL) {
1838 smb_buffer_response = smb_buffer;
1839 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1841 /* send SMBsessionSetup here */
1842 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1843 NULL /* no tCon exists yet */ , 12 /* wct */ );
1844 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1845 pSMB->req.AndXCommand = 0xFF;
1846 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1847 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1849 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1850 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1852 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1853 CAP_EXTENDED_SECURITY;
1854 if (ses->capabilities & CAP_UNICODE) {
1855 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1856 capabilities |= CAP_UNICODE;
1858 if (ses->capabilities & CAP_STATUS32) {
1859 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1860 capabilities |= CAP_STATUS32;
1862 if (ses->capabilities & CAP_DFS) {
1863 smb_buffer->Flags2 |= SMBFLG2_DFS;
1864 capabilities |= CAP_DFS;
1866 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1868 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1869 bcc_ptr = pByteArea(smb_buffer);
1870 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1871 bcc_ptr += SecurityBlobLength;
1873 if (ses->capabilities & CAP_UNICODE) {
1874 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1879 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1880 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1881 bcc_ptr += 2; /* trailing null */
1884 cifs_strtoUCS((wchar_t *) bcc_ptr,
1885 "CIFS_LINUX_DOM", 32, nls_codepage);
1888 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1890 bcc_ptr += 2 * bytes_returned;
1893 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1895 bcc_ptr += 2 * bytes_returned;
1897 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
1899 bcc_ptr += 2 * bytes_returned;
1902 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1904 bcc_ptr += 2 * bytes_returned;
1907 strncpy(bcc_ptr, user, 200);
1908 bcc_ptr += strnlen(user, 200);
1911 if (domain == NULL) {
1912 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1913 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1915 strncpy(bcc_ptr, domain, 64);
1916 bcc_ptr += strnlen(domain, 64);
1920 strcpy(bcc_ptr, "Linux version ");
1921 bcc_ptr += strlen("Linux version ");
1922 strcpy(bcc_ptr, system_utsname.release);
1923 bcc_ptr += strlen(system_utsname.release) + 1;
1924 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1925 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1927 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1928 smb_buffer->smb_buf_length += count;
1929 pSMB->req.ByteCount = cpu_to_le16(count);
1931 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1932 &bytes_returned, 1);
1934 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1935 } else if ((smb_buffer_response->WordCount == 3)
1936 || (smb_buffer_response->WordCount == 4)) {
1937 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1939 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1940 if (action & GUEST_LOGIN)
1941 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1943 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1944 cFYI(1, ("UID = %d ", ses->Suid));
1945 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
1947 /* BB Fix below to make endian neutral !! */
1949 if ((pSMBr->resp.hdr.WordCount == 3)
1950 || ((pSMBr->resp.hdr.WordCount == 4)
1952 pSMBr->resp.ByteCount))) {
1953 if (pSMBr->resp.hdr.WordCount == 4) {
1957 ("Security Blob Length %d ",
1961 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1962 if ((long) (bcc_ptr) % 2) {
1964 (BCC(smb_buffer_response)
1966 bcc_ptr++; /* Unicode strings must be word aligned */
1970 (smb_buffer_response) / 2;
1973 UniStrnlen((wchar_t *) bcc_ptr,
1974 remaining_words - 1);
1975 /* We look for obvious messed up bcc or strings in response so we do not go off
1976 the end since (at least) WIN2K and Windows XP have a major bug in not null
1977 terminating last Unicode string in response */
1979 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1980 cifs_strfromUCS_le(ses->serverOS,
1984 bcc_ptr += 2 * (len + 1);
1985 remaining_words -= len + 1;
1986 ses->serverOS[2 * len] = 0;
1987 ses->serverOS[1 + (2 * len)] = 0;
1988 if (remaining_words > 0) {
1989 len = UniStrnlen((wchar_t *)bcc_ptr,
1993 cifs_kcalloc(2 * (len + 1),
1995 cifs_strfromUCS_le(ses->serverNOS,
1999 bcc_ptr += 2 * (len + 1);
2000 ses->serverNOS[2 * len] = 0;
2001 ses->serverNOS[1 + (2 * len)] = 0;
2002 remaining_words -= len + 1;
2003 if (remaining_words > 0) {
2004 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2005 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2006 ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
2007 cifs_strfromUCS_le(ses->serverDomain,
2011 bcc_ptr += 2*(len+1);
2012 ses->serverDomain[2*len] = 0;
2013 ses->serverDomain[1+(2*len)] = 0;
2014 } /* else no more room so create dummy domain string */
2017 cifs_kcalloc(2,GFP_KERNEL);
2018 } else { /* no room so create dummy domain and NOS string */
2019 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2020 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2022 } else { /* ASCII */
2024 len = strnlen(bcc_ptr, 1024);
2025 if (((long) bcc_ptr + len) - (long)
2026 pByteArea(smb_buffer_response)
2027 <= BCC(smb_buffer_response)) {
2028 ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
2029 strncpy(ses->serverOS, bcc_ptr, len);
2032 bcc_ptr[0] = 0; /* null terminate the string */
2035 len = strnlen(bcc_ptr, 1024);
2036 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2037 strncpy(ses->serverNOS, bcc_ptr, len);
2042 len = strnlen(bcc_ptr, 1024);
2043 ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
2044 strncpy(ses->serverDomain, bcc_ptr, len);
2050 ("Variable field of length %d extends beyond end of smb ",
2055 (" Security Blob Length extends beyond end of SMB"));
2058 cERROR(1, ("No session structure passed in."));
2062 (" Invalid Word count %d: ",
2063 smb_buffer_response->WordCount));
2068 cifs_buf_release(smb_buffer);
2074 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2075 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2076 const struct nls_table *nls_codepage)
2078 struct smb_hdr *smb_buffer;
2079 struct smb_hdr *smb_buffer_response;
2080 SESSION_SETUP_ANDX *pSMB;
2081 SESSION_SETUP_ANDX *pSMBr;
2085 int remaining_words = 0;
2086 int bytes_returned = 0;
2088 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2089 PNEGOTIATE_MESSAGE SecurityBlob;
2090 PCHALLENGE_MESSAGE SecurityBlob2;
2091 __u32 negotiate_flags, capabilities;
2094 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2097 domain = ses->domainName;
2098 *pNTLMv2_flag = FALSE;
2099 smb_buffer = cifs_buf_get();
2100 if (smb_buffer == NULL) {
2103 smb_buffer_response = smb_buffer;
2104 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2105 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2107 /* send SMBsessionSetup here */
2108 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2109 NULL /* no tCon exists yet */ , 12 /* wct */ );
2110 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2111 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2113 pSMB->req.AndXCommand = 0xFF;
2114 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2115 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2117 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2118 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2120 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2121 CAP_EXTENDED_SECURITY;
2122 if (ses->capabilities & CAP_UNICODE) {
2123 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2124 capabilities |= CAP_UNICODE;
2126 if (ses->capabilities & CAP_STATUS32) {
2127 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2128 capabilities |= CAP_STATUS32;
2130 if (ses->capabilities & CAP_DFS) {
2131 smb_buffer->Flags2 |= SMBFLG2_DFS;
2132 capabilities |= CAP_DFS;
2134 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2136 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2137 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2138 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2139 SecurityBlob->MessageType = NtLmNegotiate;
2141 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2142 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2143 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2145 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2147 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2148 /* setup pointers to domain name and workstation name */
2149 bcc_ptr += SecurityBlobLength;
2151 SecurityBlob->WorkstationName.Buffer = 0;
2152 SecurityBlob->WorkstationName.Length = 0;
2153 SecurityBlob->WorkstationName.MaximumLength = 0;
2155 if (domain == NULL) {
2156 SecurityBlob->DomainName.Buffer = 0;
2157 SecurityBlob->DomainName.Length = 0;
2158 SecurityBlob->DomainName.MaximumLength = 0;
2161 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2162 strncpy(bcc_ptr, domain, 63);
2163 len = strnlen(domain, 64);
2164 SecurityBlob->DomainName.MaximumLength =
2166 SecurityBlob->DomainName.Buffer =
2167 cpu_to_le32((long) &SecurityBlob->
2169 (long) &SecurityBlob->Signature);
2171 SecurityBlobLength += len;
2172 SecurityBlob->DomainName.Length =
2175 if (ses->capabilities & CAP_UNICODE) {
2176 if ((long) bcc_ptr % 2) {
2182 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2184 bcc_ptr += 2 * bytes_returned;
2186 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2188 bcc_ptr += 2 * bytes_returned;
2189 bcc_ptr += 2; /* null terminate Linux version */
2191 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2193 bcc_ptr += 2 * bytes_returned;
2196 bcc_ptr += 2; /* null terminate network opsys string */
2199 bcc_ptr += 2; /* null domain */
2200 } else { /* ASCII */
2201 strcpy(bcc_ptr, "Linux version ");
2202 bcc_ptr += strlen("Linux version ");
2203 strcpy(bcc_ptr, system_utsname.release);
2204 bcc_ptr += strlen(system_utsname.release) + 1;
2205 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2206 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2207 bcc_ptr++; /* empty domain field */
2210 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2211 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2212 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2213 smb_buffer->smb_buf_length += count;
2214 pSMB->req.ByteCount = cpu_to_le16(count);
2216 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2217 &bytes_returned, 1);
2219 if (smb_buffer_response->Status.CifsError ==
2220 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2224 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2225 } else if ((smb_buffer_response->WordCount == 3)
2226 || (smb_buffer_response->WordCount == 4)) {
2227 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2228 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2230 if (action & GUEST_LOGIN)
2231 cFYI(1, (" Guest login"));
2232 /* Do we want to set anything in SesInfo struct when guest login? */
2234 bcc_ptr = pByteArea(smb_buffer_response);
2235 /* response can have either 3 or 4 word count - Samba sends 3 */
2237 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2238 if (SecurityBlob2->MessageType != NtLmChallenge) {
2240 ("Unexpected NTLMSSP message type received %d",
2241 SecurityBlob2->MessageType));
2243 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2244 cFYI(1, ("UID = %d ", ses->Suid));
2245 if ((pSMBr->resp.hdr.WordCount == 3)
2246 || ((pSMBr->resp.hdr.WordCount == 4)
2248 pSMBr->resp.ByteCount))) {
2250 if (pSMBr->resp.hdr.WordCount == 4) {
2251 bcc_ptr += blob_len;
2253 ("Security Blob Length %d ",
2257 cFYI(1, ("NTLMSSP Challenge rcvd "));
2259 memcpy(ses->server->cryptKey,
2260 SecurityBlob2->Challenge,
2261 CIFS_CRYPTO_KEY_SIZE);
2262 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2263 *pNTLMv2_flag = TRUE;
2265 if((SecurityBlob2->NegotiateFlags &
2266 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2267 || (sign_CIFS_PDUs > 1))
2268 ses->server->secMode |=
2269 SECMODE_SIGN_REQUIRED;
2270 if ((SecurityBlob2->NegotiateFlags &
2271 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2272 ses->server->secMode |=
2273 SECMODE_SIGN_ENABLED;
2275 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2276 if ((long) (bcc_ptr) % 2) {
2278 (BCC(smb_buffer_response)
2280 bcc_ptr++; /* Unicode strings must be word aligned */
2284 (smb_buffer_response) / 2;
2287 UniStrnlen((wchar_t *) bcc_ptr,
2288 remaining_words - 1);
2289 /* We look for obvious messed up bcc or strings in response so we do not go off
2290 the end since (at least) WIN2K and Windows XP have a major bug in not null
2291 terminating last Unicode string in response */
2293 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2294 cifs_strfromUCS_le(ses->serverOS,
2298 bcc_ptr += 2 * (len + 1);
2299 remaining_words -= len + 1;
2300 ses->serverOS[2 * len] = 0;
2301 ses->serverOS[1 + (2 * len)] = 0;
2302 if (remaining_words > 0) {
2303 len = UniStrnlen((wchar_t *)
2308 cifs_kcalloc(2 * (len + 1),
2310 cifs_strfromUCS_le(ses->
2316 bcc_ptr += 2 * (len + 1);
2317 ses->serverNOS[2 * len] = 0;
2320 remaining_words -= len + 1;
2321 if (remaining_words > 0) {
2322 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2323 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2348 } /* else no more room so create dummy domain string */
2353 } else { /* no room so create dummy domain and NOS string */
2355 cifs_kcalloc(2, GFP_KERNEL);
2357 cifs_kcalloc(2, GFP_KERNEL);
2359 } else { /* ASCII */
2360 len = strnlen(bcc_ptr, 1024);
2361 if (((long) bcc_ptr + len) - (long)
2362 pByteArea(smb_buffer_response)
2363 <= BCC(smb_buffer_response)) {
2365 cifs_kcalloc(len + 1,
2367 strncpy(ses->serverOS,
2371 bcc_ptr[0] = 0; /* null terminate string */
2374 len = strnlen(bcc_ptr, 1024);
2376 cifs_kcalloc(len + 1,
2378 strncpy(ses->serverNOS, bcc_ptr, len);
2383 len = strnlen(bcc_ptr, 1024);
2385 cifs_kcalloc(len + 1,
2387 strncpy(ses->serverDomain, bcc_ptr, len);
2393 ("Variable field of length %d extends beyond end of smb ",
2398 (" Security Blob Length extends beyond end of SMB"));
2401 cERROR(1, ("No session structure passed in."));
2405 (" Invalid Word count %d: ",
2406 smb_buffer_response->WordCount));
2411 cifs_buf_release(smb_buffer);
2416 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2417 char *ntlm_session_key, int ntlmv2_flag,
2418 const struct nls_table *nls_codepage)
2420 struct smb_hdr *smb_buffer;
2421 struct smb_hdr *smb_buffer_response;
2422 SESSION_SETUP_ANDX *pSMB;
2423 SESSION_SETUP_ANDX *pSMBr;
2428 int remaining_words = 0;
2429 int bytes_returned = 0;
2431 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2432 PAUTHENTICATE_MESSAGE SecurityBlob;
2433 __u32 negotiate_flags, capabilities;
2436 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2439 user = ses->userName;
2440 domain = ses->domainName;
2441 smb_buffer = cifs_buf_get();
2442 if (smb_buffer == NULL) {
2445 smb_buffer_response = smb_buffer;
2446 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2447 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2449 /* send SMBsessionSetup here */
2450 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2451 NULL /* no tCon exists yet */ , 12 /* wct */ );
2452 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2453 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2454 pSMB->req.AndXCommand = 0xFF;
2455 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2456 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2458 pSMB->req.hdr.Uid = ses->Suid;
2460 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2461 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2463 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2464 CAP_EXTENDED_SECURITY;
2465 if (ses->capabilities & CAP_UNICODE) {
2466 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2467 capabilities |= CAP_UNICODE;
2469 if (ses->capabilities & CAP_STATUS32) {
2470 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2471 capabilities |= CAP_STATUS32;
2473 if (ses->capabilities & CAP_DFS) {
2474 smb_buffer->Flags2 |= SMBFLG2_DFS;
2475 capabilities |= CAP_DFS;
2477 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2479 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2480 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2481 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2482 SecurityBlob->MessageType = NtLmAuthenticate;
2483 bcc_ptr += SecurityBlobLength;
2485 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2486 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2487 0x80000000 | NTLMSSP_NEGOTIATE_128;
2489 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2491 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2493 /* setup pointers to domain name and workstation name */
2495 SecurityBlob->WorkstationName.Buffer = 0;
2496 SecurityBlob->WorkstationName.Length = 0;
2497 SecurityBlob->WorkstationName.MaximumLength = 0;
2498 SecurityBlob->SessionKey.Length = 0;
2499 SecurityBlob->SessionKey.MaximumLength = 0;
2500 SecurityBlob->SessionKey.Buffer = 0;
2502 SecurityBlob->LmChallengeResponse.Length = 0;
2503 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2504 SecurityBlob->LmChallengeResponse.Buffer = 0;
2506 SecurityBlob->NtChallengeResponse.Length =
2507 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2508 SecurityBlob->NtChallengeResponse.MaximumLength =
2509 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2510 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2511 SecurityBlob->NtChallengeResponse.Buffer =
2512 cpu_to_le32(SecurityBlobLength);
2513 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2514 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2516 if (ses->capabilities & CAP_UNICODE) {
2517 if (domain == NULL) {
2518 SecurityBlob->DomainName.Buffer = 0;
2519 SecurityBlob->DomainName.Length = 0;
2520 SecurityBlob->DomainName.MaximumLength = 0;
2523 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2526 SecurityBlob->DomainName.MaximumLength =
2528 SecurityBlob->DomainName.Buffer =
2529 cpu_to_le32(SecurityBlobLength);
2531 SecurityBlobLength += len;
2532 SecurityBlob->DomainName.Length =
2536 SecurityBlob->UserName.Buffer = 0;
2537 SecurityBlob->UserName.Length = 0;
2538 SecurityBlob->UserName.MaximumLength = 0;
2541 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2544 SecurityBlob->UserName.MaximumLength =
2546 SecurityBlob->UserName.Buffer =
2547 cpu_to_le32(SecurityBlobLength);
2549 SecurityBlobLength += len;
2550 SecurityBlob->UserName.Length =
2554 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2555 SecurityBlob->WorkstationName.Length *= 2;
2556 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2557 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2558 bcc_ptr += SecurityBlob->WorkstationName.Length;
2559 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2560 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2562 if ((long) bcc_ptr % 2) {
2567 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2569 bcc_ptr += 2 * bytes_returned;
2571 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2573 bcc_ptr += 2 * bytes_returned;
2574 bcc_ptr += 2; /* null term version string */
2576 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2578 bcc_ptr += 2 * bytes_returned;
2581 bcc_ptr += 2; /* null terminate network opsys string */
2584 bcc_ptr += 2; /* null domain */
2585 } else { /* ASCII */
2586 if (domain == NULL) {
2587 SecurityBlob->DomainName.Buffer = 0;
2588 SecurityBlob->DomainName.Length = 0;
2589 SecurityBlob->DomainName.MaximumLength = 0;
2592 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2593 strncpy(bcc_ptr, domain, 63);
2594 len = strnlen(domain, 64);
2595 SecurityBlob->DomainName.MaximumLength =
2597 SecurityBlob->DomainName.Buffer =
2598 cpu_to_le32(SecurityBlobLength);
2600 SecurityBlobLength += len;
2601 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2604 SecurityBlob->UserName.Buffer = 0;
2605 SecurityBlob->UserName.Length = 0;
2606 SecurityBlob->UserName.MaximumLength = 0;
2609 strncpy(bcc_ptr, user, 63);
2610 len = strnlen(user, 64);
2611 SecurityBlob->UserName.MaximumLength =
2613 SecurityBlob->UserName.Buffer =
2614 cpu_to_le32(SecurityBlobLength);
2616 SecurityBlobLength += len;
2617 SecurityBlob->UserName.Length = cpu_to_le16(len);
2619 /* BB fill in our workstation name if known BB */
2621 strcpy(bcc_ptr, "Linux version ");
2622 bcc_ptr += strlen("Linux version ");
2623 strcpy(bcc_ptr, system_utsname.release);
2624 bcc_ptr += strlen(system_utsname.release) + 1;
2625 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2626 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2627 bcc_ptr++; /* null domain */
2630 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2631 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2632 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2633 smb_buffer->smb_buf_length += count;
2634 pSMB->req.ByteCount = cpu_to_le16(count);
2636 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2637 &bytes_returned, 1);
2639 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2640 } else if ((smb_buffer_response->WordCount == 3)
2641 || (smb_buffer_response->WordCount == 4)) {
2642 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2644 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2645 if (action & GUEST_LOGIN)
2646 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2647 /* if(SecurityBlob2->MessageType != NtLm??){
2648 cFYI("Unexpected message type on auth response is %d "));
2652 ("Does UID on challenge %d match auth response UID %d ",
2653 ses->Suid, smb_buffer_response->Uid));
2654 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2655 bcc_ptr = pByteArea(smb_buffer_response);
2656 /* response can have either 3 or 4 word count - Samba sends 3 */
2657 if ((pSMBr->resp.hdr.WordCount == 3)
2658 || ((pSMBr->resp.hdr.WordCount == 4)
2660 pSMBr->resp.ByteCount))) {
2661 if (pSMBr->resp.hdr.WordCount == 4) {
2665 ("Security Blob Length %d ",
2670 ("NTLMSSP response to Authenticate "));
2672 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2673 if ((long) (bcc_ptr) % 2) {
2675 (BCC(smb_buffer_response)
2677 bcc_ptr++; /* Unicode strings must be word aligned */
2679 remaining_words = BCC(smb_buffer_response) / 2;
2682 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2683 /* We look for obvious messed up bcc or strings in response so we do not go off
2684 the end since (at least) WIN2K and Windows XP have a major bug in not null
2685 terminating last Unicode string in response */
2687 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2688 cifs_strfromUCS_le(ses->serverOS,
2692 bcc_ptr += 2 * (len + 1);
2693 remaining_words -= len + 1;
2694 ses->serverOS[2 * len] = 0;
2695 ses->serverOS[1 + (2 * len)] = 0;
2696 if (remaining_words > 0) {
2697 len = UniStrnlen((wchar_t *)
2702 cifs_kcalloc(2 * (len + 1),
2704 cifs_strfromUCS_le(ses->
2710 bcc_ptr += 2 * (len + 1);
2711 ses->serverNOS[2 * len] = 0;
2712 ses->serverNOS[1+(2*len)] = 0;
2713 remaining_words -= len + 1;
2714 if (remaining_words > 0) {
2715 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2716 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2741 } /* else no more room so create dummy domain string */
2743 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
2744 } else { /* no room so create dummy domain and NOS string */
2745 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2746 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2748 } else { /* ASCII */
2749 len = strnlen(bcc_ptr, 1024);
2750 if (((long) bcc_ptr + len) -
2751 (long) pByteArea(smb_buffer_response)
2752 <= BCC(smb_buffer_response)) {
2753 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2754 strncpy(ses->serverOS,bcc_ptr, len);
2757 bcc_ptr[0] = 0; /* null terminate the string */
2760 len = strnlen(bcc_ptr, 1024);
2761 ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
2762 strncpy(ses->serverNOS, bcc_ptr, len);
2767 len = strnlen(bcc_ptr, 1024);
2768 ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
2769 strncpy(ses->serverDomain, bcc_ptr, len);
2775 ("Variable field of length %d extends beyond end of smb ",
2780 (" Security Blob Length extends beyond end of SMB"));
2783 cERROR(1, ("No session structure passed in."));
2787 (" Invalid Word count %d: ",
2788 smb_buffer_response->WordCount));
2793 cifs_buf_release(smb_buffer);
2799 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2800 const char *tree, struct cifsTconInfo *tcon,
2801 const struct nls_table *nls_codepage)
2803 struct smb_hdr *smb_buffer;
2804 struct smb_hdr *smb_buffer_response;
2807 unsigned char *bcc_ptr;
2815 smb_buffer = cifs_buf_get();
2816 if (smb_buffer == NULL) {
2819 smb_buffer_response = smb_buffer;
2821 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2822 NULL /*no tid */ , 4 /*wct */ );
2823 smb_buffer->Uid = ses->Suid;
2824 pSMB = (TCONX_REQ *) smb_buffer;
2825 pSMBr = (TCONX_RSP *) smb_buffer_response;
2827 pSMB->AndXCommand = 0xFF;
2828 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2829 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2830 bcc_ptr = &pSMB->Password[0];
2831 bcc_ptr++; /* skip password */
2833 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2834 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2836 if (ses->capabilities & CAP_STATUS32) {
2837 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2839 if (ses->capabilities & CAP_DFS) {
2840 smb_buffer->Flags2 |= SMBFLG2_DFS;
2842 if (ses->capabilities & CAP_UNICODE) {
2843 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2845 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2846 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2847 bcc_ptr += 2; /* skip trailing null */
2848 } else { /* ASCII */
2850 strcpy(bcc_ptr, tree);
2851 bcc_ptr += strlen(tree) + 1;
2853 strcpy(bcc_ptr, "?????");
2854 bcc_ptr += strlen("?????");
2856 count = bcc_ptr - &pSMB->Password[0];
2857 pSMB->hdr.smb_buf_length += count;
2858 pSMB->ByteCount = cpu_to_le16(count);
2860 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2862 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2863 /* above now done in SendReceive */
2864 if ((rc == 0) && (tcon != NULL)) {
2865 tcon->tidStatus = CifsGood;
2866 tcon->tid = smb_buffer_response->Tid;
2867 bcc_ptr = pByteArea(smb_buffer_response);
2868 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2869 /* skip service field (NB: this field is always ASCII) */
2870 bcc_ptr += length + 1;
2871 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2872 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2873 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2874 if ((bcc_ptr + (2 * length)) -
2875 pByteArea(smb_buffer_response) <=
2876 BCC(smb_buffer_response)) {
2877 if(tcon->nativeFileSystem)
2878 kfree(tcon->nativeFileSystem);
2879 tcon->nativeFileSystem =
2880 cifs_kcalloc(length + 2, GFP_KERNEL);
2881 cifs_strfromUCS_le(tcon->nativeFileSystem,
2882 (wchar_t *) bcc_ptr,
2883 length, nls_codepage);
2884 bcc_ptr += 2 * length;
2885 bcc_ptr[0] = 0; /* null terminate the string */
2889 /* else do not bother copying these informational fields */
2891 length = strnlen(bcc_ptr, 1024);
2892 if ((bcc_ptr + length) -
2893 pByteArea(smb_buffer_response) <=
2894 BCC(smb_buffer_response)) {
2895 if(tcon->nativeFileSystem)
2896 kfree(tcon->nativeFileSystem);
2897 tcon->nativeFileSystem =
2898 cifs_kcalloc(length + 1, GFP_KERNEL);
2899 strncpy(tcon->nativeFileSystem, bcc_ptr,
2902 /* else do not bother copying these informational fields */
2904 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2905 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2906 } else if ((rc == 0) && tcon == NULL) {
2907 /* all we need to save for IPC$ connection */
2908 ses->ipc_tid = smb_buffer_response->Tid;
2912 cifs_buf_release(smb_buffer);
2917 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
2921 struct cifsSesInfo *ses = NULL;
2922 struct task_struct *cifsd_task;
2926 if (cifs_sb->tcon) {
2927 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
2928 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
2933 tconInfoFree(cifs_sb->tcon);
2934 if ((ses) && (ses->server)) {
2935 /* save off task so we do not refer to ses later */
2936 cifsd_task = ses->server->tsk;
2937 cFYI(1, ("About to do SMBLogoff "));
2938 rc = CIFSSMBLogoff(xid, ses);
2942 } else if (rc == -ESHUTDOWN) {
2943 cFYI(1,("Waking up socket by sending it signal"));
2945 send_sig(SIGKILL,cifsd_task,1);
2947 } /* else - we have an smb session
2948 left on this socket do not kill cifsd */
2950 cFYI(1, ("No session or bad tcon"));
2953 cifs_sb->tcon = NULL;
2955 set_current_state(TASK_INTERRUPTIBLE);
2956 schedule_timeout(HZ / 2);
2962 return rc; /* BB check if we should always return zero here */
2965 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2966 struct nls_table * nls_info)
2969 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
2970 int ntlmv2_flag = FALSE;
2973 /* what if server changes its buffer size after dropping the session? */
2974 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
2975 rc = CIFSSMBNegotiate(xid, pSesInfo);
2976 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
2977 rc = CIFSSMBNegotiate(xid, pSesInfo);
2982 spin_lock(&GlobalMid_Lock);
2983 if(pSesInfo->server->tcpStatus != CifsExiting)
2984 pSesInfo->server->tcpStatus = CifsGood;
2987 spin_unlock(&GlobalMid_Lock);
2993 pSesInfo->capabilities = pSesInfo->server->capabilities;
2994 if(linuxExtEnabled == 0)
2995 pSesInfo->capabilities &= (~CAP_UNIX);
2996 /* pSesInfo->sequence_number = 0;*/
2997 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
2998 pSesInfo->server->secMode,
2999 pSesInfo->server->capabilities,
3000 pSesInfo->server->timeZone));
3001 if (extended_security
3002 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3003 && (pSesInfo->server->secType == NTLMSSP)) {
3004 cFYI(1, ("New style sesssetup "));
3005 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3006 NULL /* security blob */,
3007 0 /* blob length */,
3009 } else if (extended_security
3010 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3011 && (pSesInfo->server->secType == RawNTLMSSP)) {
3012 cFYI(1, ("NTLMSSP sesssetup "));
3013 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3020 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3021 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3026 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3028 CalcNTLMv2_response(pSesInfo,v2_response);
3030 cifs_calculate_ntlmv2_mac_key(
3031 pSesInfo->server->mac_signing_key,
3032 response, ntlm_session_key, */
3034 /* BB Put dummy sig in SessSetup PDU? */
3041 SMBNTencrypt(pSesInfo->password,
3042 pSesInfo->server->cryptKey,
3046 cifs_calculate_mac_key(
3047 pSesInfo->server->mac_signing_key,
3049 pSesInfo->password);
3051 /* for better security the weaker lanman hash not sent
3052 in AuthSessSetup so we no longer calculate it */
3054 rc = CIFSNTLMSSPAuthSessSetup(xid,
3060 } else { /* old style NTLM 0.12 session setup */
3061 SMBNTencrypt(pSesInfo->password,
3062 pSesInfo->server->cryptKey,
3066 cifs_calculate_mac_key(
3067 pSesInfo->server->mac_signing_key,
3068 ntlm_session_key, pSesInfo->password);
3070 rc = CIFSSessSetup(xid, pSesInfo,
3071 ntlm_session_key, nls_info);
3074 cERROR(1,("Send error in SessSetup = %d",rc));
3076 cFYI(1,("CIFS Session Established successfully"));
3077 pSesInfo->status = CifsGood;