4 * Copyright (C) International Business Machines Corp., 2002,2005
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 <linux/delay.h>
32 #include <asm/uaccess.h>
33 #include <asm/processor.h>
36 #include "cifsproto.h"
37 #include "cifs_unicode.h"
38 #include "cifs_debug.h"
39 #include "cifs_fs_sb.h"
42 #include "rfc1002pdu.h"
45 #define RFC1001_PORT 139
47 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
49 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
52 extern mempool_t *cifs_req_poolp;
60 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
61 char *iocharset; /* local code page for mapping to and from Unicode */
62 char source_rfc1001_name[16]; /* netbios name of client */
72 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
73 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
74 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
76 unsigned remap:1; /* set to remap seven reserved chars in filenames */
80 unsigned short int port;
83 static int ipv4_connect(struct sockaddr_in *psin_server,
84 struct socket **csocket,
86 static int ipv6_connect(struct sockaddr_in6 *psin_server,
87 struct socket **csocket);
91 * cifs tcp session reconnection
93 * mark tcp session as reconnecting so temporarily locked
94 * mark all smb sessions as reconnecting for tcp session
95 * reconnect tcp session
96 * wake up waiters on reconnection? - (not needed currently)
100 cifs_reconnect(struct TCP_Server_Info *server)
103 struct list_head *tmp;
104 struct cifsSesInfo *ses;
105 struct cifsTconInfo *tcon;
106 struct mid_q_entry * mid_entry;
108 spin_lock(&GlobalMid_Lock);
109 if(server->tcpStatus == CifsExiting) {
110 /* the demux thread will exit normally
111 next time through the loop */
112 spin_unlock(&GlobalMid_Lock);
115 server->tcpStatus = CifsNeedReconnect;
116 spin_unlock(&GlobalMid_Lock);
119 cFYI(1, ("Reconnecting tcp session "));
121 /* before reconnecting the tcp session, mark the smb session (uid)
122 and the tid bad so they are not used until reconnected */
123 read_lock(&GlobalSMBSeslock);
124 list_for_each(tmp, &GlobalSMBSessionList) {
125 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
127 if (ses->server == server) {
128 ses->status = CifsNeedReconnect;
132 /* else tcp and smb sessions need reconnection */
134 list_for_each(tmp, &GlobalTreeConnectionList) {
135 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
136 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
137 tcon->tidStatus = CifsNeedReconnect;
140 read_unlock(&GlobalSMBSeslock);
141 /* do not want to be sending data on a socket we are freeing */
142 down(&server->tcpSem);
143 if(server->ssocket) {
144 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
145 server->ssocket->flags));
146 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
147 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
148 server->ssocket->flags));
149 sock_release(server->ssocket);
150 server->ssocket = NULL;
153 spin_lock(&GlobalMid_Lock);
154 list_for_each(tmp, &server->pending_mid_q) {
155 mid_entry = list_entry(tmp, struct
159 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
160 /* Mark other intransit requests as needing
161 retry so we do not immediately mark the
162 session bad again (ie after we reconnect
163 below) as they timeout too */
164 mid_entry->midState = MID_RETRY_NEEDED;
168 spin_unlock(&GlobalMid_Lock);
171 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
173 if(server->protocolType == IPV6) {
174 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
176 rc = ipv4_connect(&server->addr.sockAddr,
178 server->workstation_RFC1001_name);
181 set_current_state(TASK_INTERRUPTIBLE);
182 schedule_timeout(3 * HZ);
184 atomic_inc(&tcpSesReconnectCount);
185 spin_lock(&GlobalMid_Lock);
186 if(server->tcpStatus != CifsExiting)
187 server->tcpStatus = CifsGood;
188 server->sequence_number = 0;
189 spin_unlock(&GlobalMid_Lock);
190 /* atomic_set(&server->inFlight,0);*/
191 wake_up(&server->response_q);
198 cifs_demultiplex_thread(struct TCP_Server_Info *server)
201 unsigned int pdu_length, total_read;
202 struct smb_hdr *smb_buffer = NULL;
203 struct smb_hdr *bigbuf = NULL;
204 struct smb_hdr *smallbuf = NULL;
205 struct msghdr smb_msg;
207 struct socket *csocket = server->ssocket;
208 struct list_head *tmp;
209 struct cifsSesInfo *ses;
210 struct task_struct *task_to_wake = NULL;
211 struct mid_q_entry *mid_entry;
213 int isLargeBuf = FALSE;
216 allow_signal(SIGKILL);
217 current->flags |= PF_MEMALLOC;
218 server->tsk = current; /* save process info to wake at shutdown */
219 cFYI(1, ("Demultiplex PID: %d", current->pid));
220 write_lock(&GlobalSMBSeslock);
221 atomic_inc(&tcpSesAllocCount);
222 length = tcpSesAllocCount.counter;
223 write_unlock(&GlobalSMBSeslock);
225 mempool_resize(cifs_req_poolp,
226 length + cifs_min_rcv,
230 while (server->tcpStatus != CifsExiting) {
231 if (bigbuf == NULL) {
232 bigbuf = cifs_buf_get();
234 cERROR(1,("No memory for large SMB response"));
236 /* retry will check if exiting */
239 } else if(isLargeBuf) {
240 /* we are reusing a dirtry large buf, clear its start */
241 memset(bigbuf, 0, sizeof (struct smb_hdr));
244 if (smallbuf == NULL) {
245 smallbuf = cifs_small_buf_get();
246 if(smallbuf == NULL) {
247 cERROR(1,("No memory for SMB response"));
249 /* retry will check if exiting */
252 /* beginning of smb buffer is cleared in our buf_get */
253 } else /* if existing small buf clear beginning */
254 memset(smallbuf, 0, sizeof (struct smb_hdr));
257 smb_buffer = smallbuf;
258 iov.iov_base = smb_buffer;
260 smb_msg.msg_control = NULL;
261 smb_msg.msg_controllen = 0;
263 kernel_recvmsg(csocket, &smb_msg,
264 &iov, 1, 4, 0 /* BB see socket.h flags */);
266 if(server->tcpStatus == CifsExiting) {
268 } else if (server->tcpStatus == CifsNeedReconnect) {
269 cFYI(1,("Reconnecting after server stopped responding"));
270 cifs_reconnect(server);
271 cFYI(1,("call to reconnect done"));
272 csocket = server->ssocket;
274 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
275 msleep(1); /* minimum sleep to prevent looping
276 allowing socket to clear and app threads to set
277 tcpStatus CifsNeedReconnect if server hung */
279 } else if (length <= 0) {
280 if(server->tcpStatus == CifsNew) {
281 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
282 /* some servers kill the TCP session rather than
283 returning an SMB negprot error, in which
284 case reconnecting here is not going to help,
285 and so simply return error to mount */
288 if(length == -EINTR) {
289 cFYI(1,("cifsd thread killed"));
292 cFYI(1,("Reconnecting after unexpected peek error %d",length));
293 cifs_reconnect(server);
294 csocket = server->ssocket;
295 wake_up(&server->response_q);
297 } else if (length > 3) {
298 pdu_length = ntohl(smb_buffer->smb_buf_length);
299 /* Only read pdu_length after below checks for too short (due
300 to e.g. int overflow) and too long ie beyond end of buf */
301 cFYI(1,("rfc1002 length(big endian)0x%x)",
304 temp = (char *) smb_buffer;
305 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
306 cFYI(0,("Received 4 byte keep alive packet"));
307 } else if (temp[0] ==
308 (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
309 cFYI(1,("Good RFC 1002 session rsp"));
310 } else if (temp[0] ==
311 (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
312 /* we get this from Windows 98 instead of
313 an error on SMB negprot response */
314 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
315 if(server->tcpStatus == CifsNew) {
316 /* if nack on negprot (rather than
317 ret of smb negprot error) reconnecting
318 not going to help, ret error to mount */
321 /* give server a second to
322 clean up before reconnect attempt */
324 /* always try 445 first on reconnect
325 since we get NACK on some if we ever
326 connected to port 139 (the NACK is
327 since we do not begin with RFC1001
328 session initialize frame) */
329 server->addr.sockAddr.sin_port =
331 cifs_reconnect(server);
332 csocket = server->ssocket;
333 wake_up(&server->response_q);
336 } else if (temp[0] != (char) 0) {
337 cERROR(1,("Unknown RFC 1002 frame"));
338 cifs_dump_mem(" Received Data: ", temp, length);
339 cifs_reconnect(server);
340 csocket = server->ssocket;
343 if((pdu_length > CIFSMaxBufSize +
344 MAX_CIFS_HDR_SIZE - 4) ||
345 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
347 ("Invalid size SMB length %d and pdu_length %d",
348 length, pdu_length+4));
349 cifs_reconnect(server);
350 csocket = server->ssocket;
351 wake_up(&server->response_q);
353 } else { /* length ok */
354 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
356 memcpy(bigbuf, smallbuf, 4);
360 iov.iov_base = 4 + (char *)smb_buffer;
361 iov.iov_len = pdu_length;
363 total_read < pdu_length;
364 total_read += length) {
365 length = kernel_recvmsg(csocket, &smb_msg,
367 pdu_length - total_read, 0);
368 if((server->tcpStatus == CifsExiting) ||
369 (length == -EINTR)) {
372 } else if (server->tcpStatus ==
374 cifs_reconnect(server);
375 csocket = server->ssocket;
376 /* Reconnect wakes up rspns q */
377 /* Now we will reread sock */
379 } else if ((length == -ERESTARTSYS) ||
380 (length == -EAGAIN)) {
381 msleep(1); /* minimum sleep to prevent looping
382 allowing socket to clear and app threads to set
383 tcpStatus CifsNeedReconnect if server hung */
385 } else if (length <= 0) {
387 ("Received no data, expecting %d",
388 pdu_length - total_read));
389 cifs_reconnect(server);
390 csocket = server->ssocket;
394 length += 4; /* account for rfc1002 hdr */
397 dump_smb(smb_buffer, length);
399 (smb_buffer, smb_buffer->Mid, total_read+4)) {
400 cERROR(1, ("Bad SMB Received "));
404 /* BB FIXME - add checkTrans2SMBSecondary() */
407 spin_lock(&GlobalMid_Lock);
408 list_for_each(tmp, &server->pending_mid_q) {
409 mid_entry = list_entry(tmp, struct
413 if ((mid_entry->mid == smb_buffer->Mid)
414 && (mid_entry->midState ==
415 MID_REQUEST_SUBMITTED)
416 && (mid_entry->command ==
417 smb_buffer->Command)) {
418 cFYI(1,("Found Mid 0x%x wake up"
420 task_to_wake = mid_entry->tsk;
421 mid_entry->resp_buf =
423 mid_entry->midState =
424 MID_RESPONSE_RECEIVED;
426 mid_entry->largeBuf = 1;
428 mid_entry->largeBuf = 0;
431 spin_unlock(&GlobalMid_Lock);
437 smb_buffer = NULL; /* will be freed by users thread after he is done */
438 wake_up_process(task_to_wake);
439 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
440 cERROR(1, ("No task to wake, unknown frame rcvd!"));
441 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
446 ("Frame less than four bytes received %d bytes long.",
448 cifs_reconnect(server);
449 csocket = server->ssocket;
450 wake_up(&server->response_q);
454 cFYI(1,("Exiting cifsd loop"));
457 spin_lock(&GlobalMid_Lock);
458 server->tcpStatus = CifsExiting;
460 atomic_set(&server->inFlight, 0);
461 spin_unlock(&GlobalMid_Lock);
462 /* Although there should not be any requests blocked on
463 this queue it can not hurt to be paranoid and try to wake up requests
464 that may haven been blocked when more than 50 at time were on the wire
465 to the same server - they now will see the session is in exit state
466 and get out of SendReceive. */
467 wake_up_all(&server->request_q);
468 /* give those requests time to exit */
471 if(server->ssocket) {
472 sock_release(csocket);
473 server->ssocket = NULL;
475 /* buffer usuallly freed in free_mid - need to free it here on exit */
477 cifs_buf_release(bigbuf);
478 if (smallbuf != NULL)
479 cifs_small_buf_release(smallbuf);
481 read_lock(&GlobalSMBSeslock);
482 if (list_empty(&server->pending_mid_q)) {
483 /* loop through server session structures attached to this and
485 list_for_each(tmp, &GlobalSMBSessionList) {
487 list_entry(tmp, struct cifsSesInfo,
489 if (ses->server == server) {
490 ses->status = CifsExiting;
494 read_unlock(&GlobalSMBSeslock);
496 spin_lock(&GlobalMid_Lock);
497 list_for_each(tmp, &server->pending_mid_q) {
498 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
499 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
501 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
502 task_to_wake = mid_entry->tsk;
504 wake_up_process(task_to_wake);
508 spin_unlock(&GlobalMid_Lock);
509 read_unlock(&GlobalSMBSeslock);
510 /* 1/8th of sec is more than enough time for them to exit */
514 if (list_empty(&server->pending_mid_q)) {
515 /* mpx threads have not exited yet give them
516 at least the smb send timeout time for long ops */
517 cFYI(1, ("Wait for exit from demultiplex thread"));
519 /* if threads still have not exited they are probably never
520 coming home not much else we can do but free the memory */
524 write_lock(&GlobalSMBSeslock);
525 atomic_dec(&tcpSesAllocCount);
526 length = tcpSesAllocCount.counter;
527 write_unlock(&GlobalSMBSeslock);
529 mempool_resize(cifs_req_poolp,
530 length + cifs_min_rcv,
539 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
543 unsigned int temp_len, i, j;
549 memset(vol->source_rfc1001_name,0x20,15);
550 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
551 /* does not have to be a perfect mapping since the field is
552 informational, only used for servers that do not support
553 port 445 and it can be overridden at mount time */
554 vol->source_rfc1001_name[i] =
555 toupper(system_utsname.nodename[i]);
557 vol->source_rfc1001_name[15] = 0;
559 vol->linux_uid = current->uid; /* current->euid instead? */
560 vol->linux_gid = current->gid;
561 vol->dir_mode = S_IRWXUGO;
562 /* 2767 perms indicate mandatory locking support */
563 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
565 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
571 if(strncmp(options,"sep=",4) == 0) {
572 if(options[4] != 0) {
573 separator[0] = options[4];
576 cFYI(1,("Null separator not allowed"));
580 while ((data = strsep(&options, separator)) != NULL) {
583 if ((value = strchr(data, '=')) != NULL)
586 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
588 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
590 } else if (strnicmp(data, "user", 4) == 0) {
591 if (!value || !*value) {
593 "CIFS: invalid or missing username\n");
594 return 1; /* needs_arg; */
596 if (strnlen(value, 200) < 200) {
597 vol->username = value;
599 printk(KERN_WARNING "CIFS: username too long\n");
602 } else if (strnicmp(data, "pass", 4) == 0) {
604 vol->password = NULL;
606 } else if(value[0] == 0) {
607 /* check if string begins with double comma
608 since that would mean the password really
609 does start with a comma, and would not
610 indicate an empty string */
611 if(value[1] != separator[0]) {
612 vol->password = NULL;
616 temp_len = strlen(value);
617 /* removed password length check, NTLM passwords
618 can be arbitrarily long */
620 /* if comma in password, the string will be
621 prematurely null terminated. Commas in password are
622 specified across the cifs mount interface by a double
623 comma ie ,, and a comma used as in other cases ie ','
624 as a parameter delimiter/separator is single and due
625 to the strsep above is temporarily zeroed. */
627 /* NB: password legally can have multiple commas and
628 the only illegal character in a password is null */
630 if ((value[temp_len] == 0) &&
631 (value[temp_len+1] == separator[0])) {
633 value[temp_len] = separator[0];
634 temp_len+=2; /* move after the second comma */
635 while(value[temp_len] != 0) {
636 if (value[temp_len] == separator[0]) {
637 if (value[temp_len+1] ==
639 /* skip second comma */
642 /* single comma indicating start
649 if(value[temp_len] == 0) {
653 /* point option to start of next parm */
654 options = value + temp_len + 1;
656 /* go from value to value + temp_len condensing
657 double commas to singles. Note that this ends up
658 allocating a few bytes too many, which is ok */
659 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
660 if(vol->password == NULL) {
661 printk("CIFS: no memory for pass\n");
664 for(i=0,j=0;i<temp_len;i++,j++) {
665 vol->password[j] = value[i];
666 if(value[i] == separator[0]
667 && value[i+1] == separator[0]) {
668 /* skip second comma */
672 vol->password[j] = 0;
674 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
675 if(vol->password == NULL) {
676 printk("CIFS: no memory for pass\n");
679 strcpy(vol->password, value);
681 } else if (strnicmp(data, "ip", 2) == 0) {
682 if (!value || !*value) {
684 } else if (strnlen(value, 35) < 35) {
687 printk(KERN_WARNING "CIFS: ip address too long\n");
690 } else if ((strnicmp(data, "unc", 3) == 0)
691 || (strnicmp(data, "target", 6) == 0)
692 || (strnicmp(data, "path", 4) == 0)) {
693 if (!value || !*value) {
695 "CIFS: invalid path to network resource\n");
696 return 1; /* needs_arg; */
698 if ((temp_len = strnlen(value, 300)) < 300) {
699 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
702 strcpy(vol->UNC,value);
703 if (strncmp(vol->UNC, "//", 2) == 0) {
706 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
708 "CIFS: UNC Path does not begin with // or \\\\ \n");
712 printk(KERN_WARNING "CIFS: UNC name too long\n");
715 } else if ((strnicmp(data, "domain", 3) == 0)
716 || (strnicmp(data, "workgroup", 5) == 0)) {
717 if (!value || !*value) {
718 printk(KERN_WARNING "CIFS: invalid domain name\n");
719 return 1; /* needs_arg; */
721 /* BB are there cases in which a comma can be valid in
722 a domain name and need special handling? */
723 if (strnlen(value, 65) < 65) {
724 vol->domainname = value;
725 cFYI(1, ("Domain name set"));
727 printk(KERN_WARNING "CIFS: domain name too long\n");
730 } else if (strnicmp(data, "iocharset", 9) == 0) {
731 if (!value || !*value) {
732 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
733 return 1; /* needs_arg; */
735 if (strnlen(value, 65) < 65) {
736 if(strnicmp(value,"default",7))
737 vol->iocharset = value;
738 /* if iocharset not set load_nls_default used by caller */
739 cFYI(1, ("iocharset set to %s",value));
741 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
744 } else if (strnicmp(data, "uid", 3) == 0) {
745 if (value && *value) {
747 simple_strtoul(value, &value, 0);
749 } else if (strnicmp(data, "gid", 3) == 0) {
750 if (value && *value) {
752 simple_strtoul(value, &value, 0);
754 } else if (strnicmp(data, "file_mode", 4) == 0) {
755 if (value && *value) {
757 simple_strtoul(value, &value, 0);
759 } else if (strnicmp(data, "dir_mode", 4) == 0) {
760 if (value && *value) {
762 simple_strtoul(value, &value, 0);
764 } else if (strnicmp(data, "dirmode", 4) == 0) {
765 if (value && *value) {
767 simple_strtoul(value, &value, 0);
769 } else if (strnicmp(data, "port", 4) == 0) {
770 if (value && *value) {
772 simple_strtoul(value, &value, 0);
774 } else if (strnicmp(data, "rsize", 5) == 0) {
775 if (value && *value) {
777 simple_strtoul(value, &value, 0);
779 } else if (strnicmp(data, "wsize", 5) == 0) {
780 if (value && *value) {
782 simple_strtoul(value, &value, 0);
784 } else if (strnicmp(data, "sockopt", 5) == 0) {
785 if (value && *value) {
787 simple_strtoul(value, &value, 0);
789 } else if (strnicmp(data, "netbiosname", 4) == 0) {
790 if (!value || !*value || (*value == ' ')) {
791 cFYI(1,("invalid (empty) netbiosname specified"));
793 memset(vol->source_rfc1001_name,0x20,15);
795 /* BB are there cases in which a comma can be
796 valid in this workstation netbios name (and need
797 special handling)? */
799 /* We do not uppercase netbiosname for user */
803 vol->source_rfc1001_name[i] = value[i];
805 /* The string has 16th byte zero still from
806 set at top of the function */
807 if((i==15) && (value[i] != 0))
808 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
810 } else if (strnicmp(data, "credentials", 4) == 0) {
812 } else if (strnicmp(data, "version", 3) == 0) {
814 } else if (strnicmp(data, "guest",5) == 0) {
816 } else if (strnicmp(data, "rw", 2) == 0) {
818 } else if ((strnicmp(data, "suid", 4) == 0) ||
819 (strnicmp(data, "nosuid", 6) == 0) ||
820 (strnicmp(data, "exec", 4) == 0) ||
821 (strnicmp(data, "noexec", 6) == 0) ||
822 (strnicmp(data, "nodev", 5) == 0) ||
823 (strnicmp(data, "noauto", 6) == 0) ||
824 (strnicmp(data, "dev", 3) == 0)) {
825 /* The mount tool or mount.cifs helper (if present)
826 uses these opts to set flags, and the flags are read
827 by the kernel vfs layer before we get here (ie
828 before read super) so there is no point trying to
829 parse these options again and set anything and it
830 is ok to just ignore them */
832 } else if (strnicmp(data, "ro", 2) == 0) {
834 } else if (strnicmp(data, "hard", 4) == 0) {
836 } else if (strnicmp(data, "soft", 4) == 0) {
838 } else if (strnicmp(data, "perm", 4) == 0) {
840 } else if (strnicmp(data, "noperm", 6) == 0) {
842 } else if (strnicmp(data, "mapchars", 8) == 0) {
844 } else if (strnicmp(data, "nomapchars", 10) == 0) {
846 } else if (strnicmp(data, "setuids", 7) == 0) {
848 } else if (strnicmp(data, "nosetuids", 9) == 0) {
850 } else if (strnicmp(data, "nohard", 6) == 0) {
852 } else if (strnicmp(data, "nosoft", 6) == 0) {
854 } else if (strnicmp(data, "nointr", 6) == 0) {
856 } else if (strnicmp(data, "intr", 4) == 0) {
858 } else if (strnicmp(data, "serverino",7) == 0) {
860 } else if (strnicmp(data, "noserverino",9) == 0) {
862 } else if (strnicmp(data, "acl",3) == 0) {
864 } else if (strnicmp(data, "noacl",5) == 0) {
866 } else if (strnicmp(data, "direct",6) == 0) {
868 } else if (strnicmp(data, "forcedirectio",13) == 0) {
870 } else if (strnicmp(data, "in6_addr",8) == 0) {
871 if (!value || !*value) {
872 vol->in6_addr = NULL;
873 } else if (strnlen(value, 49) == 48) {
874 vol->in6_addr = value;
876 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
879 } else if (strnicmp(data, "noac", 4) == 0) {
880 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
882 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
884 if (vol->UNC == NULL) {
885 if(devname == NULL) {
886 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
889 if ((temp_len = strnlen(devname, 300)) < 300) {
890 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
893 strcpy(vol->UNC,devname);
894 if (strncmp(vol->UNC, "//", 2) == 0) {
897 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
898 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
902 printk(KERN_WARNING "CIFS: UNC name too long\n");
906 if(vol->UNCip == NULL)
907 vol->UNCip = &vol->UNC[2];
912 static struct cifsSesInfo *
913 cifs_find_tcp_session(struct in_addr * target_ip_addr,
914 struct in6_addr *target_ip6_addr,
915 char *userName, struct TCP_Server_Info **psrvTcp)
917 struct list_head *tmp;
918 struct cifsSesInfo *ses;
920 read_lock(&GlobalSMBSeslock);
922 list_for_each(tmp, &GlobalSMBSessionList) {
923 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
925 if((target_ip_addr &&
926 (ses->server->addr.sockAddr.sin_addr.s_addr
927 == target_ip_addr->s_addr)) || (target_ip6_addr
928 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
929 target_ip6_addr,sizeof(*target_ip6_addr)))){
930 /* BB lock server and tcp session and increment use count here?? */
931 *psrvTcp = ses->server; /* found a match on the TCP session */
932 /* BB check if reconnection needed */
934 (ses->userName, userName,
935 MAX_USERNAME_SIZE) == 0){
936 read_unlock(&GlobalSMBSeslock);
937 return ses; /* found exact match on both tcp and SMB sessions */
941 /* else tcp and smb sessions need reconnection */
943 read_unlock(&GlobalSMBSeslock);
947 static struct cifsTconInfo *
948 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
950 struct list_head *tmp;
951 struct cifsTconInfo *tcon;
953 read_lock(&GlobalSMBSeslock);
954 list_for_each(tmp, &GlobalTreeConnectionList) {
955 cFYI(1, ("Next tcon - "));
956 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
958 if (tcon->ses->server) {
960 (" old ip addr: %x == new ip %x ?",
961 tcon->ses->server->addr.sockAddr.sin_addr.
962 s_addr, new_target_ip_addr));
963 if (tcon->ses->server->addr.sockAddr.sin_addr.
964 s_addr == new_target_ip_addr) {
965 /* BB lock tcon and server and tcp session and increment use count here? */
966 /* found a match on the TCP session */
967 /* BB check if reconnection needed */
968 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
969 tcon->treeName, uncName));
971 (tcon->treeName, uncName,
972 MAX_TREE_SIZE) == 0) {
974 ("Matched UNC, old user: %s == new: %s ?",
975 tcon->treeName, uncName));
977 (tcon->ses->userName,
979 MAX_USERNAME_SIZE) == 0) {
980 read_unlock(&GlobalSMBSeslock);
981 return tcon;/* also matched user (smb session)*/
988 read_unlock(&GlobalSMBSeslock);
993 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
994 const char *old_path, const struct nls_table *nls_codepage,
997 unsigned char *referrals = NULL;
998 unsigned int num_referrals;
1001 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1002 &num_referrals, &referrals, remap);
1004 /* BB Add in code to: if valid refrl, if not ip address contact
1005 the helper that resolves tcp names, mount to it, try to
1006 tcon to it unmount it if fail */
1015 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1016 const char *old_path, const struct nls_table *nls_codepage,
1017 unsigned int *pnum_referrals,
1018 unsigned char ** preferrals, int remap)
1023 *pnum_referrals = 0;
1025 if (pSesInfo->ipc_tid == 0) {
1026 temp_unc = kmalloc(2 /* for slashes */ +
1027 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1028 + 1 + 4 /* slash IPC$ */ + 2,
1030 if (temp_unc == NULL)
1034 strcpy(temp_unc + 2, pSesInfo->serverName);
1035 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1036 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1038 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1042 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1043 pnum_referrals, nls_codepage, remap);
1048 /* See RFC1001 section 14 on representation of Netbios names */
1049 static void rfc1002mangle(char * target,char * source, unsigned int length)
1053 for(i=0,j=0;i<(length);i++) {
1054 /* mask a nibble at a time and encode */
1055 target[j] = 'A' + (0x0F & (source[i] >> 4));
1056 target[j+1] = 'A' + (0x0F & source[i]);
1064 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1065 char * netbios_name)
1069 __be16 orig_port = 0;
1071 if(*csocket == NULL) {
1072 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1074 cERROR(1, ("Error %d creating socket",rc));
1078 /* BB other socket options to set KEEPALIVE, NODELAY? */
1079 cFYI(1,("Socket created"));
1080 (*csocket)->sk->sk_allocation = GFP_NOFS;
1084 psin_server->sin_family = AF_INET;
1085 if(psin_server->sin_port) { /* user overrode default port */
1086 rc = (*csocket)->ops->connect(*csocket,
1087 (struct sockaddr *) psin_server,
1088 sizeof (struct sockaddr_in),0);
1094 /* save original port so we can retry user specified port
1095 later if fall back ports fail this time */
1096 orig_port = psin_server->sin_port;
1098 /* do not retry on the same port we just failed on */
1099 if(psin_server->sin_port != htons(CIFS_PORT)) {
1100 psin_server->sin_port = htons(CIFS_PORT);
1102 rc = (*csocket)->ops->connect(*csocket,
1103 (struct sockaddr *) psin_server,
1104 sizeof (struct sockaddr_in),0);
1110 psin_server->sin_port = htons(RFC1001_PORT);
1111 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1112 psin_server, sizeof (struct sockaddr_in),0);
1117 /* give up here - unless we want to retry on different
1118 protocol families some day */
1121 psin_server->sin_port = orig_port;
1122 cFYI(1,("Error %d connecting to server via ipv4",rc));
1123 sock_release(*csocket);
1127 /* Eventually check for other socket options to change from
1128 the default. sock_setsockopt not used because it expects
1129 user space buffer */
1130 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1132 /* send RFC1001 sessinit */
1134 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1135 /* some servers require RFC1001 sessinit before sending
1136 negprot - BB check reconnection in case where second
1137 sessinit is sent but no second negprot */
1138 struct rfc1002_session_packet * ses_init_buf;
1139 struct smb_hdr * smb_buf;
1140 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1142 ses_init_buf->trailer.session_req.called_len = 32;
1143 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1144 DEFAULT_CIFS_CALLED_NAME,16);
1145 ses_init_buf->trailer.session_req.calling_len = 32;
1146 /* calling name ends in null (byte 16) from old smb
1148 if(netbios_name && (netbios_name[0] !=0)) {
1149 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1152 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1153 "LINUX_CIFS_CLNT",16);
1155 ses_init_buf->trailer.session_req.scope1 = 0;
1156 ses_init_buf->trailer.session_req.scope2 = 0;
1157 smb_buf = (struct smb_hdr *)ses_init_buf;
1158 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1159 smb_buf->smb_buf_length = 0x81000044;
1160 rc = smb_send(*csocket, smb_buf, 0x44,
1161 (struct sockaddr *)psin_server);
1162 kfree(ses_init_buf);
1164 /* else the negprot may still work without this
1165 even though malloc failed */
1173 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1177 __be16 orig_port = 0;
1179 if(*csocket == NULL) {
1180 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1182 cERROR(1, ("Error %d creating ipv6 socket",rc));
1186 /* BB other socket options to set KEEPALIVE, NODELAY? */
1187 cFYI(1,("ipv6 Socket created"));
1188 (*csocket)->sk->sk_allocation = GFP_NOFS;
1192 psin_server->sin6_family = AF_INET6;
1194 if(psin_server->sin6_port) { /* user overrode default port */
1195 rc = (*csocket)->ops->connect(*csocket,
1196 (struct sockaddr *) psin_server,
1197 sizeof (struct sockaddr_in6),0);
1203 /* save original port so we can retry user specified port
1204 later if fall back ports fail this time */
1206 orig_port = psin_server->sin6_port;
1207 /* do not retry on the same port we just failed on */
1208 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1209 psin_server->sin6_port = htons(CIFS_PORT);
1211 rc = (*csocket)->ops->connect(*csocket,
1212 (struct sockaddr *) psin_server,
1213 sizeof (struct sockaddr_in6),0);
1219 psin_server->sin6_port = htons(RFC1001_PORT);
1220 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1221 psin_server, sizeof (struct sockaddr_in6),0);
1226 /* give up here - unless we want to retry on different
1227 protocol families some day */
1230 psin_server->sin6_port = orig_port;
1231 cFYI(1,("Error %d connecting to server via ipv6",rc));
1232 sock_release(*csocket);
1236 /* Eventually check for other socket options to change from
1237 the default. sock_setsockopt not used because it expects
1238 user space buffer */
1239 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1245 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1246 char *mount_data, const char *devname)
1250 int address_type = AF_INET;
1251 struct socket *csocket = NULL;
1252 struct sockaddr_in sin_server;
1253 struct sockaddr_in6 sin_server6;
1254 struct smb_vol volume_info;
1255 struct cifsSesInfo *pSesInfo = NULL;
1256 struct cifsSesInfo *existingCifsSes = NULL;
1257 struct cifsTconInfo *tcon = NULL;
1258 struct TCP_Server_Info *srvTcp = NULL;
1262 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1264 memset(&volume_info,0,sizeof(struct smb_vol));
1265 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1267 kfree(volume_info.UNC);
1268 if(volume_info.password)
1269 kfree(volume_info.password);
1274 if (volume_info.username) {
1275 /* BB fixme parse for domain name here */
1276 cFYI(1, ("Username: %s ", volume_info.username));
1279 cifserror("No username specified ");
1280 /* In userspace mount helper we can get user name from alternate
1281 locations such as env variables and files on disk */
1283 kfree(volume_info.UNC);
1284 if(volume_info.password)
1285 kfree(volume_info.password);
1290 if (volume_info.UNCip && volume_info.UNC) {
1291 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1294 /* not ipv4 address, try ipv6 */
1295 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1297 address_type = AF_INET6;
1299 address_type = AF_INET;
1303 /* we failed translating address */
1305 kfree(volume_info.UNC);
1306 if(volume_info.password)
1307 kfree(volume_info.password);
1312 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1315 } else if (volume_info.UNCip){
1316 /* BB using ip addr as server name connect to the DFS root below */
1317 cERROR(1,("Connecting to DFS root not implemented yet"));
1319 kfree(volume_info.UNC);
1320 if(volume_info.password)
1321 kfree(volume_info.password);
1324 } else /* which servers DFS root would we conect to */ {
1326 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1328 kfree(volume_info.UNC);
1329 if(volume_info.password)
1330 kfree(volume_info.password);
1335 /* this is needed for ASCII cp to Unicode converts */
1336 if(volume_info.iocharset == NULL) {
1337 cifs_sb->local_nls = load_nls_default();
1338 /* load_nls_default can not return null */
1340 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1341 if(cifs_sb->local_nls == NULL) {
1342 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1344 kfree(volume_info.UNC);
1345 if(volume_info.password)
1346 kfree(volume_info.password);
1352 if(address_type == AF_INET)
1353 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1354 NULL /* no ipv6 addr */,
1355 volume_info.username, &srvTcp);
1356 else if(address_type == AF_INET6)
1357 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1358 &sin_server6.sin6_addr,
1359 volume_info.username, &srvTcp);
1362 kfree(volume_info.UNC);
1363 if(volume_info.password)
1364 kfree(volume_info.password);
1371 cFYI(1, ("Existing tcp session with server found "));
1372 } else { /* create socket */
1373 if(volume_info.port)
1374 sin_server.sin_port = htons(volume_info.port);
1376 sin_server.sin_port = 0;
1377 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1380 ("Error connecting to IPv4 socket. Aborting operation"));
1382 sock_release(csocket);
1384 kfree(volume_info.UNC);
1385 if(volume_info.password)
1386 kfree(volume_info.password);
1391 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1392 if (srvTcp == NULL) {
1394 sock_release(csocket);
1396 kfree(volume_info.UNC);
1397 if(volume_info.password)
1398 kfree(volume_info.password);
1402 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1403 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1404 atomic_set(&srvTcp->inFlight,0);
1405 /* BB Add code for ipv6 case too */
1406 srvTcp->ssocket = csocket;
1407 srvTcp->protocolType = IPV4;
1408 init_waitqueue_head(&srvTcp->response_q);
1409 init_waitqueue_head(&srvTcp->request_q);
1410 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1411 /* at this point we are the only ones with the pointer
1412 to the struct since the kernel thread not created yet
1413 so no need to spinlock this init of tcpStatus */
1414 srvTcp->tcpStatus = CifsNew;
1415 init_MUTEX(&srvTcp->tcpSem);
1416 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1417 CLONE_FS | CLONE_FILES | CLONE_VM);
1420 sock_release(csocket);
1422 kfree(volume_info.UNC);
1423 if(volume_info.password)
1424 kfree(volume_info.password);
1429 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1430 srvTcp->sequence_number = 0;
1434 if (existingCifsSes) {
1435 pSesInfo = existingCifsSes;
1436 cFYI(1, ("Existing smb sess found "));
1437 if(volume_info.password)
1438 kfree(volume_info.password);
1439 /* volume_info.UNC freed at end of function */
1441 cFYI(1, ("Existing smb sess not found "));
1442 pSesInfo = sesInfoAlloc();
1443 if (pSesInfo == NULL)
1446 pSesInfo->server = srvTcp;
1447 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1448 NIPQUAD(sin_server.sin_addr.s_addr));
1452 /* volume_info.password freed at unmount */
1453 if (volume_info.password)
1454 pSesInfo->password = volume_info.password;
1455 if (volume_info.username)
1456 strncpy(pSesInfo->userName,
1457 volume_info.username,MAX_USERNAME_SIZE);
1458 if (volume_info.domainname)
1459 strncpy(pSesInfo->domainName,
1460 volume_info.domainname,MAX_USERNAME_SIZE);
1461 pSesInfo->linux_uid = volume_info.linux_uid;
1462 down(&pSesInfo->sesSem);
1463 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1464 up(&pSesInfo->sesSem);
1466 atomic_inc(&srvTcp->socketUseCount);
1468 if(volume_info.password)
1469 kfree(volume_info.password);
1472 /* search for existing tcon to this server share */
1474 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1475 cifs_sb->rsize = volume_info.rsize;
1477 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1478 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1479 cifs_sb->wsize = volume_info.wsize;
1481 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1482 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1483 cifs_sb->rsize = PAGE_CACHE_SIZE;
1484 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1486 cifs_sb->mnt_uid = volume_info.linux_uid;
1487 cifs_sb->mnt_gid = volume_info.linux_gid;
1488 cifs_sb->mnt_file_mode = volume_info.file_mode;
1489 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1490 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1492 if(volume_info.noperm)
1493 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1494 if(volume_info.setuids)
1495 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1496 if(volume_info.server_ino)
1497 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1498 if(volume_info.remap)
1499 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1500 if(volume_info.no_xattr)
1501 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1502 if(volume_info.direct_io) {
1503 cERROR(1,("mounting share using direct i/o"));
1504 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1508 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1509 volume_info.username);
1511 cFYI(1, ("Found match on UNC path "));
1512 /* we can have only one retry value for a connection
1513 to a share so for resources mounted more than once
1514 to the same server share the last value passed in
1515 for the retry flag is used */
1516 tcon->retry = volume_info.retry;
1518 tcon = tconInfoAlloc();
1522 /* check for null share name ie connect to dfs root */
1524 /* BB check if this works for exactly length three strings */
1525 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1526 && (strchr(volume_info.UNC + 3, '/') ==
1528 rc = connect_to_dfs_path(xid, pSesInfo,
1529 "", cifs_sb->local_nls,
1530 cifs_sb->mnt_cifs_flags &
1531 CIFS_MOUNT_MAP_SPECIAL_CHR);
1533 kfree(volume_info.UNC);
1537 rc = CIFSTCon(xid, pSesInfo,
1539 tcon, cifs_sb->local_nls);
1540 cFYI(1, ("CIFS Tcon rc = %d", rc));
1543 atomic_inc(&pSesInfo->inUse);
1544 tcon->retry = volume_info.retry;
1550 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1551 sb->s_maxbytes = (u64) 1 << 63;
1553 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1556 sb->s_time_gran = 100;
1558 /* on error free sesinfo and tcon struct if needed */
1560 /* if session setup failed, use count is zero but
1561 we still need to free cifsd thread */
1562 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1563 spin_lock(&GlobalMid_Lock);
1564 srvTcp->tcpStatus = CifsExiting;
1565 spin_unlock(&GlobalMid_Lock);
1567 send_sig(SIGKILL,srvTcp->tsk,1);
1569 /* If find_unc succeeded then rc == 0 so we can not end */
1570 if (tcon) /* up accidently freeing someone elses tcon struct */
1572 if (existingCifsSes == NULL) {
1574 if ((pSesInfo->server) &&
1575 (pSesInfo->status == CifsGood)) {
1577 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1578 /* if the socketUseCount is now zero */
1579 if((temp_rc == -ESHUTDOWN) &&
1580 (pSesInfo->server->tsk))
1581 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1583 cFYI(1, ("No session or bad tcon"));
1584 sesInfoFree(pSesInfo);
1585 /* pSesInfo = NULL; */
1589 atomic_inc(&tcon->useCount);
1590 cifs_sb->tcon = tcon;
1591 tcon->ses = pSesInfo;
1593 /* do not care if following two calls succeed - informational only */
1594 CIFSSMBQFSDeviceInfo(xid, tcon);
1595 CIFSSMBQFSAttributeInfo(xid, tcon);
1596 if (tcon->ses->capabilities & CAP_UNIX) {
1597 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1598 if(!volume_info.no_psx_acl) {
1599 if(CIFS_UNIX_POSIX_ACL_CAP &
1600 le64_to_cpu(tcon->fsUnixInfo.Capability))
1601 cFYI(1,("server negotiated posix acl support"));
1602 sb->s_flags |= MS_POSIXACL;
1608 /* volume_info.password is freed above when existing session found
1609 (in which case it is not needed anymore) but when new sesion is created
1610 the password ptr is put in the new session structure (in which case the
1611 password will be freed at unmount time) */
1613 kfree(volume_info.UNC);
1619 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1620 char session_key[CIFS_SESSION_KEY_SIZE],
1621 const struct nls_table *nls_codepage)
1623 struct smb_hdr *smb_buffer;
1624 struct smb_hdr *smb_buffer_response;
1625 SESSION_SETUP_ANDX *pSMB;
1626 SESSION_SETUP_ANDX *pSMBr;
1631 int remaining_words = 0;
1632 int bytes_returned = 0;
1637 cFYI(1, ("In sesssetup "));
1640 user = ses->userName;
1641 domain = ses->domainName;
1642 smb_buffer = cifs_buf_get();
1643 if (smb_buffer == NULL) {
1646 smb_buffer_response = smb_buffer;
1647 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1649 /* send SMBsessionSetup here */
1650 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1651 NULL /* no tCon exists yet */ , 13 /* wct */ );
1653 pSMB->req_no_secext.AndXCommand = 0xFF;
1654 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1655 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1657 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1658 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1660 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1661 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1662 if (ses->capabilities & CAP_UNICODE) {
1663 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1664 capabilities |= CAP_UNICODE;
1666 if (ses->capabilities & CAP_STATUS32) {
1667 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1668 capabilities |= CAP_STATUS32;
1670 if (ses->capabilities & CAP_DFS) {
1671 smb_buffer->Flags2 |= SMBFLG2_DFS;
1672 capabilities |= CAP_DFS;
1674 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1676 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1677 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1679 pSMB->req_no_secext.CaseSensitivePasswordLength =
1680 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1681 bcc_ptr = pByteArea(smb_buffer);
1682 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1683 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1684 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1685 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1687 if (ses->capabilities & CAP_UNICODE) {
1688 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1693 bytes_returned = 0; /* skill null user */
1696 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1698 /* convert number of 16 bit words to bytes */
1699 bcc_ptr += 2 * bytes_returned;
1700 bcc_ptr += 2; /* trailing null */
1703 cifs_strtoUCS((wchar_t *) bcc_ptr,
1704 "CIFS_LINUX_DOM", 32, nls_codepage);
1707 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1709 bcc_ptr += 2 * bytes_returned;
1712 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1714 bcc_ptr += 2 * bytes_returned;
1716 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1718 bcc_ptr += 2 * bytes_returned;
1721 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1723 bcc_ptr += 2 * bytes_returned;
1727 strncpy(bcc_ptr, user, 200);
1728 bcc_ptr += strnlen(user, 200);
1732 if (domain == NULL) {
1733 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1734 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1736 strncpy(bcc_ptr, domain, 64);
1737 bcc_ptr += strnlen(domain, 64);
1741 strcpy(bcc_ptr, "Linux version ");
1742 bcc_ptr += strlen("Linux version ");
1743 strcpy(bcc_ptr, system_utsname.release);
1744 bcc_ptr += strlen(system_utsname.release) + 1;
1745 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1746 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1748 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1749 smb_buffer->smb_buf_length += count;
1750 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1752 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1753 &bytes_returned, 1);
1755 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1756 } else if ((smb_buffer_response->WordCount == 3)
1757 || (smb_buffer_response->WordCount == 4)) {
1758 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1759 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1760 if (action & GUEST_LOGIN)
1761 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1762 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1763 cFYI(1, ("UID = %d ", ses->Suid));
1764 /* response can have either 3 or 4 word count - Samba sends 3 */
1765 bcc_ptr = pByteArea(smb_buffer_response);
1766 if ((pSMBr->resp.hdr.WordCount == 3)
1767 || ((pSMBr->resp.hdr.WordCount == 4)
1768 && (blob_len < pSMBr->resp.ByteCount))) {
1769 if (pSMBr->resp.hdr.WordCount == 4)
1770 bcc_ptr += blob_len;
1772 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1773 if ((long) (bcc_ptr) % 2) {
1775 (BCC(smb_buffer_response) - 1) /2;
1776 bcc_ptr++; /* Unicode strings must be word aligned */
1779 BCC(smb_buffer_response) / 2;
1782 UniStrnlen((wchar_t *) bcc_ptr,
1783 remaining_words - 1);
1784 /* We look for obvious messed up bcc or strings in response so we do not go off
1785 the end since (at least) WIN2K and Windows XP have a major bug in not null
1786 terminating last Unicode string in response */
1787 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1788 if(ses->serverOS == NULL)
1789 goto sesssetup_nomem;
1790 cifs_strfromUCS_le(ses->serverOS,
1791 (wchar_t *)bcc_ptr, len,nls_codepage);
1792 bcc_ptr += 2 * (len + 1);
1793 remaining_words -= len + 1;
1794 ses->serverOS[2 * len] = 0;
1795 ses->serverOS[1 + (2 * len)] = 0;
1796 if (remaining_words > 0) {
1797 len = UniStrnlen((wchar_t *)bcc_ptr,
1799 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
1800 if(ses->serverNOS == NULL)
1801 goto sesssetup_nomem;
1802 cifs_strfromUCS_le(ses->serverNOS,
1803 (wchar_t *)bcc_ptr,len,nls_codepage);
1804 bcc_ptr += 2 * (len + 1);
1805 ses->serverNOS[2 * len] = 0;
1806 ses->serverNOS[1 + (2 * len)] = 0;
1807 if(strncmp(ses->serverNOS,
1808 "NT LAN Manager 4",16) == 0) {
1809 cFYI(1,("NT4 server"));
1810 ses->flags |= CIFS_SES_NT4;
1812 remaining_words -= len + 1;
1813 if (remaining_words > 0) {
1814 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1815 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1817 kcalloc(1, 2*(len+1),GFP_KERNEL);
1818 if(ses->serverDomain == NULL)
1819 goto sesssetup_nomem;
1820 cifs_strfromUCS_le(ses->serverDomain,
1821 (wchar_t *)bcc_ptr,len,nls_codepage);
1822 bcc_ptr += 2 * (len + 1);
1823 ses->serverDomain[2*len] = 0;
1824 ses->serverDomain[1+(2*len)] = 0;
1825 } /* else no more room so create dummy domain string */
1828 kcalloc(1, 2, GFP_KERNEL);
1829 } else { /* no room so create dummy domain and NOS string */
1830 /* if these kcallocs fail not much we
1831 can do, but better to not fail the
1834 kcalloc(1, 2, GFP_KERNEL);
1836 kcalloc(1, 2, GFP_KERNEL);
1838 } else { /* ASCII */
1839 len = strnlen(bcc_ptr, 1024);
1840 if (((long) bcc_ptr + len) - (long)
1841 pByteArea(smb_buffer_response)
1842 <= BCC(smb_buffer_response)) {
1843 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
1844 if(ses->serverOS == NULL)
1845 goto sesssetup_nomem;
1846 strncpy(ses->serverOS,bcc_ptr, len);
1849 bcc_ptr[0] = 0; /* null terminate the string */
1852 len = strnlen(bcc_ptr, 1024);
1853 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
1854 if(ses->serverNOS == NULL)
1855 goto sesssetup_nomem;
1856 strncpy(ses->serverNOS, bcc_ptr, len);
1861 len = strnlen(bcc_ptr, 1024);
1862 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
1863 if(ses->serverDomain == NULL)
1864 goto sesssetup_nomem;
1865 strncpy(ses->serverDomain, bcc_ptr, len);
1871 ("Variable field of length %d extends beyond end of smb ",
1876 (" Security Blob Length extends beyond end of SMB"));
1880 (" Invalid Word count %d: ",
1881 smb_buffer_response->WordCount));
1884 sesssetup_nomem: /* do not return an error on nomem for the info strings,
1885 since that could make reconnection harder, and
1886 reconnection might be needed to free memory */
1888 cifs_buf_release(smb_buffer);
1894 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1895 char *SecurityBlob,int SecurityBlobLength,
1896 const struct nls_table *nls_codepage)
1898 struct smb_hdr *smb_buffer;
1899 struct smb_hdr *smb_buffer_response;
1900 SESSION_SETUP_ANDX *pSMB;
1901 SESSION_SETUP_ANDX *pSMBr;
1906 int remaining_words = 0;
1907 int bytes_returned = 0;
1912 cFYI(1, ("In spnego sesssetup "));
1915 user = ses->userName;
1916 domain = ses->domainName;
1918 smb_buffer = cifs_buf_get();
1919 if (smb_buffer == NULL) {
1922 smb_buffer_response = smb_buffer;
1923 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1925 /* send SMBsessionSetup here */
1926 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1927 NULL /* no tCon exists yet */ , 12 /* wct */ );
1928 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1929 pSMB->req.AndXCommand = 0xFF;
1930 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1931 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1933 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1934 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1936 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1937 CAP_EXTENDED_SECURITY;
1938 if (ses->capabilities & CAP_UNICODE) {
1939 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1940 capabilities |= CAP_UNICODE;
1942 if (ses->capabilities & CAP_STATUS32) {
1943 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1944 capabilities |= CAP_STATUS32;
1946 if (ses->capabilities & CAP_DFS) {
1947 smb_buffer->Flags2 |= SMBFLG2_DFS;
1948 capabilities |= CAP_DFS;
1950 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1952 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1953 bcc_ptr = pByteArea(smb_buffer);
1954 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1955 bcc_ptr += SecurityBlobLength;
1957 if (ses->capabilities & CAP_UNICODE) {
1958 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1963 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1964 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1965 bcc_ptr += 2; /* trailing null */
1968 cifs_strtoUCS((wchar_t *) bcc_ptr,
1969 "CIFS_LINUX_DOM", 32, nls_codepage);
1972 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1974 bcc_ptr += 2 * bytes_returned;
1977 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1979 bcc_ptr += 2 * bytes_returned;
1981 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
1983 bcc_ptr += 2 * bytes_returned;
1986 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1988 bcc_ptr += 2 * bytes_returned;
1991 strncpy(bcc_ptr, user, 200);
1992 bcc_ptr += strnlen(user, 200);
1995 if (domain == NULL) {
1996 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1997 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1999 strncpy(bcc_ptr, domain, 64);
2000 bcc_ptr += strnlen(domain, 64);
2004 strcpy(bcc_ptr, "Linux version ");
2005 bcc_ptr += strlen("Linux version ");
2006 strcpy(bcc_ptr, system_utsname.release);
2007 bcc_ptr += strlen(system_utsname.release) + 1;
2008 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2009 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2011 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2012 smb_buffer->smb_buf_length += count;
2013 pSMB->req.ByteCount = cpu_to_le16(count);
2015 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2016 &bytes_returned, 1);
2018 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2019 } else if ((smb_buffer_response->WordCount == 3)
2020 || (smb_buffer_response->WordCount == 4)) {
2021 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2023 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2024 if (action & GUEST_LOGIN)
2025 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2027 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2028 cFYI(1, ("UID = %d ", ses->Suid));
2029 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2031 /* BB Fix below to make endian neutral !! */
2033 if ((pSMBr->resp.hdr.WordCount == 3)
2034 || ((pSMBr->resp.hdr.WordCount == 4)
2036 pSMBr->resp.ByteCount))) {
2037 if (pSMBr->resp.hdr.WordCount == 4) {
2041 ("Security Blob Length %d ",
2045 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2046 if ((long) (bcc_ptr) % 2) {
2048 (BCC(smb_buffer_response)
2050 bcc_ptr++; /* Unicode strings must be word aligned */
2054 (smb_buffer_response) / 2;
2057 UniStrnlen((wchar_t *) bcc_ptr,
2058 remaining_words - 1);
2059 /* We look for obvious messed up bcc or strings in response so we do not go off
2060 the end since (at least) WIN2K and Windows XP have a major bug in not null
2061 terminating last Unicode string in response */
2063 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2064 cifs_strfromUCS_le(ses->serverOS,
2068 bcc_ptr += 2 * (len + 1);
2069 remaining_words -= len + 1;
2070 ses->serverOS[2 * len] = 0;
2071 ses->serverOS[1 + (2 * len)] = 0;
2072 if (remaining_words > 0) {
2073 len = UniStrnlen((wchar_t *)bcc_ptr,
2077 kcalloc(1, 2 * (len + 1),
2079 cifs_strfromUCS_le(ses->serverNOS,
2083 bcc_ptr += 2 * (len + 1);
2084 ses->serverNOS[2 * len] = 0;
2085 ses->serverNOS[1 + (2 * len)] = 0;
2086 remaining_words -= len + 1;
2087 if (remaining_words > 0) {
2088 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2089 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2090 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2091 cifs_strfromUCS_le(ses->serverDomain,
2095 bcc_ptr += 2*(len+1);
2096 ses->serverDomain[2*len] = 0;
2097 ses->serverDomain[1+(2*len)] = 0;
2098 } /* else no more room so create dummy domain string */
2101 kcalloc(1, 2,GFP_KERNEL);
2102 } else { /* no room so create dummy domain and NOS string */
2103 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2104 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2106 } else { /* ASCII */
2108 len = strnlen(bcc_ptr, 1024);
2109 if (((long) bcc_ptr + len) - (long)
2110 pByteArea(smb_buffer_response)
2111 <= BCC(smb_buffer_response)) {
2112 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2113 strncpy(ses->serverOS, bcc_ptr, len);
2116 bcc_ptr[0] = 0; /* null terminate the string */
2119 len = strnlen(bcc_ptr, 1024);
2120 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2121 strncpy(ses->serverNOS, bcc_ptr, len);
2126 len = strnlen(bcc_ptr, 1024);
2127 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2128 strncpy(ses->serverDomain, bcc_ptr, len);
2134 ("Variable field of length %d extends beyond end of smb ",
2139 (" Security Blob Length extends beyond end of SMB"));
2142 cERROR(1, ("No session structure passed in."));
2146 (" Invalid Word count %d: ",
2147 smb_buffer_response->WordCount));
2152 cifs_buf_release(smb_buffer);
2158 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2159 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2160 const struct nls_table *nls_codepage)
2162 struct smb_hdr *smb_buffer;
2163 struct smb_hdr *smb_buffer_response;
2164 SESSION_SETUP_ANDX *pSMB;
2165 SESSION_SETUP_ANDX *pSMBr;
2169 int remaining_words = 0;
2170 int bytes_returned = 0;
2172 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2173 PNEGOTIATE_MESSAGE SecurityBlob;
2174 PCHALLENGE_MESSAGE SecurityBlob2;
2175 __u32 negotiate_flags, capabilities;
2178 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2181 domain = ses->domainName;
2182 *pNTLMv2_flag = FALSE;
2183 smb_buffer = cifs_buf_get();
2184 if (smb_buffer == NULL) {
2187 smb_buffer_response = smb_buffer;
2188 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2189 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2191 /* send SMBsessionSetup here */
2192 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2193 NULL /* no tCon exists yet */ , 12 /* wct */ );
2194 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2195 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2197 pSMB->req.AndXCommand = 0xFF;
2198 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2199 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2201 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2202 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2204 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2205 CAP_EXTENDED_SECURITY;
2206 if (ses->capabilities & CAP_UNICODE) {
2207 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2208 capabilities |= CAP_UNICODE;
2210 if (ses->capabilities & CAP_STATUS32) {
2211 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2212 capabilities |= CAP_STATUS32;
2214 if (ses->capabilities & CAP_DFS) {
2215 smb_buffer->Flags2 |= SMBFLG2_DFS;
2216 capabilities |= CAP_DFS;
2218 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2220 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2221 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2222 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2223 SecurityBlob->MessageType = NtLmNegotiate;
2225 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2226 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2227 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2229 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2231 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2232 /* setup pointers to domain name and workstation name */
2233 bcc_ptr += SecurityBlobLength;
2235 SecurityBlob->WorkstationName.Buffer = 0;
2236 SecurityBlob->WorkstationName.Length = 0;
2237 SecurityBlob->WorkstationName.MaximumLength = 0;
2239 if (domain == NULL) {
2240 SecurityBlob->DomainName.Buffer = 0;
2241 SecurityBlob->DomainName.Length = 0;
2242 SecurityBlob->DomainName.MaximumLength = 0;
2245 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2246 strncpy(bcc_ptr, domain, 63);
2247 len = strnlen(domain, 64);
2248 SecurityBlob->DomainName.MaximumLength =
2250 SecurityBlob->DomainName.Buffer =
2251 cpu_to_le32((long) &SecurityBlob->
2253 (long) &SecurityBlob->Signature);
2255 SecurityBlobLength += len;
2256 SecurityBlob->DomainName.Length =
2259 if (ses->capabilities & CAP_UNICODE) {
2260 if ((long) bcc_ptr % 2) {
2266 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2268 bcc_ptr += 2 * bytes_returned;
2270 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2272 bcc_ptr += 2 * bytes_returned;
2273 bcc_ptr += 2; /* null terminate Linux version */
2275 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2277 bcc_ptr += 2 * bytes_returned;
2280 bcc_ptr += 2; /* null terminate network opsys string */
2283 bcc_ptr += 2; /* null domain */
2284 } else { /* ASCII */
2285 strcpy(bcc_ptr, "Linux version ");
2286 bcc_ptr += strlen("Linux version ");
2287 strcpy(bcc_ptr, system_utsname.release);
2288 bcc_ptr += strlen(system_utsname.release) + 1;
2289 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2290 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2291 bcc_ptr++; /* empty domain field */
2294 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2295 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2296 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2297 smb_buffer->smb_buf_length += count;
2298 pSMB->req.ByteCount = cpu_to_le16(count);
2300 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2301 &bytes_returned, 1);
2303 if (smb_buffer_response->Status.CifsError ==
2304 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2308 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2309 } else if ((smb_buffer_response->WordCount == 3)
2310 || (smb_buffer_response->WordCount == 4)) {
2311 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2312 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2314 if (action & GUEST_LOGIN)
2315 cFYI(1, (" Guest login"));
2316 /* Do we want to set anything in SesInfo struct when guest login? */
2318 bcc_ptr = pByteArea(smb_buffer_response);
2319 /* response can have either 3 or 4 word count - Samba sends 3 */
2321 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2322 if (SecurityBlob2->MessageType != NtLmChallenge) {
2324 ("Unexpected NTLMSSP message type received %d",
2325 SecurityBlob2->MessageType));
2327 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2328 cFYI(1, ("UID = %d ", ses->Suid));
2329 if ((pSMBr->resp.hdr.WordCount == 3)
2330 || ((pSMBr->resp.hdr.WordCount == 4)
2332 pSMBr->resp.ByteCount))) {
2334 if (pSMBr->resp.hdr.WordCount == 4) {
2335 bcc_ptr += blob_len;
2337 ("Security Blob Length %d ",
2341 cFYI(1, ("NTLMSSP Challenge rcvd "));
2343 memcpy(ses->server->cryptKey,
2344 SecurityBlob2->Challenge,
2345 CIFS_CRYPTO_KEY_SIZE);
2346 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2347 *pNTLMv2_flag = TRUE;
2349 if((SecurityBlob2->NegotiateFlags &
2350 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2351 || (sign_CIFS_PDUs > 1))
2352 ses->server->secMode |=
2353 SECMODE_SIGN_REQUIRED;
2354 if ((SecurityBlob2->NegotiateFlags &
2355 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2356 ses->server->secMode |=
2357 SECMODE_SIGN_ENABLED;
2359 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2360 if ((long) (bcc_ptr) % 2) {
2362 (BCC(smb_buffer_response)
2364 bcc_ptr++; /* Unicode strings must be word aligned */
2368 (smb_buffer_response) / 2;
2371 UniStrnlen((wchar_t *) bcc_ptr,
2372 remaining_words - 1);
2373 /* We look for obvious messed up bcc or strings in response so we do not go off
2374 the end since (at least) WIN2K and Windows XP have a major bug in not null
2375 terminating last Unicode string in response */
2377 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2378 cifs_strfromUCS_le(ses->serverOS,
2382 bcc_ptr += 2 * (len + 1);
2383 remaining_words -= len + 1;
2384 ses->serverOS[2 * len] = 0;
2385 ses->serverOS[1 + (2 * len)] = 0;
2386 if (remaining_words > 0) {
2387 len = UniStrnlen((wchar_t *)
2392 kcalloc(1, 2 * (len + 1),
2394 cifs_strfromUCS_le(ses->
2400 bcc_ptr += 2 * (len + 1);
2401 ses->serverNOS[2 * len] = 0;
2404 remaining_words -= len + 1;
2405 if (remaining_words > 0) {
2406 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2407 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2432 } /* else no more room so create dummy domain string */
2437 } else { /* no room so create dummy domain and NOS string */
2439 kcalloc(1, 2, GFP_KERNEL);
2441 kcalloc(1, 2, GFP_KERNEL);
2443 } else { /* ASCII */
2444 len = strnlen(bcc_ptr, 1024);
2445 if (((long) bcc_ptr + len) - (long)
2446 pByteArea(smb_buffer_response)
2447 <= BCC(smb_buffer_response)) {
2451 strncpy(ses->serverOS,
2455 bcc_ptr[0] = 0; /* null terminate string */
2458 len = strnlen(bcc_ptr, 1024);
2462 strncpy(ses->serverNOS, bcc_ptr, len);
2467 len = strnlen(bcc_ptr, 1024);
2471 strncpy(ses->serverDomain, bcc_ptr, len);
2477 ("Variable field of length %d extends beyond end of smb ",
2482 (" Security Blob Length extends beyond end of SMB"));
2485 cERROR(1, ("No session structure passed in."));
2489 (" Invalid Word count %d: ",
2490 smb_buffer_response->WordCount));
2495 cifs_buf_release(smb_buffer);
2500 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2501 char *ntlm_session_key, int ntlmv2_flag,
2502 const struct nls_table *nls_codepage)
2504 struct smb_hdr *smb_buffer;
2505 struct smb_hdr *smb_buffer_response;
2506 SESSION_SETUP_ANDX *pSMB;
2507 SESSION_SETUP_ANDX *pSMBr;
2512 int remaining_words = 0;
2513 int bytes_returned = 0;
2515 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2516 PAUTHENTICATE_MESSAGE SecurityBlob;
2517 __u32 negotiate_flags, capabilities;
2520 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2523 user = ses->userName;
2524 domain = ses->domainName;
2525 smb_buffer = cifs_buf_get();
2526 if (smb_buffer == NULL) {
2529 smb_buffer_response = smb_buffer;
2530 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2531 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2533 /* send SMBsessionSetup here */
2534 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2535 NULL /* no tCon exists yet */ , 12 /* wct */ );
2536 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2537 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2538 pSMB->req.AndXCommand = 0xFF;
2539 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2540 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2542 pSMB->req.hdr.Uid = ses->Suid;
2544 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2545 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2547 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2548 CAP_EXTENDED_SECURITY;
2549 if (ses->capabilities & CAP_UNICODE) {
2550 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2551 capabilities |= CAP_UNICODE;
2553 if (ses->capabilities & CAP_STATUS32) {
2554 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2555 capabilities |= CAP_STATUS32;
2557 if (ses->capabilities & CAP_DFS) {
2558 smb_buffer->Flags2 |= SMBFLG2_DFS;
2559 capabilities |= CAP_DFS;
2561 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2563 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2564 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2565 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2566 SecurityBlob->MessageType = NtLmAuthenticate;
2567 bcc_ptr += SecurityBlobLength;
2569 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2570 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2571 0x80000000 | NTLMSSP_NEGOTIATE_128;
2573 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2575 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2577 /* setup pointers to domain name and workstation name */
2579 SecurityBlob->WorkstationName.Buffer = 0;
2580 SecurityBlob->WorkstationName.Length = 0;
2581 SecurityBlob->WorkstationName.MaximumLength = 0;
2582 SecurityBlob->SessionKey.Length = 0;
2583 SecurityBlob->SessionKey.MaximumLength = 0;
2584 SecurityBlob->SessionKey.Buffer = 0;
2586 SecurityBlob->LmChallengeResponse.Length = 0;
2587 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2588 SecurityBlob->LmChallengeResponse.Buffer = 0;
2590 SecurityBlob->NtChallengeResponse.Length =
2591 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2592 SecurityBlob->NtChallengeResponse.MaximumLength =
2593 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2594 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2595 SecurityBlob->NtChallengeResponse.Buffer =
2596 cpu_to_le32(SecurityBlobLength);
2597 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2598 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2600 if (ses->capabilities & CAP_UNICODE) {
2601 if (domain == NULL) {
2602 SecurityBlob->DomainName.Buffer = 0;
2603 SecurityBlob->DomainName.Length = 0;
2604 SecurityBlob->DomainName.MaximumLength = 0;
2607 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2610 SecurityBlob->DomainName.MaximumLength =
2612 SecurityBlob->DomainName.Buffer =
2613 cpu_to_le32(SecurityBlobLength);
2615 SecurityBlobLength += len;
2616 SecurityBlob->DomainName.Length =
2620 SecurityBlob->UserName.Buffer = 0;
2621 SecurityBlob->UserName.Length = 0;
2622 SecurityBlob->UserName.MaximumLength = 0;
2625 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2628 SecurityBlob->UserName.MaximumLength =
2630 SecurityBlob->UserName.Buffer =
2631 cpu_to_le32(SecurityBlobLength);
2633 SecurityBlobLength += len;
2634 SecurityBlob->UserName.Length =
2638 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2639 SecurityBlob->WorkstationName.Length *= 2;
2640 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2641 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2642 bcc_ptr += SecurityBlob->WorkstationName.Length;
2643 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2644 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2646 if ((long) bcc_ptr % 2) {
2651 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2653 bcc_ptr += 2 * bytes_returned;
2655 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2657 bcc_ptr += 2 * bytes_returned;
2658 bcc_ptr += 2; /* null term version string */
2660 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2662 bcc_ptr += 2 * bytes_returned;
2665 bcc_ptr += 2; /* null terminate network opsys string */
2668 bcc_ptr += 2; /* null domain */
2669 } else { /* ASCII */
2670 if (domain == NULL) {
2671 SecurityBlob->DomainName.Buffer = 0;
2672 SecurityBlob->DomainName.Length = 0;
2673 SecurityBlob->DomainName.MaximumLength = 0;
2676 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2677 strncpy(bcc_ptr, domain, 63);
2678 len = strnlen(domain, 64);
2679 SecurityBlob->DomainName.MaximumLength =
2681 SecurityBlob->DomainName.Buffer =
2682 cpu_to_le32(SecurityBlobLength);
2684 SecurityBlobLength += len;
2685 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2688 SecurityBlob->UserName.Buffer = 0;
2689 SecurityBlob->UserName.Length = 0;
2690 SecurityBlob->UserName.MaximumLength = 0;
2693 strncpy(bcc_ptr, user, 63);
2694 len = strnlen(user, 64);
2695 SecurityBlob->UserName.MaximumLength =
2697 SecurityBlob->UserName.Buffer =
2698 cpu_to_le32(SecurityBlobLength);
2700 SecurityBlobLength += len;
2701 SecurityBlob->UserName.Length = cpu_to_le16(len);
2703 /* BB fill in our workstation name if known BB */
2705 strcpy(bcc_ptr, "Linux version ");
2706 bcc_ptr += strlen("Linux version ");
2707 strcpy(bcc_ptr, system_utsname.release);
2708 bcc_ptr += strlen(system_utsname.release) + 1;
2709 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2710 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2711 bcc_ptr++; /* null domain */
2714 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2715 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2716 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2717 smb_buffer->smb_buf_length += count;
2718 pSMB->req.ByteCount = cpu_to_le16(count);
2720 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2721 &bytes_returned, 1);
2723 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2724 } else if ((smb_buffer_response->WordCount == 3)
2725 || (smb_buffer_response->WordCount == 4)) {
2726 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2728 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2729 if (action & GUEST_LOGIN)
2730 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2731 /* if(SecurityBlob2->MessageType != NtLm??){
2732 cFYI("Unexpected message type on auth response is %d "));
2736 ("Does UID on challenge %d match auth response UID %d ",
2737 ses->Suid, smb_buffer_response->Uid));
2738 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2739 bcc_ptr = pByteArea(smb_buffer_response);
2740 /* response can have either 3 or 4 word count - Samba sends 3 */
2741 if ((pSMBr->resp.hdr.WordCount == 3)
2742 || ((pSMBr->resp.hdr.WordCount == 4)
2744 pSMBr->resp.ByteCount))) {
2745 if (pSMBr->resp.hdr.WordCount == 4) {
2749 ("Security Blob Length %d ",
2754 ("NTLMSSP response to Authenticate "));
2756 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2757 if ((long) (bcc_ptr) % 2) {
2759 (BCC(smb_buffer_response)
2761 bcc_ptr++; /* Unicode strings must be word aligned */
2763 remaining_words = BCC(smb_buffer_response) / 2;
2766 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2767 /* We look for obvious messed up bcc or strings in response so we do not go off
2768 the end since (at least) WIN2K and Windows XP have a major bug in not null
2769 terminating last Unicode string in response */
2771 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2772 cifs_strfromUCS_le(ses->serverOS,
2776 bcc_ptr += 2 * (len + 1);
2777 remaining_words -= len + 1;
2778 ses->serverOS[2 * len] = 0;
2779 ses->serverOS[1 + (2 * len)] = 0;
2780 if (remaining_words > 0) {
2781 len = UniStrnlen((wchar_t *)
2786 kcalloc(1, 2 * (len + 1),
2788 cifs_strfromUCS_le(ses->
2794 bcc_ptr += 2 * (len + 1);
2795 ses->serverNOS[2 * len] = 0;
2796 ses->serverNOS[1+(2*len)] = 0;
2797 remaining_words -= len + 1;
2798 if (remaining_words > 0) {
2799 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2800 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2825 } /* else no more room so create dummy domain string */
2827 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
2828 } else { /* no room so create dummy domain and NOS string */
2829 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2830 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2832 } else { /* ASCII */
2833 len = strnlen(bcc_ptr, 1024);
2834 if (((long) bcc_ptr + len) -
2835 (long) pByteArea(smb_buffer_response)
2836 <= BCC(smb_buffer_response)) {
2837 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2838 strncpy(ses->serverOS,bcc_ptr, len);
2841 bcc_ptr[0] = 0; /* null terminate the string */
2844 len = strnlen(bcc_ptr, 1024);
2845 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
2846 strncpy(ses->serverNOS, bcc_ptr, len);
2851 len = strnlen(bcc_ptr, 1024);
2852 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
2853 strncpy(ses->serverDomain, bcc_ptr, len);
2859 ("Variable field of length %d extends beyond end of smb ",
2864 (" Security Blob Length extends beyond end of SMB"));
2867 cERROR(1, ("No session structure passed in."));
2871 (" Invalid Word count %d: ",
2872 smb_buffer_response->WordCount));
2877 cifs_buf_release(smb_buffer);
2883 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2884 const char *tree, struct cifsTconInfo *tcon,
2885 const struct nls_table *nls_codepage)
2887 struct smb_hdr *smb_buffer;
2888 struct smb_hdr *smb_buffer_response;
2891 unsigned char *bcc_ptr;
2899 smb_buffer = cifs_buf_get();
2900 if (smb_buffer == NULL) {
2903 smb_buffer_response = smb_buffer;
2905 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2906 NULL /*no tid */ , 4 /*wct */ );
2907 smb_buffer->Uid = ses->Suid;
2908 pSMB = (TCONX_REQ *) smb_buffer;
2909 pSMBr = (TCONX_RSP *) smb_buffer_response;
2911 pSMB->AndXCommand = 0xFF;
2912 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2913 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2914 bcc_ptr = &pSMB->Password[0];
2915 bcc_ptr++; /* skip password */
2917 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2918 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2920 if (ses->capabilities & CAP_STATUS32) {
2921 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2923 if (ses->capabilities & CAP_DFS) {
2924 smb_buffer->Flags2 |= SMBFLG2_DFS;
2926 if (ses->capabilities & CAP_UNICODE) {
2927 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2929 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2930 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2931 bcc_ptr += 2; /* skip trailing null */
2932 } else { /* ASCII */
2934 strcpy(bcc_ptr, tree);
2935 bcc_ptr += strlen(tree) + 1;
2937 strcpy(bcc_ptr, "?????");
2938 bcc_ptr += strlen("?????");
2940 count = bcc_ptr - &pSMB->Password[0];
2941 pSMB->hdr.smb_buf_length += count;
2942 pSMB->ByteCount = cpu_to_le16(count);
2944 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2946 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2947 /* above now done in SendReceive */
2948 if ((rc == 0) && (tcon != NULL)) {
2949 tcon->tidStatus = CifsGood;
2950 tcon->tid = smb_buffer_response->Tid;
2951 bcc_ptr = pByteArea(smb_buffer_response);
2952 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2953 /* skip service field (NB: this field is always ASCII) */
2954 bcc_ptr += length + 1;
2955 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2956 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2957 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2958 if ((bcc_ptr + (2 * length)) -
2959 pByteArea(smb_buffer_response) <=
2960 BCC(smb_buffer_response)) {
2961 if(tcon->nativeFileSystem)
2962 kfree(tcon->nativeFileSystem);
2963 tcon->nativeFileSystem =
2964 kcalloc(1, length + 2, GFP_KERNEL);
2965 cifs_strfromUCS_le(tcon->nativeFileSystem,
2966 (wchar_t *) bcc_ptr,
2967 length, nls_codepage);
2968 bcc_ptr += 2 * length;
2969 bcc_ptr[0] = 0; /* null terminate the string */
2973 /* else do not bother copying these informational fields */
2975 length = strnlen(bcc_ptr, 1024);
2976 if ((bcc_ptr + length) -
2977 pByteArea(smb_buffer_response) <=
2978 BCC(smb_buffer_response)) {
2979 if(tcon->nativeFileSystem)
2980 kfree(tcon->nativeFileSystem);
2981 tcon->nativeFileSystem =
2982 kcalloc(1, length + 1, GFP_KERNEL);
2983 strncpy(tcon->nativeFileSystem, bcc_ptr,
2986 /* else do not bother copying these informational fields */
2988 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2989 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2990 } else if ((rc == 0) && tcon == NULL) {
2991 /* all we need to save for IPC$ connection */
2992 ses->ipc_tid = smb_buffer_response->Tid;
2996 cifs_buf_release(smb_buffer);
3001 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3005 struct cifsSesInfo *ses = NULL;
3006 struct task_struct *cifsd_task;
3010 if (cifs_sb->tcon) {
3011 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3012 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3017 tconInfoFree(cifs_sb->tcon);
3018 if ((ses) && (ses->server)) {
3019 /* save off task so we do not refer to ses later */
3020 cifsd_task = ses->server->tsk;
3021 cFYI(1, ("About to do SMBLogoff "));
3022 rc = CIFSSMBLogoff(xid, ses);
3026 } else if (rc == -ESHUTDOWN) {
3027 cFYI(1,("Waking up socket by sending it signal"));
3029 send_sig(SIGKILL,cifsd_task,1);
3031 } /* else - we have an smb session
3032 left on this socket do not kill cifsd */
3034 cFYI(1, ("No session or bad tcon"));
3037 cifs_sb->tcon = NULL;
3039 set_current_state(TASK_INTERRUPTIBLE);
3040 schedule_timeout(HZ / 2);
3046 return rc; /* BB check if we should always return zero here */
3049 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3050 struct nls_table * nls_info)
3053 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3054 int ntlmv2_flag = FALSE;
3057 /* what if server changes its buffer size after dropping the session? */
3058 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3059 rc = CIFSSMBNegotiate(xid, pSesInfo);
3060 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3061 rc = CIFSSMBNegotiate(xid, pSesInfo);
3066 spin_lock(&GlobalMid_Lock);
3067 if(pSesInfo->server->tcpStatus != CifsExiting)
3068 pSesInfo->server->tcpStatus = CifsGood;
3071 spin_unlock(&GlobalMid_Lock);
3077 pSesInfo->capabilities = pSesInfo->server->capabilities;
3078 if(linuxExtEnabled == 0)
3079 pSesInfo->capabilities &= (~CAP_UNIX);
3080 /* pSesInfo->sequence_number = 0;*/
3081 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3082 pSesInfo->server->secMode,
3083 pSesInfo->server->capabilities,
3084 pSesInfo->server->timeZone));
3085 if (extended_security
3086 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3087 && (pSesInfo->server->secType == NTLMSSP)) {
3088 cFYI(1, ("New style sesssetup "));
3089 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3090 NULL /* security blob */,
3091 0 /* blob length */,
3093 } else if (extended_security
3094 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3095 && (pSesInfo->server->secType == RawNTLMSSP)) {
3096 cFYI(1, ("NTLMSSP sesssetup "));
3097 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3104 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3105 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3110 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3112 CalcNTLMv2_response(pSesInfo,v2_response);
3114 cifs_calculate_ntlmv2_mac_key(
3115 pSesInfo->server->mac_signing_key,
3116 response, ntlm_session_key, */
3118 /* BB Put dummy sig in SessSetup PDU? */
3125 SMBNTencrypt(pSesInfo->password,
3126 pSesInfo->server->cryptKey,
3130 cifs_calculate_mac_key(
3131 pSesInfo->server->mac_signing_key,
3133 pSesInfo->password);
3135 /* for better security the weaker lanman hash not sent
3136 in AuthSessSetup so we no longer calculate it */
3138 rc = CIFSNTLMSSPAuthSessSetup(xid,
3144 } else { /* old style NTLM 0.12 session setup */
3145 SMBNTencrypt(pSesInfo->password,
3146 pSesInfo->server->cryptKey,
3150 cifs_calculate_mac_key(
3151 pSesInfo->server->mac_signing_key,
3152 ntlm_session_key, pSesInfo->password);
3154 rc = CIFSSessSetup(xid, pSesInfo,
3155 ntlm_session_key, nls_info);
3158 cERROR(1,("Send error in SessSetup = %d",rc));
3160 cFYI(1,("CIFS Session Established successfully"));
3161 pSesInfo->status = CifsGood;