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 retry so
161 we do not immediately mark the session bad again
162 (ie after we reconnect below) as they timeout too */
163 mid_entry->midState = MID_RETRY_NEEDED;
167 spin_unlock(&GlobalMid_Lock);
170 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
172 if(server->protocolType == IPV6) {
173 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
175 rc = ipv4_connect(&server->addr.sockAddr,
177 server->workstation_RFC1001_name);
180 set_current_state(TASK_INTERRUPTIBLE);
181 schedule_timeout(3 * HZ);
183 atomic_inc(&tcpSesReconnectCount);
184 spin_lock(&GlobalMid_Lock);
185 if(server->tcpStatus != CifsExiting)
186 server->tcpStatus = CifsGood;
187 server->sequence_number = 0;
188 spin_unlock(&GlobalMid_Lock);
189 /* atomic_set(&server->inFlight,0);*/
190 wake_up(&server->response_q);
197 cifs_demultiplex_thread(struct TCP_Server_Info *server)
200 unsigned int pdu_length, total_read;
201 struct smb_hdr *smb_buffer = NULL;
202 struct smb_hdr *bigbuf = NULL;
203 struct smb_hdr *smallbuf = NULL;
204 struct msghdr smb_msg;
206 struct socket *csocket = server->ssocket;
207 struct list_head *tmp;
208 struct cifsSesInfo *ses;
209 struct task_struct *task_to_wake = NULL;
210 struct mid_q_entry *mid_entry;
212 int isLargeBuf = FALSE;
215 allow_signal(SIGKILL);
216 current->flags |= PF_MEMALLOC;
217 server->tsk = current; /* save process info to wake at shutdown */
218 cFYI(1, ("Demultiplex PID: %d", current->pid));
219 write_lock(&GlobalSMBSeslock);
220 atomic_inc(&tcpSesAllocCount);
221 length = tcpSesAllocCount.counter;
222 write_unlock(&GlobalSMBSeslock);
224 mempool_resize(cifs_req_poolp,
225 length + cifs_min_rcv,
229 while (server->tcpStatus != CifsExiting) {
230 if (bigbuf == NULL) {
231 bigbuf = cifs_buf_get();
233 cERROR(1,("No memory for large SMB response"));
235 /* retry will check if exiting */
238 } else if(isLargeBuf) {
239 /* we are reusing a dirtry large buf, clear its start */
240 memset(bigbuf, 0, sizeof (struct smb_hdr));
243 if (smallbuf == NULL) {
244 smallbuf = cifs_small_buf_get();
245 if(smallbuf == NULL) {
246 cERROR(1,("No memory for SMB response"));
248 /* retry will check if exiting */
251 /* beginning of smb buffer is cleared in our buf_get */
252 } else /* if existing small buf clear beginning */
253 memset(smallbuf, 0, sizeof (struct smb_hdr));
256 smb_buffer = smallbuf;
257 iov.iov_base = smb_buffer;
259 smb_msg.msg_control = NULL;
260 smb_msg.msg_controllen = 0;
262 kernel_recvmsg(csocket, &smb_msg,
263 &iov, 1, 4, 0 /* BB see socket.h flags */);
265 if(server->tcpStatus == CifsExiting) {
267 } else if (server->tcpStatus == CifsNeedReconnect) {
268 cFYI(1,("Reconnecting after server stopped responding"));
269 cifs_reconnect(server);
270 cFYI(1,("call to reconnect done"));
271 csocket = server->ssocket;
273 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
274 msleep(1); /* minimum sleep to prevent looping
275 allowing socket to clear and app threads to set
276 tcpStatus CifsNeedReconnect if server hung */
278 } else if (length <= 0) {
279 if(server->tcpStatus == CifsNew) {
280 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
281 /* some servers kill tcp session rather than returning
282 smb negprot error in which case reconnecting here is
283 not going to help - return error to mount */
286 if(length == -EINTR) {
287 cFYI(1,("cifsd thread killed"));
290 cFYI(1,("Reconnecting after unexpected peek error %d",length));
291 cifs_reconnect(server);
292 csocket = server->ssocket;
293 wake_up(&server->response_q);
295 } else if (length > 3) {
296 pdu_length = ntohl(smb_buffer->smb_buf_length);
297 /* Only read pdu_length after below checks for too short (due
298 to e.g. int overflow) and too long ie beyond end of buf */
299 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
301 temp = (char *) smb_buffer;
302 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
303 cFYI(0,("Received 4 byte keep alive packet"));
304 } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) {
305 cFYI(1,("Good RFC 1002 session rsp"));
306 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
307 /* we get this from Windows 98 instead of error on SMB negprot response */
308 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
309 if(server->tcpStatus == CifsNew) {
310 /* if nack on negprot (rather than
311 ret of smb negprot error) reconnecting
312 not going to help, ret error to mount */
315 /* give server a second to
316 clean up before reconnect attempt */
318 /* always try 445 first on reconnect
319 since we get NACK on some if we ever
320 connected to port 139 (the NACK is
321 since we do not begin with RFC1001
322 session initialize frame) */
323 server->addr.sockAddr.sin_port = htons(CIFS_PORT);
324 cifs_reconnect(server);
325 csocket = server->ssocket;
326 wake_up(&server->response_q);
329 } else if (temp[0] != (char) 0) {
330 cERROR(1,("Unknown RFC 1002 frame"));
331 cifs_dump_mem(" Received Data: ", temp, length);
332 cifs_reconnect(server);
333 csocket = server->ssocket;
336 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)
337 || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
339 ("Invalid size SMB length %d and pdu_length %d",
340 length, pdu_length+4));
341 cifs_reconnect(server);
342 csocket = server->ssocket;
343 wake_up(&server->response_q);
345 } else { /* length ok */
346 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
348 memcpy(bigbuf, smallbuf, 4);
352 iov.iov_base = 4 + (char *)smb_buffer;
353 iov.iov_len = pdu_length;
355 total_read < pdu_length;
356 total_read += length) {
357 length = kernel_recvmsg(csocket, &smb_msg,
359 pdu_length - total_read, 0);
362 ("Zero length receive when expecting %d ",
363 pdu_length - total_read));
364 cifs_reconnect(server);
365 csocket = server->ssocket;
366 wake_up(&server->response_q);
370 length += 4; /* account for rfc1002 hdr */
373 dump_smb(smb_buffer, length);
375 (smb_buffer, smb_buffer->Mid, total_read+4)) {
376 cERROR(1, ("Bad SMB Received "));
381 spin_lock(&GlobalMid_Lock);
382 list_for_each(tmp, &server->pending_mid_q) {
383 mid_entry = list_entry(tmp, struct
387 if ((mid_entry->mid == smb_buffer->Mid)
388 && (mid_entry->midState ==
389 MID_REQUEST_SUBMITTED)
390 && (mid_entry->command ==
391 smb_buffer->Command)) {
392 cFYI(1,("Found Mid 0x%x wake up"
394 task_to_wake = mid_entry->tsk;
395 mid_entry->resp_buf =
397 mid_entry->midState =
398 MID_RESPONSE_RECEIVED;
400 mid_entry->largeBuf = 1;
402 mid_entry->largeBuf = 0;
405 spin_unlock(&GlobalMid_Lock);
411 smb_buffer = NULL; /* will be freed by users thread after he is done */
412 wake_up_process(task_to_wake);
413 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
414 cERROR(1, ("No task to wake, unknown frame rcvd!"));
415 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
420 ("Frame less than four bytes received %d bytes long.",
422 cifs_reconnect(server);
423 csocket = server->ssocket;
424 wake_up(&server->response_q);
428 spin_lock(&GlobalMid_Lock);
429 server->tcpStatus = CifsExiting;
431 atomic_set(&server->inFlight, 0);
432 spin_unlock(&GlobalMid_Lock);
433 /* Although there should not be any requests blocked on
434 this queue it can not hurt to be paranoid and try to wake up requests
435 that may haven been blocked when more than 50 at time were on the wire
436 to the same server - they now will see the session is in exit state
437 and get out of SendReceive. */
438 wake_up_all(&server->request_q);
439 /* give those requests time to exit */
442 if(server->ssocket) {
443 sock_release(csocket);
444 server->ssocket = NULL;
446 /* buffer usuallly freed in free_mid - need to free it here on exit */
448 cifs_buf_release(bigbuf);
449 if (smallbuf != NULL)
450 cifs_small_buf_release(smallbuf);
452 read_lock(&GlobalSMBSeslock);
453 if (list_empty(&server->pending_mid_q)) {
454 /* loop through server session structures attached to this and mark them dead */
455 list_for_each(tmp, &GlobalSMBSessionList) {
457 list_entry(tmp, struct cifsSesInfo,
459 if (ses->server == server) {
460 ses->status = CifsExiting;
464 read_unlock(&GlobalSMBSeslock);
466 spin_lock(&GlobalMid_Lock);
467 list_for_each(tmp, &server->pending_mid_q) {
468 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
469 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
471 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
472 task_to_wake = mid_entry->tsk;
474 wake_up_process(task_to_wake);
478 spin_unlock(&GlobalMid_Lock);
479 read_unlock(&GlobalSMBSeslock);
480 /* 1/8th of sec is more than enough time for them to exit */
484 if (list_empty(&server->pending_mid_q)) {
485 /* mpx threads have not exited yet give them
486 at least the smb send timeout time for long ops */
487 cFYI(1, ("Wait for exit from demultiplex thread"));
489 /* if threads still have not exited they are probably never
490 coming home not much else we can do but free the memory */
494 write_lock(&GlobalSMBSeslock);
495 atomic_dec(&tcpSesAllocCount);
496 length = tcpSesAllocCount.counter;
497 write_unlock(&GlobalSMBSeslock);
499 mempool_resize(cifs_req_poolp,
500 length + cifs_min_rcv,
509 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
513 unsigned int temp_len, i, j;
519 memset(vol->source_rfc1001_name,0x20,15);
520 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
521 /* does not have to be a perfect mapping since the field is
522 informational, only used for servers that do not support
523 port 445 and it can be overridden at mount time */
524 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
526 vol->source_rfc1001_name[15] = 0;
528 vol->linux_uid = current->uid; /* current->euid instead? */
529 vol->linux_gid = current->gid;
530 vol->dir_mode = S_IRWXUGO;
531 /* 2767 perms indicate mandatory locking support */
532 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
534 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
540 if(strncmp(options,"sep=",4) == 0) {
541 if(options[4] != 0) {
542 separator[0] = options[4];
545 cFYI(1,("Null separator not allowed"));
549 while ((data = strsep(&options, separator)) != NULL) {
552 if ((value = strchr(data, '=')) != NULL)
555 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
557 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
559 } else if (strnicmp(data, "user", 4) == 0) {
560 if (!value || !*value) {
562 "CIFS: invalid or missing username\n");
563 return 1; /* needs_arg; */
565 if (strnlen(value, 200) < 200) {
566 vol->username = value;
568 printk(KERN_WARNING "CIFS: username too long\n");
571 } else if (strnicmp(data, "pass", 4) == 0) {
573 vol->password = NULL;
575 } else if(value[0] == 0) {
576 /* check if string begins with double comma
577 since that would mean the password really
578 does start with a comma, and would not
579 indicate an empty string */
580 if(value[1] != separator[0]) {
581 vol->password = NULL;
585 temp_len = strlen(value);
586 /* removed password length check, NTLM passwords
587 can be arbitrarily long */
589 /* if comma in password, the string will be
590 prematurely null terminated. Commas in password are
591 specified across the cifs mount interface by a double
592 comma ie ,, and a comma used as in other cases ie ','
593 as a parameter delimiter/separator is single and due
594 to the strsep above is temporarily zeroed. */
596 /* NB: password legally can have multiple commas and
597 the only illegal character in a password is null */
599 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
601 value[temp_len] = separator[0];
602 temp_len+=2; /* move after the second comma */
603 while(value[temp_len] != 0) {
604 if (value[temp_len] == separator[0]) {
605 if (value[temp_len+1] == separator[0]) {
606 temp_len++; /* skip second comma */
608 /* single comma indicating start
615 if(value[temp_len] == 0) {
619 /* point option to start of next parm */
620 options = value + temp_len + 1;
622 /* go from value to value + temp_len condensing
623 double commas to singles. Note that this ends up
624 allocating a few bytes too many, which is ok */
625 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
626 if(vol->password == NULL) {
627 printk("CIFS: no memory for pass\n");
630 for(i=0,j=0;i<temp_len;i++,j++) {
631 vol->password[j] = value[i];
632 if(value[i] == separator[0] && value[i+1] == separator[0]) {
633 /* skip second comma */
637 vol->password[j] = 0;
639 vol->password = kcalloc(1, temp_len + 1, GFP_KERNEL);
640 if(vol->password == NULL) {
641 printk("CIFS: no memory for pass\n");
644 strcpy(vol->password, value);
646 } else if (strnicmp(data, "ip", 2) == 0) {
647 if (!value || !*value) {
649 } else if (strnlen(value, 35) < 35) {
652 printk(KERN_WARNING "CIFS: ip address too long\n");
655 } else if ((strnicmp(data, "unc", 3) == 0)
656 || (strnicmp(data, "target", 6) == 0)
657 || (strnicmp(data, "path", 4) == 0)) {
658 if (!value || !*value) {
660 "CIFS: invalid path to network resource\n");
661 return 1; /* needs_arg; */
663 if ((temp_len = strnlen(value, 300)) < 300) {
664 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
667 strcpy(vol->UNC,value);
668 if (strncmp(vol->UNC, "//", 2) == 0) {
671 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
673 "CIFS: UNC Path does not begin with // or \\\\ \n");
677 printk(KERN_WARNING "CIFS: UNC name too long\n");
680 } else if ((strnicmp(data, "domain", 3) == 0)
681 || (strnicmp(data, "workgroup", 5) == 0)) {
682 if (!value || !*value) {
683 printk(KERN_WARNING "CIFS: invalid domain name\n");
684 return 1; /* needs_arg; */
686 /* BB are there cases in which a comma can be valid in
687 a domain name and need special handling? */
688 if (strnlen(value, 65) < 65) {
689 vol->domainname = value;
690 cFYI(1, ("Domain name set"));
692 printk(KERN_WARNING "CIFS: domain name too long\n");
695 } else if (strnicmp(data, "iocharset", 9) == 0) {
696 if (!value || !*value) {
697 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
698 return 1; /* needs_arg; */
700 if (strnlen(value, 65) < 65) {
701 if(strnicmp(value,"default",7))
702 vol->iocharset = value;
703 /* if iocharset not set load_nls_default used by caller */
704 cFYI(1, ("iocharset set to %s",value));
706 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
709 } else if (strnicmp(data, "uid", 3) == 0) {
710 if (value && *value) {
712 simple_strtoul(value, &value, 0);
714 } else if (strnicmp(data, "gid", 3) == 0) {
715 if (value && *value) {
717 simple_strtoul(value, &value, 0);
719 } else if (strnicmp(data, "file_mode", 4) == 0) {
720 if (value && *value) {
722 simple_strtoul(value, &value, 0);
724 } else if (strnicmp(data, "dir_mode", 4) == 0) {
725 if (value && *value) {
727 simple_strtoul(value, &value, 0);
729 } else if (strnicmp(data, "dirmode", 4) == 0) {
730 if (value && *value) {
732 simple_strtoul(value, &value, 0);
734 } else if (strnicmp(data, "port", 4) == 0) {
735 if (value && *value) {
737 simple_strtoul(value, &value, 0);
739 } else if (strnicmp(data, "rsize", 5) == 0) {
740 if (value && *value) {
742 simple_strtoul(value, &value, 0);
744 } else if (strnicmp(data, "wsize", 5) == 0) {
745 if (value && *value) {
747 simple_strtoul(value, &value, 0);
749 } else if (strnicmp(data, "sockopt", 5) == 0) {
750 if (value && *value) {
752 simple_strtoul(value, &value, 0);
754 } else if (strnicmp(data, "netbiosname", 4) == 0) {
755 if (!value || !*value || (*value == ' ')) {
756 cFYI(1,("invalid (empty) netbiosname specified"));
758 memset(vol->source_rfc1001_name,0x20,15);
760 /* BB are there cases in which a comma can be
761 valid in this workstation netbios name (and need
762 special handling)? */
764 /* We do not uppercase netbiosname for user */
768 vol->source_rfc1001_name[i] = value[i];
770 /* The string has 16th byte zero still from
771 set at top of the function */
772 if((i==15) && (value[i] != 0))
773 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
775 } else if (strnicmp(data, "credentials", 4) == 0) {
777 } else if (strnicmp(data, "version", 3) == 0) {
779 } else if (strnicmp(data, "guest",5) == 0) {
781 } else if (strnicmp(data, "rw", 2) == 0) {
783 } else if ((strnicmp(data, "suid", 4) == 0) ||
784 (strnicmp(data, "nosuid", 6) == 0) ||
785 (strnicmp(data, "exec", 4) == 0) ||
786 (strnicmp(data, "noexec", 6) == 0) ||
787 (strnicmp(data, "nodev", 5) == 0) ||
788 (strnicmp(data, "noauto", 6) == 0) ||
789 (strnicmp(data, "dev", 3) == 0)) {
790 /* The mount tool or mount.cifs helper (if present)
791 uses these opts to set flags, and the flags are read
792 by the kernel vfs layer before we get here (ie
793 before read super) so there is no point trying to
794 parse these options again and set anything and it
795 is ok to just ignore them */
797 } else if (strnicmp(data, "ro", 2) == 0) {
799 } else if (strnicmp(data, "hard", 4) == 0) {
801 } else if (strnicmp(data, "soft", 4) == 0) {
803 } else if (strnicmp(data, "perm", 4) == 0) {
805 } else if (strnicmp(data, "noperm", 6) == 0) {
807 } else if (strnicmp(data, "mapchars", 8) == 0) {
809 } else if (strnicmp(data, "nomapchars", 10) == 0) {
811 } else if (strnicmp(data, "setuids", 7) == 0) {
813 } else if (strnicmp(data, "nosetuids", 9) == 0) {
815 } else if (strnicmp(data, "nohard", 6) == 0) {
817 } else if (strnicmp(data, "nosoft", 6) == 0) {
819 } else if (strnicmp(data, "nointr", 6) == 0) {
821 } else if (strnicmp(data, "intr", 4) == 0) {
823 } else if (strnicmp(data, "serverino",7) == 0) {
825 } else if (strnicmp(data, "noserverino",9) == 0) {
827 } else if (strnicmp(data, "acl",3) == 0) {
829 } else if (strnicmp(data, "noacl",5) == 0) {
831 } else if (strnicmp(data, "direct",6) == 0) {
833 } else if (strnicmp(data, "forcedirectio",13) == 0) {
835 } else if (strnicmp(data, "in6_addr",8) == 0) {
836 if (!value || !*value) {
837 vol->in6_addr = NULL;
838 } else if (strnlen(value, 49) == 48) {
839 vol->in6_addr = value;
841 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
844 } else if (strnicmp(data, "noac", 4) == 0) {
845 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
847 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
849 if (vol->UNC == NULL) {
850 if(devname == NULL) {
851 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
854 if ((temp_len = strnlen(devname, 300)) < 300) {
855 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
858 strcpy(vol->UNC,devname);
859 if (strncmp(vol->UNC, "//", 2) == 0) {
862 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
863 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
867 printk(KERN_WARNING "CIFS: UNC name too long\n");
871 if(vol->UNCip == NULL)
872 vol->UNCip = &vol->UNC[2];
877 static struct cifsSesInfo *
878 cifs_find_tcp_session(struct in_addr * target_ip_addr,
879 struct in6_addr *target_ip6_addr,
880 char *userName, struct TCP_Server_Info **psrvTcp)
882 struct list_head *tmp;
883 struct cifsSesInfo *ses;
885 read_lock(&GlobalSMBSeslock);
887 list_for_each(tmp, &GlobalSMBSessionList) {
888 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
890 if((target_ip_addr &&
891 (ses->server->addr.sockAddr.sin_addr.s_addr
892 == target_ip_addr->s_addr)) || (target_ip6_addr
893 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
894 target_ip6_addr,sizeof(*target_ip6_addr)))){
895 /* BB lock server and tcp session and increment use count here?? */
896 *psrvTcp = ses->server; /* found a match on the TCP session */
897 /* BB check if reconnection needed */
899 (ses->userName, userName,
900 MAX_USERNAME_SIZE) == 0){
901 read_unlock(&GlobalSMBSeslock);
902 return ses; /* found exact match on both tcp and SMB sessions */
906 /* else tcp and smb sessions need reconnection */
908 read_unlock(&GlobalSMBSeslock);
912 static struct cifsTconInfo *
913 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
915 struct list_head *tmp;
916 struct cifsTconInfo *tcon;
918 read_lock(&GlobalSMBSeslock);
919 list_for_each(tmp, &GlobalTreeConnectionList) {
920 cFYI(1, ("Next tcon - "));
921 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
923 if (tcon->ses->server) {
925 (" old ip addr: %x == new ip %x ?",
926 tcon->ses->server->addr.sockAddr.sin_addr.
927 s_addr, new_target_ip_addr));
928 if (tcon->ses->server->addr.sockAddr.sin_addr.
929 s_addr == new_target_ip_addr) {
930 /* BB lock tcon and server and tcp session and increment use count here? */
931 /* found a match on the TCP session */
932 /* BB check if reconnection needed */
933 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
934 tcon->treeName, uncName));
936 (tcon->treeName, uncName,
937 MAX_TREE_SIZE) == 0) {
939 ("Matched UNC, old user: %s == new: %s ?",
940 tcon->treeName, uncName));
942 (tcon->ses->userName,
944 MAX_USERNAME_SIZE) == 0) {
945 read_unlock(&GlobalSMBSeslock);
946 return tcon;/* also matched user (smb session)*/
953 read_unlock(&GlobalSMBSeslock);
958 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
959 const char *old_path, const struct nls_table *nls_codepage,
962 unsigned char *referrals = NULL;
963 unsigned int num_referrals;
966 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
967 &num_referrals, &referrals, remap);
969 /* BB Add in code to: if valid refrl, if not ip address contact
970 the helper that resolves tcp names, mount to it, try to
971 tcon to it unmount it if fail */
980 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
981 const char *old_path, const struct nls_table *nls_codepage,
982 unsigned int *pnum_referrals,
983 unsigned char ** preferrals, int remap)
990 if (pSesInfo->ipc_tid == 0) {
991 temp_unc = kmalloc(2 /* for slashes */ +
992 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
993 + 1 + 4 /* slash IPC$ */ + 2,
995 if (temp_unc == NULL)
999 strcpy(temp_unc + 2, pSesInfo->serverName);
1000 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1001 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1003 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1007 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1008 pnum_referrals, nls_codepage, remap);
1013 /* See RFC1001 section 14 on representation of Netbios names */
1014 static void rfc1002mangle(char * target,char * source, unsigned int length)
1018 for(i=0,j=0;i<(length);i++) {
1019 /* mask a nibble at a time and encode */
1020 target[j] = 'A' + (0x0F & (source[i] >> 4));
1021 target[j+1] = 'A' + (0x0F & source[i]);
1029 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1030 char * netbios_name)
1034 __be16 orig_port = 0;
1036 if(*csocket == NULL) {
1037 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1039 cERROR(1, ("Error %d creating socket",rc));
1043 /* BB other socket options to set KEEPALIVE, NODELAY? */
1044 cFYI(1,("Socket created"));
1045 (*csocket)->sk->sk_allocation = GFP_NOFS;
1049 psin_server->sin_family = AF_INET;
1050 if(psin_server->sin_port) { /* user overrode default port */
1051 rc = (*csocket)->ops->connect(*csocket,
1052 (struct sockaddr *) psin_server,
1053 sizeof (struct sockaddr_in),0);
1059 /* save original port so we can retry user specified port
1060 later if fall back ports fail this time */
1061 orig_port = psin_server->sin_port;
1063 /* do not retry on the same port we just failed on */
1064 if(psin_server->sin_port != htons(CIFS_PORT)) {
1065 psin_server->sin_port = htons(CIFS_PORT);
1067 rc = (*csocket)->ops->connect(*csocket,
1068 (struct sockaddr *) psin_server,
1069 sizeof (struct sockaddr_in),0);
1075 psin_server->sin_port = htons(RFC1001_PORT);
1076 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1077 psin_server, sizeof (struct sockaddr_in),0);
1082 /* give up here - unless we want to retry on different
1083 protocol families some day */
1086 psin_server->sin_port = orig_port;
1087 cFYI(1,("Error %d connecting to server via ipv4",rc));
1088 sock_release(*csocket);
1092 /* Eventually check for other socket options to change from
1093 the default. sock_setsockopt not used because it expects
1094 user space buffer */
1095 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1097 /* send RFC1001 sessinit */
1099 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1100 /* some servers require RFC1001 sessinit before sending
1101 negprot - BB check reconnection in case where second
1102 sessinit is sent but no second negprot */
1103 struct rfc1002_session_packet * ses_init_buf;
1104 struct smb_hdr * smb_buf;
1105 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1107 ses_init_buf->trailer.session_req.called_len = 32;
1108 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1109 DEFAULT_CIFS_CALLED_NAME,16);
1110 ses_init_buf->trailer.session_req.calling_len = 32;
1111 /* calling name ends in null (byte 16) from old smb
1113 if(netbios_name && (netbios_name[0] !=0)) {
1114 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1117 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1118 "LINUX_CIFS_CLNT",16);
1120 ses_init_buf->trailer.session_req.scope1 = 0;
1121 ses_init_buf->trailer.session_req.scope2 = 0;
1122 smb_buf = (struct smb_hdr *)ses_init_buf;
1123 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1124 smb_buf->smb_buf_length = 0x81000044;
1125 rc = smb_send(*csocket, smb_buf, 0x44,
1126 (struct sockaddr *)psin_server);
1127 kfree(ses_init_buf);
1129 /* else the negprot may still work without this
1130 even though malloc failed */
1138 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1142 __be16 orig_port = 0;
1144 if(*csocket == NULL) {
1145 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1147 cERROR(1, ("Error %d creating ipv6 socket",rc));
1151 /* BB other socket options to set KEEPALIVE, NODELAY? */
1152 cFYI(1,("ipv6 Socket created"));
1153 (*csocket)->sk->sk_allocation = GFP_NOFS;
1157 psin_server->sin6_family = AF_INET6;
1159 if(psin_server->sin6_port) { /* user overrode default port */
1160 rc = (*csocket)->ops->connect(*csocket,
1161 (struct sockaddr *) psin_server,
1162 sizeof (struct sockaddr_in6),0);
1168 /* save original port so we can retry user specified port
1169 later if fall back ports fail this time */
1171 orig_port = psin_server->sin6_port;
1172 /* do not retry on the same port we just failed on */
1173 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1174 psin_server->sin6_port = htons(CIFS_PORT);
1176 rc = (*csocket)->ops->connect(*csocket,
1177 (struct sockaddr *) psin_server,
1178 sizeof (struct sockaddr_in6),0);
1184 psin_server->sin6_port = htons(RFC1001_PORT);
1185 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1186 psin_server, sizeof (struct sockaddr_in6),0);
1191 /* give up here - unless we want to retry on different
1192 protocol families some day */
1195 psin_server->sin6_port = orig_port;
1196 cFYI(1,("Error %d connecting to server via ipv6",rc));
1197 sock_release(*csocket);
1201 /* Eventually check for other socket options to change from
1202 the default. sock_setsockopt not used because it expects
1203 user space buffer */
1204 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1210 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1211 char *mount_data, const char *devname)
1215 int address_type = AF_INET;
1216 struct socket *csocket = NULL;
1217 struct sockaddr_in sin_server;
1218 struct sockaddr_in6 sin_server6;
1219 struct smb_vol volume_info;
1220 struct cifsSesInfo *pSesInfo = NULL;
1221 struct cifsSesInfo *existingCifsSes = NULL;
1222 struct cifsTconInfo *tcon = NULL;
1223 struct TCP_Server_Info *srvTcp = NULL;
1227 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1229 memset(&volume_info,0,sizeof(struct smb_vol));
1230 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1232 kfree(volume_info.UNC);
1233 if(volume_info.password)
1234 kfree(volume_info.password);
1239 if (volume_info.username) {
1240 /* BB fixme parse for domain name here */
1241 cFYI(1, ("Username: %s ", volume_info.username));
1244 cifserror("No username specified ");
1245 /* In userspace mount helper we can get user name from alternate
1246 locations such as env variables and files on disk */
1248 kfree(volume_info.UNC);
1249 if(volume_info.password)
1250 kfree(volume_info.password);
1255 if (volume_info.UNCip && volume_info.UNC) {
1256 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1259 /* not ipv4 address, try ipv6 */
1260 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1262 address_type = AF_INET6;
1264 address_type = AF_INET;
1268 /* we failed translating address */
1270 kfree(volume_info.UNC);
1271 if(volume_info.password)
1272 kfree(volume_info.password);
1277 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1280 } else if (volume_info.UNCip){
1281 /* BB using ip addr as server name connect to the DFS root below */
1282 cERROR(1,("Connecting to DFS root not implemented yet"));
1284 kfree(volume_info.UNC);
1285 if(volume_info.password)
1286 kfree(volume_info.password);
1289 } else /* which servers DFS root would we conect to */ {
1291 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1293 kfree(volume_info.UNC);
1294 if(volume_info.password)
1295 kfree(volume_info.password);
1300 /* this is needed for ASCII cp to Unicode converts */
1301 if(volume_info.iocharset == NULL) {
1302 cifs_sb->local_nls = load_nls_default();
1303 /* load_nls_default can not return null */
1305 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1306 if(cifs_sb->local_nls == NULL) {
1307 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1309 kfree(volume_info.UNC);
1310 if(volume_info.password)
1311 kfree(volume_info.password);
1317 if(address_type == AF_INET)
1318 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1319 NULL /* no ipv6 addr */,
1320 volume_info.username, &srvTcp);
1321 else if(address_type == AF_INET6)
1322 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1323 &sin_server6.sin6_addr,
1324 volume_info.username, &srvTcp);
1327 kfree(volume_info.UNC);
1328 if(volume_info.password)
1329 kfree(volume_info.password);
1336 cFYI(1, ("Existing tcp session with server found "));
1337 } else { /* create socket */
1338 if(volume_info.port)
1339 sin_server.sin_port = htons(volume_info.port);
1341 sin_server.sin_port = 0;
1342 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1345 ("Error connecting to IPv4 socket. Aborting operation"));
1347 sock_release(csocket);
1349 kfree(volume_info.UNC);
1350 if(volume_info.password)
1351 kfree(volume_info.password);
1356 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1357 if (srvTcp == NULL) {
1359 sock_release(csocket);
1361 kfree(volume_info.UNC);
1362 if(volume_info.password)
1363 kfree(volume_info.password);
1367 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1368 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1369 atomic_set(&srvTcp->inFlight,0);
1370 /* BB Add code for ipv6 case too */
1371 srvTcp->ssocket = csocket;
1372 srvTcp->protocolType = IPV4;
1373 init_waitqueue_head(&srvTcp->response_q);
1374 init_waitqueue_head(&srvTcp->request_q);
1375 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1376 /* at this point we are the only ones with the pointer
1377 to the struct since the kernel thread not created yet
1378 so no need to spinlock this init of tcpStatus */
1379 srvTcp->tcpStatus = CifsNew;
1380 init_MUTEX(&srvTcp->tcpSem);
1381 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1382 CLONE_FS | CLONE_FILES | CLONE_VM);
1385 sock_release(csocket);
1387 kfree(volume_info.UNC);
1388 if(volume_info.password)
1389 kfree(volume_info.password);
1394 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1395 srvTcp->sequence_number = 0;
1399 if (existingCifsSes) {
1400 pSesInfo = existingCifsSes;
1401 cFYI(1, ("Existing smb sess found "));
1402 if(volume_info.password)
1403 kfree(volume_info.password);
1404 /* volume_info.UNC freed at end of function */
1406 cFYI(1, ("Existing smb sess not found "));
1407 pSesInfo = sesInfoAlloc();
1408 if (pSesInfo == NULL)
1411 pSesInfo->server = srvTcp;
1412 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1413 NIPQUAD(sin_server.sin_addr.s_addr));
1417 /* volume_info.password freed at unmount */
1418 if (volume_info.password)
1419 pSesInfo->password = volume_info.password;
1420 if (volume_info.username)
1421 strncpy(pSesInfo->userName,
1422 volume_info.username,MAX_USERNAME_SIZE);
1423 if (volume_info.domainname)
1424 strncpy(pSesInfo->domainName,
1425 volume_info.domainname,MAX_USERNAME_SIZE);
1426 pSesInfo->linux_uid = volume_info.linux_uid;
1427 down(&pSesInfo->sesSem);
1428 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1429 up(&pSesInfo->sesSem);
1431 atomic_inc(&srvTcp->socketUseCount);
1433 if(volume_info.password)
1434 kfree(volume_info.password);
1437 /* search for existing tcon to this server share */
1439 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1440 cifs_sb->rsize = volume_info.rsize;
1442 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1443 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1444 cifs_sb->wsize = volume_info.wsize;
1446 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1447 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1448 cifs_sb->rsize = PAGE_CACHE_SIZE;
1449 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1451 cifs_sb->mnt_uid = volume_info.linux_uid;
1452 cifs_sb->mnt_gid = volume_info.linux_gid;
1453 cifs_sb->mnt_file_mode = volume_info.file_mode;
1454 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1455 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1457 if(volume_info.noperm)
1458 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1459 if(volume_info.setuids)
1460 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1461 if(volume_info.server_ino)
1462 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1463 if(volume_info.remap)
1464 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1465 if(volume_info.no_xattr)
1466 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1467 if(volume_info.direct_io) {
1468 cERROR(1,("mounting share using direct i/o"));
1469 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1473 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1474 volume_info.username);
1476 cFYI(1, ("Found match on UNC path "));
1477 /* we can have only one retry value for a connection
1478 to a share so for resources mounted more than once
1479 to the same server share the last value passed in
1480 for the retry flag is used */
1481 tcon->retry = volume_info.retry;
1483 tcon = tconInfoAlloc();
1487 /* check for null share name ie connect to dfs root */
1489 /* BB check if this works for exactly length three strings */
1490 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1491 && (strchr(volume_info.UNC + 3, '/') ==
1493 rc = connect_to_dfs_path(xid, pSesInfo,
1494 "", cifs_sb->local_nls,
1495 cifs_sb->mnt_cifs_flags &
1496 CIFS_MOUNT_MAP_SPECIAL_CHR);
1498 kfree(volume_info.UNC);
1502 rc = CIFSTCon(xid, pSesInfo,
1504 tcon, cifs_sb->local_nls);
1505 cFYI(1, ("CIFS Tcon rc = %d", rc));
1508 atomic_inc(&pSesInfo->inUse);
1509 tcon->retry = volume_info.retry;
1515 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1516 sb->s_maxbytes = (u64) 1 << 63;
1518 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1521 sb->s_time_gran = 100;
1523 /* on error free sesinfo and tcon struct if needed */
1525 /* if session setup failed, use count is zero but
1526 we still need to free cifsd thread */
1527 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1528 spin_lock(&GlobalMid_Lock);
1529 srvTcp->tcpStatus = CifsExiting;
1530 spin_unlock(&GlobalMid_Lock);
1532 send_sig(SIGKILL,srvTcp->tsk,1);
1534 /* If find_unc succeeded then rc == 0 so we can not end */
1535 if (tcon) /* up accidently freeing someone elses tcon struct */
1537 if (existingCifsSes == NULL) {
1539 if ((pSesInfo->server) &&
1540 (pSesInfo->status == CifsGood)) {
1542 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1543 /* if the socketUseCount is now zero */
1544 if((temp_rc == -ESHUTDOWN) &&
1545 (pSesInfo->server->tsk))
1546 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1548 cFYI(1, ("No session or bad tcon"));
1549 sesInfoFree(pSesInfo);
1550 /* pSesInfo = NULL; */
1554 atomic_inc(&tcon->useCount);
1555 cifs_sb->tcon = tcon;
1556 tcon->ses = pSesInfo;
1558 /* do not care if following two calls succeed - informational only */
1559 CIFSSMBQFSDeviceInfo(xid, tcon);
1560 CIFSSMBQFSAttributeInfo(xid, tcon);
1561 if (tcon->ses->capabilities & CAP_UNIX) {
1562 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1563 if(!volume_info.no_psx_acl) {
1564 if(CIFS_UNIX_POSIX_ACL_CAP &
1565 le64_to_cpu(tcon->fsUnixInfo.Capability))
1566 cFYI(1,("server negotiated posix acl support"));
1567 sb->s_flags |= MS_POSIXACL;
1573 /* volume_info.password is freed above when existing session found
1574 (in which case it is not needed anymore) but when new sesion is created
1575 the password ptr is put in the new session structure (in which case the
1576 password will be freed at unmount time) */
1578 kfree(volume_info.UNC);
1584 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1585 char session_key[CIFS_SESSION_KEY_SIZE],
1586 const struct nls_table *nls_codepage)
1588 struct smb_hdr *smb_buffer;
1589 struct smb_hdr *smb_buffer_response;
1590 SESSION_SETUP_ANDX *pSMB;
1591 SESSION_SETUP_ANDX *pSMBr;
1596 int remaining_words = 0;
1597 int bytes_returned = 0;
1602 cFYI(1, ("In sesssetup "));
1605 user = ses->userName;
1606 domain = ses->domainName;
1607 smb_buffer = cifs_buf_get();
1608 if (smb_buffer == NULL) {
1611 smb_buffer_response = smb_buffer;
1612 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1614 /* send SMBsessionSetup here */
1615 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1616 NULL /* no tCon exists yet */ , 13 /* wct */ );
1618 pSMB->req_no_secext.AndXCommand = 0xFF;
1619 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1620 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1622 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1623 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1625 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1626 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1627 if (ses->capabilities & CAP_UNICODE) {
1628 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1629 capabilities |= CAP_UNICODE;
1631 if (ses->capabilities & CAP_STATUS32) {
1632 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1633 capabilities |= CAP_STATUS32;
1635 if (ses->capabilities & CAP_DFS) {
1636 smb_buffer->Flags2 |= SMBFLG2_DFS;
1637 capabilities |= CAP_DFS;
1639 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1641 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1642 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1644 pSMB->req_no_secext.CaseSensitivePasswordLength =
1645 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1646 bcc_ptr = pByteArea(smb_buffer);
1647 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1648 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1649 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1650 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1652 if (ses->capabilities & CAP_UNICODE) {
1653 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1658 bytes_returned = 0; /* skill null user */
1661 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1663 /* convert number of 16 bit words to bytes */
1664 bcc_ptr += 2 * bytes_returned;
1665 bcc_ptr += 2; /* trailing null */
1668 cifs_strtoUCS((wchar_t *) bcc_ptr,
1669 "CIFS_LINUX_DOM", 32, nls_codepage);
1672 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1674 bcc_ptr += 2 * bytes_returned;
1677 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1679 bcc_ptr += 2 * bytes_returned;
1681 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1683 bcc_ptr += 2 * bytes_returned;
1686 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1688 bcc_ptr += 2 * bytes_returned;
1692 strncpy(bcc_ptr, user, 200);
1693 bcc_ptr += strnlen(user, 200);
1697 if (domain == NULL) {
1698 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1699 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1701 strncpy(bcc_ptr, domain, 64);
1702 bcc_ptr += strnlen(domain, 64);
1706 strcpy(bcc_ptr, "Linux version ");
1707 bcc_ptr += strlen("Linux version ");
1708 strcpy(bcc_ptr, system_utsname.release);
1709 bcc_ptr += strlen(system_utsname.release) + 1;
1710 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1711 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1713 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1714 smb_buffer->smb_buf_length += count;
1715 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1717 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1718 &bytes_returned, 1);
1720 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1721 } else if ((smb_buffer_response->WordCount == 3)
1722 || (smb_buffer_response->WordCount == 4)) {
1723 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1724 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1725 if (action & GUEST_LOGIN)
1726 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1727 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1728 cFYI(1, ("UID = %d ", ses->Suid));
1729 /* response can have either 3 or 4 word count - Samba sends 3 */
1730 bcc_ptr = pByteArea(smb_buffer_response);
1731 if ((pSMBr->resp.hdr.WordCount == 3)
1732 || ((pSMBr->resp.hdr.WordCount == 4)
1733 && (blob_len < pSMBr->resp.ByteCount))) {
1734 if (pSMBr->resp.hdr.WordCount == 4)
1735 bcc_ptr += blob_len;
1737 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1738 if ((long) (bcc_ptr) % 2) {
1740 (BCC(smb_buffer_response) - 1) /2;
1741 bcc_ptr++; /* Unicode strings must be word aligned */
1744 BCC(smb_buffer_response) / 2;
1747 UniStrnlen((wchar_t *) bcc_ptr,
1748 remaining_words - 1);
1749 /* We look for obvious messed up bcc or strings in response so we do not go off
1750 the end since (at least) WIN2K and Windows XP have a major bug in not null
1751 terminating last Unicode string in response */
1752 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1753 if(ses->serverOS == NULL)
1754 goto sesssetup_nomem;
1755 cifs_strfromUCS_le(ses->serverOS,
1756 (wchar_t *)bcc_ptr, len,nls_codepage);
1757 bcc_ptr += 2 * (len + 1);
1758 remaining_words -= len + 1;
1759 ses->serverOS[2 * len] = 0;
1760 ses->serverOS[1 + (2 * len)] = 0;
1761 if (remaining_words > 0) {
1762 len = UniStrnlen((wchar_t *)bcc_ptr,
1764 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
1765 if(ses->serverNOS == NULL)
1766 goto sesssetup_nomem;
1767 cifs_strfromUCS_le(ses->serverNOS,
1768 (wchar_t *)bcc_ptr,len,nls_codepage);
1769 bcc_ptr += 2 * (len + 1);
1770 ses->serverNOS[2 * len] = 0;
1771 ses->serverNOS[1 + (2 * len)] = 0;
1772 if(strncmp(ses->serverNOS,
1773 "NT LAN Manager 4",16) == 0) {
1774 cFYI(1,("NT4 server"));
1775 ses->flags |= CIFS_SES_NT4;
1777 remaining_words -= len + 1;
1778 if (remaining_words > 0) {
1779 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1780 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1782 kcalloc(1, 2*(len+1),GFP_KERNEL);
1783 if(ses->serverDomain == NULL)
1784 goto sesssetup_nomem;
1785 cifs_strfromUCS_le(ses->serverDomain,
1786 (wchar_t *)bcc_ptr,len,nls_codepage);
1787 bcc_ptr += 2 * (len + 1);
1788 ses->serverDomain[2*len] = 0;
1789 ses->serverDomain[1+(2*len)] = 0;
1790 } /* else no more room so create dummy domain string */
1793 kcalloc(1, 2, GFP_KERNEL);
1794 } else { /* no room so create dummy domain and NOS string */
1795 /* if these kcallocs fail not much we
1796 can do, but better to not fail the
1799 kcalloc(1, 2, GFP_KERNEL);
1801 kcalloc(1, 2, GFP_KERNEL);
1803 } else { /* ASCII */
1804 len = strnlen(bcc_ptr, 1024);
1805 if (((long) bcc_ptr + len) - (long)
1806 pByteArea(smb_buffer_response)
1807 <= BCC(smb_buffer_response)) {
1808 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
1809 if(ses->serverOS == NULL)
1810 goto sesssetup_nomem;
1811 strncpy(ses->serverOS,bcc_ptr, len);
1814 bcc_ptr[0] = 0; /* null terminate the string */
1817 len = strnlen(bcc_ptr, 1024);
1818 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
1819 if(ses->serverNOS == NULL)
1820 goto sesssetup_nomem;
1821 strncpy(ses->serverNOS, bcc_ptr, len);
1826 len = strnlen(bcc_ptr, 1024);
1827 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
1828 if(ses->serverDomain == NULL)
1829 goto sesssetup_nomem;
1830 strncpy(ses->serverDomain, bcc_ptr, len);
1836 ("Variable field of length %d extends beyond end of smb ",
1841 (" Security Blob Length extends beyond end of SMB"));
1845 (" Invalid Word count %d: ",
1846 smb_buffer_response->WordCount));
1849 sesssetup_nomem: /* do not return an error on nomem for the info strings,
1850 since that could make reconnection harder, and
1851 reconnection might be needed to free memory */
1853 cifs_buf_release(smb_buffer);
1859 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1860 char *SecurityBlob,int SecurityBlobLength,
1861 const struct nls_table *nls_codepage)
1863 struct smb_hdr *smb_buffer;
1864 struct smb_hdr *smb_buffer_response;
1865 SESSION_SETUP_ANDX *pSMB;
1866 SESSION_SETUP_ANDX *pSMBr;
1871 int remaining_words = 0;
1872 int bytes_returned = 0;
1877 cFYI(1, ("In spnego sesssetup "));
1880 user = ses->userName;
1881 domain = ses->domainName;
1883 smb_buffer = cifs_buf_get();
1884 if (smb_buffer == NULL) {
1887 smb_buffer_response = smb_buffer;
1888 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1890 /* send SMBsessionSetup here */
1891 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1892 NULL /* no tCon exists yet */ , 12 /* wct */ );
1893 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1894 pSMB->req.AndXCommand = 0xFF;
1895 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1896 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1898 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1899 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1901 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1902 CAP_EXTENDED_SECURITY;
1903 if (ses->capabilities & CAP_UNICODE) {
1904 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1905 capabilities |= CAP_UNICODE;
1907 if (ses->capabilities & CAP_STATUS32) {
1908 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1909 capabilities |= CAP_STATUS32;
1911 if (ses->capabilities & CAP_DFS) {
1912 smb_buffer->Flags2 |= SMBFLG2_DFS;
1913 capabilities |= CAP_DFS;
1915 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1917 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1918 bcc_ptr = pByteArea(smb_buffer);
1919 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1920 bcc_ptr += SecurityBlobLength;
1922 if (ses->capabilities & CAP_UNICODE) {
1923 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1928 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1929 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1930 bcc_ptr += 2; /* trailing null */
1933 cifs_strtoUCS((wchar_t *) bcc_ptr,
1934 "CIFS_LINUX_DOM", 32, nls_codepage);
1937 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1939 bcc_ptr += 2 * bytes_returned;
1942 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1944 bcc_ptr += 2 * bytes_returned;
1946 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
1948 bcc_ptr += 2 * bytes_returned;
1951 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1953 bcc_ptr += 2 * bytes_returned;
1956 strncpy(bcc_ptr, user, 200);
1957 bcc_ptr += strnlen(user, 200);
1960 if (domain == NULL) {
1961 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1962 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1964 strncpy(bcc_ptr, domain, 64);
1965 bcc_ptr += strnlen(domain, 64);
1969 strcpy(bcc_ptr, "Linux version ");
1970 bcc_ptr += strlen("Linux version ");
1971 strcpy(bcc_ptr, system_utsname.release);
1972 bcc_ptr += strlen(system_utsname.release) + 1;
1973 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1974 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1976 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1977 smb_buffer->smb_buf_length += count;
1978 pSMB->req.ByteCount = cpu_to_le16(count);
1980 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1981 &bytes_returned, 1);
1983 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1984 } else if ((smb_buffer_response->WordCount == 3)
1985 || (smb_buffer_response->WordCount == 4)) {
1986 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1988 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1989 if (action & GUEST_LOGIN)
1990 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1992 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1993 cFYI(1, ("UID = %d ", ses->Suid));
1994 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
1996 /* BB Fix below to make endian neutral !! */
1998 if ((pSMBr->resp.hdr.WordCount == 3)
1999 || ((pSMBr->resp.hdr.WordCount == 4)
2001 pSMBr->resp.ByteCount))) {
2002 if (pSMBr->resp.hdr.WordCount == 4) {
2006 ("Security Blob Length %d ",
2010 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2011 if ((long) (bcc_ptr) % 2) {
2013 (BCC(smb_buffer_response)
2015 bcc_ptr++; /* Unicode strings must be word aligned */
2019 (smb_buffer_response) / 2;
2022 UniStrnlen((wchar_t *) bcc_ptr,
2023 remaining_words - 1);
2024 /* We look for obvious messed up bcc or strings in response so we do not go off
2025 the end since (at least) WIN2K and Windows XP have a major bug in not null
2026 terminating last Unicode string in response */
2028 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2029 cifs_strfromUCS_le(ses->serverOS,
2033 bcc_ptr += 2 * (len + 1);
2034 remaining_words -= len + 1;
2035 ses->serverOS[2 * len] = 0;
2036 ses->serverOS[1 + (2 * len)] = 0;
2037 if (remaining_words > 0) {
2038 len = UniStrnlen((wchar_t *)bcc_ptr,
2042 kcalloc(1, 2 * (len + 1),
2044 cifs_strfromUCS_le(ses->serverNOS,
2048 bcc_ptr += 2 * (len + 1);
2049 ses->serverNOS[2 * len] = 0;
2050 ses->serverNOS[1 + (2 * len)] = 0;
2051 remaining_words -= len + 1;
2052 if (remaining_words > 0) {
2053 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2054 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2055 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2056 cifs_strfromUCS_le(ses->serverDomain,
2060 bcc_ptr += 2*(len+1);
2061 ses->serverDomain[2*len] = 0;
2062 ses->serverDomain[1+(2*len)] = 0;
2063 } /* else no more room so create dummy domain string */
2066 kcalloc(1, 2,GFP_KERNEL);
2067 } else { /* no room so create dummy domain and NOS string */
2068 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2069 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2071 } else { /* ASCII */
2073 len = strnlen(bcc_ptr, 1024);
2074 if (((long) bcc_ptr + len) - (long)
2075 pByteArea(smb_buffer_response)
2076 <= BCC(smb_buffer_response)) {
2077 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2078 strncpy(ses->serverOS, bcc_ptr, len);
2081 bcc_ptr[0] = 0; /* null terminate the string */
2084 len = strnlen(bcc_ptr, 1024);
2085 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2086 strncpy(ses->serverNOS, bcc_ptr, len);
2091 len = strnlen(bcc_ptr, 1024);
2092 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2093 strncpy(ses->serverDomain, bcc_ptr, len);
2099 ("Variable field of length %d extends beyond end of smb ",
2104 (" Security Blob Length extends beyond end of SMB"));
2107 cERROR(1, ("No session structure passed in."));
2111 (" Invalid Word count %d: ",
2112 smb_buffer_response->WordCount));
2117 cifs_buf_release(smb_buffer);
2123 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2124 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2125 const struct nls_table *nls_codepage)
2127 struct smb_hdr *smb_buffer;
2128 struct smb_hdr *smb_buffer_response;
2129 SESSION_SETUP_ANDX *pSMB;
2130 SESSION_SETUP_ANDX *pSMBr;
2134 int remaining_words = 0;
2135 int bytes_returned = 0;
2137 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2138 PNEGOTIATE_MESSAGE SecurityBlob;
2139 PCHALLENGE_MESSAGE SecurityBlob2;
2140 __u32 negotiate_flags, capabilities;
2143 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2146 domain = ses->domainName;
2147 *pNTLMv2_flag = FALSE;
2148 smb_buffer = cifs_buf_get();
2149 if (smb_buffer == NULL) {
2152 smb_buffer_response = smb_buffer;
2153 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2154 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2156 /* send SMBsessionSetup here */
2157 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2158 NULL /* no tCon exists yet */ , 12 /* wct */ );
2159 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2160 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2162 pSMB->req.AndXCommand = 0xFF;
2163 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2164 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2166 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2167 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2169 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2170 CAP_EXTENDED_SECURITY;
2171 if (ses->capabilities & CAP_UNICODE) {
2172 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2173 capabilities |= CAP_UNICODE;
2175 if (ses->capabilities & CAP_STATUS32) {
2176 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2177 capabilities |= CAP_STATUS32;
2179 if (ses->capabilities & CAP_DFS) {
2180 smb_buffer->Flags2 |= SMBFLG2_DFS;
2181 capabilities |= CAP_DFS;
2183 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2185 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2186 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2187 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2188 SecurityBlob->MessageType = NtLmNegotiate;
2190 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2191 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2192 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2194 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2196 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2197 /* setup pointers to domain name and workstation name */
2198 bcc_ptr += SecurityBlobLength;
2200 SecurityBlob->WorkstationName.Buffer = 0;
2201 SecurityBlob->WorkstationName.Length = 0;
2202 SecurityBlob->WorkstationName.MaximumLength = 0;
2204 if (domain == NULL) {
2205 SecurityBlob->DomainName.Buffer = 0;
2206 SecurityBlob->DomainName.Length = 0;
2207 SecurityBlob->DomainName.MaximumLength = 0;
2210 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2211 strncpy(bcc_ptr, domain, 63);
2212 len = strnlen(domain, 64);
2213 SecurityBlob->DomainName.MaximumLength =
2215 SecurityBlob->DomainName.Buffer =
2216 cpu_to_le32((long) &SecurityBlob->
2218 (long) &SecurityBlob->Signature);
2220 SecurityBlobLength += len;
2221 SecurityBlob->DomainName.Length =
2224 if (ses->capabilities & CAP_UNICODE) {
2225 if ((long) bcc_ptr % 2) {
2231 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2233 bcc_ptr += 2 * bytes_returned;
2235 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2237 bcc_ptr += 2 * bytes_returned;
2238 bcc_ptr += 2; /* null terminate Linux version */
2240 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2242 bcc_ptr += 2 * bytes_returned;
2245 bcc_ptr += 2; /* null terminate network opsys string */
2248 bcc_ptr += 2; /* null domain */
2249 } else { /* ASCII */
2250 strcpy(bcc_ptr, "Linux version ");
2251 bcc_ptr += strlen("Linux version ");
2252 strcpy(bcc_ptr, system_utsname.release);
2253 bcc_ptr += strlen(system_utsname.release) + 1;
2254 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2255 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2256 bcc_ptr++; /* empty domain field */
2259 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2260 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2261 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2262 smb_buffer->smb_buf_length += count;
2263 pSMB->req.ByteCount = cpu_to_le16(count);
2265 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2266 &bytes_returned, 1);
2268 if (smb_buffer_response->Status.CifsError ==
2269 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2273 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2274 } else if ((smb_buffer_response->WordCount == 3)
2275 || (smb_buffer_response->WordCount == 4)) {
2276 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2277 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2279 if (action & GUEST_LOGIN)
2280 cFYI(1, (" Guest login"));
2281 /* Do we want to set anything in SesInfo struct when guest login? */
2283 bcc_ptr = pByteArea(smb_buffer_response);
2284 /* response can have either 3 or 4 word count - Samba sends 3 */
2286 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2287 if (SecurityBlob2->MessageType != NtLmChallenge) {
2289 ("Unexpected NTLMSSP message type received %d",
2290 SecurityBlob2->MessageType));
2292 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2293 cFYI(1, ("UID = %d ", ses->Suid));
2294 if ((pSMBr->resp.hdr.WordCount == 3)
2295 || ((pSMBr->resp.hdr.WordCount == 4)
2297 pSMBr->resp.ByteCount))) {
2299 if (pSMBr->resp.hdr.WordCount == 4) {
2300 bcc_ptr += blob_len;
2302 ("Security Blob Length %d ",
2306 cFYI(1, ("NTLMSSP Challenge rcvd "));
2308 memcpy(ses->server->cryptKey,
2309 SecurityBlob2->Challenge,
2310 CIFS_CRYPTO_KEY_SIZE);
2311 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2312 *pNTLMv2_flag = TRUE;
2314 if((SecurityBlob2->NegotiateFlags &
2315 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2316 || (sign_CIFS_PDUs > 1))
2317 ses->server->secMode |=
2318 SECMODE_SIGN_REQUIRED;
2319 if ((SecurityBlob2->NegotiateFlags &
2320 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2321 ses->server->secMode |=
2322 SECMODE_SIGN_ENABLED;
2324 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2325 if ((long) (bcc_ptr) % 2) {
2327 (BCC(smb_buffer_response)
2329 bcc_ptr++; /* Unicode strings must be word aligned */
2333 (smb_buffer_response) / 2;
2336 UniStrnlen((wchar_t *) bcc_ptr,
2337 remaining_words - 1);
2338 /* We look for obvious messed up bcc or strings in response so we do not go off
2339 the end since (at least) WIN2K and Windows XP have a major bug in not null
2340 terminating last Unicode string in response */
2342 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2343 cifs_strfromUCS_le(ses->serverOS,
2347 bcc_ptr += 2 * (len + 1);
2348 remaining_words -= len + 1;
2349 ses->serverOS[2 * len] = 0;
2350 ses->serverOS[1 + (2 * len)] = 0;
2351 if (remaining_words > 0) {
2352 len = UniStrnlen((wchar_t *)
2357 kcalloc(1, 2 * (len + 1),
2359 cifs_strfromUCS_le(ses->
2365 bcc_ptr += 2 * (len + 1);
2366 ses->serverNOS[2 * len] = 0;
2369 remaining_words -= len + 1;
2370 if (remaining_words > 0) {
2371 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2372 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2397 } /* else no more room so create dummy domain string */
2402 } else { /* no room so create dummy domain and NOS string */
2404 kcalloc(1, 2, GFP_KERNEL);
2406 kcalloc(1, 2, GFP_KERNEL);
2408 } else { /* ASCII */
2409 len = strnlen(bcc_ptr, 1024);
2410 if (((long) bcc_ptr + len) - (long)
2411 pByteArea(smb_buffer_response)
2412 <= BCC(smb_buffer_response)) {
2416 strncpy(ses->serverOS,
2420 bcc_ptr[0] = 0; /* null terminate string */
2423 len = strnlen(bcc_ptr, 1024);
2427 strncpy(ses->serverNOS, bcc_ptr, len);
2432 len = strnlen(bcc_ptr, 1024);
2436 strncpy(ses->serverDomain, bcc_ptr, len);
2442 ("Variable field of length %d extends beyond end of smb ",
2447 (" Security Blob Length extends beyond end of SMB"));
2450 cERROR(1, ("No session structure passed in."));
2454 (" Invalid Word count %d: ",
2455 smb_buffer_response->WordCount));
2460 cifs_buf_release(smb_buffer);
2465 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2466 char *ntlm_session_key, int ntlmv2_flag,
2467 const struct nls_table *nls_codepage)
2469 struct smb_hdr *smb_buffer;
2470 struct smb_hdr *smb_buffer_response;
2471 SESSION_SETUP_ANDX *pSMB;
2472 SESSION_SETUP_ANDX *pSMBr;
2477 int remaining_words = 0;
2478 int bytes_returned = 0;
2480 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2481 PAUTHENTICATE_MESSAGE SecurityBlob;
2482 __u32 negotiate_flags, capabilities;
2485 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2488 user = ses->userName;
2489 domain = ses->domainName;
2490 smb_buffer = cifs_buf_get();
2491 if (smb_buffer == NULL) {
2494 smb_buffer_response = smb_buffer;
2495 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2496 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2498 /* send SMBsessionSetup here */
2499 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2500 NULL /* no tCon exists yet */ , 12 /* wct */ );
2501 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2502 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2503 pSMB->req.AndXCommand = 0xFF;
2504 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2505 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2507 pSMB->req.hdr.Uid = ses->Suid;
2509 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2510 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2512 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2513 CAP_EXTENDED_SECURITY;
2514 if (ses->capabilities & CAP_UNICODE) {
2515 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2516 capabilities |= CAP_UNICODE;
2518 if (ses->capabilities & CAP_STATUS32) {
2519 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2520 capabilities |= CAP_STATUS32;
2522 if (ses->capabilities & CAP_DFS) {
2523 smb_buffer->Flags2 |= SMBFLG2_DFS;
2524 capabilities |= CAP_DFS;
2526 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2528 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2529 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2530 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2531 SecurityBlob->MessageType = NtLmAuthenticate;
2532 bcc_ptr += SecurityBlobLength;
2534 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2535 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2536 0x80000000 | NTLMSSP_NEGOTIATE_128;
2538 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2540 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2542 /* setup pointers to domain name and workstation name */
2544 SecurityBlob->WorkstationName.Buffer = 0;
2545 SecurityBlob->WorkstationName.Length = 0;
2546 SecurityBlob->WorkstationName.MaximumLength = 0;
2547 SecurityBlob->SessionKey.Length = 0;
2548 SecurityBlob->SessionKey.MaximumLength = 0;
2549 SecurityBlob->SessionKey.Buffer = 0;
2551 SecurityBlob->LmChallengeResponse.Length = 0;
2552 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2553 SecurityBlob->LmChallengeResponse.Buffer = 0;
2555 SecurityBlob->NtChallengeResponse.Length =
2556 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2557 SecurityBlob->NtChallengeResponse.MaximumLength =
2558 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2559 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2560 SecurityBlob->NtChallengeResponse.Buffer =
2561 cpu_to_le32(SecurityBlobLength);
2562 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2563 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2565 if (ses->capabilities & CAP_UNICODE) {
2566 if (domain == NULL) {
2567 SecurityBlob->DomainName.Buffer = 0;
2568 SecurityBlob->DomainName.Length = 0;
2569 SecurityBlob->DomainName.MaximumLength = 0;
2572 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2575 SecurityBlob->DomainName.MaximumLength =
2577 SecurityBlob->DomainName.Buffer =
2578 cpu_to_le32(SecurityBlobLength);
2580 SecurityBlobLength += len;
2581 SecurityBlob->DomainName.Length =
2585 SecurityBlob->UserName.Buffer = 0;
2586 SecurityBlob->UserName.Length = 0;
2587 SecurityBlob->UserName.MaximumLength = 0;
2590 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2593 SecurityBlob->UserName.MaximumLength =
2595 SecurityBlob->UserName.Buffer =
2596 cpu_to_le32(SecurityBlobLength);
2598 SecurityBlobLength += len;
2599 SecurityBlob->UserName.Length =
2603 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2604 SecurityBlob->WorkstationName.Length *= 2;
2605 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2606 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2607 bcc_ptr += SecurityBlob->WorkstationName.Length;
2608 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2609 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2611 if ((long) bcc_ptr % 2) {
2616 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2618 bcc_ptr += 2 * bytes_returned;
2620 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2622 bcc_ptr += 2 * bytes_returned;
2623 bcc_ptr += 2; /* null term version string */
2625 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2627 bcc_ptr += 2 * bytes_returned;
2630 bcc_ptr += 2; /* null terminate network opsys string */
2633 bcc_ptr += 2; /* null domain */
2634 } else { /* ASCII */
2635 if (domain == NULL) {
2636 SecurityBlob->DomainName.Buffer = 0;
2637 SecurityBlob->DomainName.Length = 0;
2638 SecurityBlob->DomainName.MaximumLength = 0;
2641 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2642 strncpy(bcc_ptr, domain, 63);
2643 len = strnlen(domain, 64);
2644 SecurityBlob->DomainName.MaximumLength =
2646 SecurityBlob->DomainName.Buffer =
2647 cpu_to_le32(SecurityBlobLength);
2649 SecurityBlobLength += len;
2650 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2653 SecurityBlob->UserName.Buffer = 0;
2654 SecurityBlob->UserName.Length = 0;
2655 SecurityBlob->UserName.MaximumLength = 0;
2658 strncpy(bcc_ptr, user, 63);
2659 len = strnlen(user, 64);
2660 SecurityBlob->UserName.MaximumLength =
2662 SecurityBlob->UserName.Buffer =
2663 cpu_to_le32(SecurityBlobLength);
2665 SecurityBlobLength += len;
2666 SecurityBlob->UserName.Length = cpu_to_le16(len);
2668 /* BB fill in our workstation name if known BB */
2670 strcpy(bcc_ptr, "Linux version ");
2671 bcc_ptr += strlen("Linux version ");
2672 strcpy(bcc_ptr, system_utsname.release);
2673 bcc_ptr += strlen(system_utsname.release) + 1;
2674 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2675 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2676 bcc_ptr++; /* null domain */
2679 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2680 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2681 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2682 smb_buffer->smb_buf_length += count;
2683 pSMB->req.ByteCount = cpu_to_le16(count);
2685 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2686 &bytes_returned, 1);
2688 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2689 } else if ((smb_buffer_response->WordCount == 3)
2690 || (smb_buffer_response->WordCount == 4)) {
2691 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2693 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2694 if (action & GUEST_LOGIN)
2695 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2696 /* if(SecurityBlob2->MessageType != NtLm??){
2697 cFYI("Unexpected message type on auth response is %d "));
2701 ("Does UID on challenge %d match auth response UID %d ",
2702 ses->Suid, smb_buffer_response->Uid));
2703 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2704 bcc_ptr = pByteArea(smb_buffer_response);
2705 /* response can have either 3 or 4 word count - Samba sends 3 */
2706 if ((pSMBr->resp.hdr.WordCount == 3)
2707 || ((pSMBr->resp.hdr.WordCount == 4)
2709 pSMBr->resp.ByteCount))) {
2710 if (pSMBr->resp.hdr.WordCount == 4) {
2714 ("Security Blob Length %d ",
2719 ("NTLMSSP response to Authenticate "));
2721 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2722 if ((long) (bcc_ptr) % 2) {
2724 (BCC(smb_buffer_response)
2726 bcc_ptr++; /* Unicode strings must be word aligned */
2728 remaining_words = BCC(smb_buffer_response) / 2;
2731 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2732 /* We look for obvious messed up bcc or strings in response so we do not go off
2733 the end since (at least) WIN2K and Windows XP have a major bug in not null
2734 terminating last Unicode string in response */
2736 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2737 cifs_strfromUCS_le(ses->serverOS,
2741 bcc_ptr += 2 * (len + 1);
2742 remaining_words -= len + 1;
2743 ses->serverOS[2 * len] = 0;
2744 ses->serverOS[1 + (2 * len)] = 0;
2745 if (remaining_words > 0) {
2746 len = UniStrnlen((wchar_t *)
2751 kcalloc(1, 2 * (len + 1),
2753 cifs_strfromUCS_le(ses->
2759 bcc_ptr += 2 * (len + 1);
2760 ses->serverNOS[2 * len] = 0;
2761 ses->serverNOS[1+(2*len)] = 0;
2762 remaining_words -= len + 1;
2763 if (remaining_words > 0) {
2764 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2765 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2790 } /* else no more room so create dummy domain string */
2792 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
2793 } else { /* no room so create dummy domain and NOS string */
2794 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2795 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2797 } else { /* ASCII */
2798 len = strnlen(bcc_ptr, 1024);
2799 if (((long) bcc_ptr + len) -
2800 (long) pByteArea(smb_buffer_response)
2801 <= BCC(smb_buffer_response)) {
2802 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2803 strncpy(ses->serverOS,bcc_ptr, len);
2806 bcc_ptr[0] = 0; /* null terminate the string */
2809 len = strnlen(bcc_ptr, 1024);
2810 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
2811 strncpy(ses->serverNOS, bcc_ptr, len);
2816 len = strnlen(bcc_ptr, 1024);
2817 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
2818 strncpy(ses->serverDomain, bcc_ptr, len);
2824 ("Variable field of length %d extends beyond end of smb ",
2829 (" Security Blob Length extends beyond end of SMB"));
2832 cERROR(1, ("No session structure passed in."));
2836 (" Invalid Word count %d: ",
2837 smb_buffer_response->WordCount));
2842 cifs_buf_release(smb_buffer);
2848 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2849 const char *tree, struct cifsTconInfo *tcon,
2850 const struct nls_table *nls_codepage)
2852 struct smb_hdr *smb_buffer;
2853 struct smb_hdr *smb_buffer_response;
2856 unsigned char *bcc_ptr;
2864 smb_buffer = cifs_buf_get();
2865 if (smb_buffer == NULL) {
2868 smb_buffer_response = smb_buffer;
2870 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2871 NULL /*no tid */ , 4 /*wct */ );
2872 smb_buffer->Uid = ses->Suid;
2873 pSMB = (TCONX_REQ *) smb_buffer;
2874 pSMBr = (TCONX_RSP *) smb_buffer_response;
2876 pSMB->AndXCommand = 0xFF;
2877 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2878 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2879 bcc_ptr = &pSMB->Password[0];
2880 bcc_ptr++; /* skip password */
2882 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2883 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2885 if (ses->capabilities & CAP_STATUS32) {
2886 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2888 if (ses->capabilities & CAP_DFS) {
2889 smb_buffer->Flags2 |= SMBFLG2_DFS;
2891 if (ses->capabilities & CAP_UNICODE) {
2892 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2894 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2895 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2896 bcc_ptr += 2; /* skip trailing null */
2897 } else { /* ASCII */
2899 strcpy(bcc_ptr, tree);
2900 bcc_ptr += strlen(tree) + 1;
2902 strcpy(bcc_ptr, "?????");
2903 bcc_ptr += strlen("?????");
2905 count = bcc_ptr - &pSMB->Password[0];
2906 pSMB->hdr.smb_buf_length += count;
2907 pSMB->ByteCount = cpu_to_le16(count);
2909 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2911 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2912 /* above now done in SendReceive */
2913 if ((rc == 0) && (tcon != NULL)) {
2914 tcon->tidStatus = CifsGood;
2915 tcon->tid = smb_buffer_response->Tid;
2916 bcc_ptr = pByteArea(smb_buffer_response);
2917 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2918 /* skip service field (NB: this field is always ASCII) */
2919 bcc_ptr += length + 1;
2920 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2921 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2922 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2923 if ((bcc_ptr + (2 * length)) -
2924 pByteArea(smb_buffer_response) <=
2925 BCC(smb_buffer_response)) {
2926 if(tcon->nativeFileSystem)
2927 kfree(tcon->nativeFileSystem);
2928 tcon->nativeFileSystem =
2929 kcalloc(1, length + 2, GFP_KERNEL);
2930 cifs_strfromUCS_le(tcon->nativeFileSystem,
2931 (wchar_t *) bcc_ptr,
2932 length, nls_codepage);
2933 bcc_ptr += 2 * length;
2934 bcc_ptr[0] = 0; /* null terminate the string */
2938 /* else do not bother copying these informational fields */
2940 length = strnlen(bcc_ptr, 1024);
2941 if ((bcc_ptr + length) -
2942 pByteArea(smb_buffer_response) <=
2943 BCC(smb_buffer_response)) {
2944 if(tcon->nativeFileSystem)
2945 kfree(tcon->nativeFileSystem);
2946 tcon->nativeFileSystem =
2947 kcalloc(1, length + 1, GFP_KERNEL);
2948 strncpy(tcon->nativeFileSystem, bcc_ptr,
2951 /* else do not bother copying these informational fields */
2953 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2954 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2955 } else if ((rc == 0) && tcon == NULL) {
2956 /* all we need to save for IPC$ connection */
2957 ses->ipc_tid = smb_buffer_response->Tid;
2961 cifs_buf_release(smb_buffer);
2966 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
2970 struct cifsSesInfo *ses = NULL;
2971 struct task_struct *cifsd_task;
2975 if (cifs_sb->tcon) {
2976 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
2977 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
2982 tconInfoFree(cifs_sb->tcon);
2983 if ((ses) && (ses->server)) {
2984 /* save off task so we do not refer to ses later */
2985 cifsd_task = ses->server->tsk;
2986 cFYI(1, ("About to do SMBLogoff "));
2987 rc = CIFSSMBLogoff(xid, ses);
2991 } else if (rc == -ESHUTDOWN) {
2992 cFYI(1,("Waking up socket by sending it signal"));
2994 send_sig(SIGKILL,cifsd_task,1);
2996 } /* else - we have an smb session
2997 left on this socket do not kill cifsd */
2999 cFYI(1, ("No session or bad tcon"));
3002 cifs_sb->tcon = NULL;
3004 set_current_state(TASK_INTERRUPTIBLE);
3005 schedule_timeout(HZ / 2);
3011 return rc; /* BB check if we should always return zero here */
3014 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3015 struct nls_table * nls_info)
3018 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3019 int ntlmv2_flag = FALSE;
3022 /* what if server changes its buffer size after dropping the session? */
3023 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3024 rc = CIFSSMBNegotiate(xid, pSesInfo);
3025 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3026 rc = CIFSSMBNegotiate(xid, pSesInfo);
3031 spin_lock(&GlobalMid_Lock);
3032 if(pSesInfo->server->tcpStatus != CifsExiting)
3033 pSesInfo->server->tcpStatus = CifsGood;
3036 spin_unlock(&GlobalMid_Lock);
3042 pSesInfo->capabilities = pSesInfo->server->capabilities;
3043 if(linuxExtEnabled == 0)
3044 pSesInfo->capabilities &= (~CAP_UNIX);
3045 /* pSesInfo->sequence_number = 0;*/
3046 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3047 pSesInfo->server->secMode,
3048 pSesInfo->server->capabilities,
3049 pSesInfo->server->timeZone));
3050 if (extended_security
3051 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3052 && (pSesInfo->server->secType == NTLMSSP)) {
3053 cFYI(1, ("New style sesssetup "));
3054 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3055 NULL /* security blob */,
3056 0 /* blob length */,
3058 } else if (extended_security
3059 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3060 && (pSesInfo->server->secType == RawNTLMSSP)) {
3061 cFYI(1, ("NTLMSSP sesssetup "));
3062 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3069 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3070 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3075 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3077 CalcNTLMv2_response(pSesInfo,v2_response);
3079 cifs_calculate_ntlmv2_mac_key(
3080 pSesInfo->server->mac_signing_key,
3081 response, ntlm_session_key, */
3083 /* BB Put dummy sig in SessSetup PDU? */
3090 SMBNTencrypt(pSesInfo->password,
3091 pSesInfo->server->cryptKey,
3095 cifs_calculate_mac_key(
3096 pSesInfo->server->mac_signing_key,
3098 pSesInfo->password);
3100 /* for better security the weaker lanman hash not sent
3101 in AuthSessSetup so we no longer calculate it */
3103 rc = CIFSNTLMSSPAuthSessSetup(xid,
3109 } else { /* old style NTLM 0.12 session setup */
3110 SMBNTencrypt(pSesInfo->password,
3111 pSesInfo->server->cryptKey,
3115 cifs_calculate_mac_key(
3116 pSesInfo->server->mac_signing_key,
3117 ntlm_session_key, pSesInfo->password);
3119 rc = CIFSSessSetup(xid, pSesInfo,
3120 ntlm_session_key, nls_info);
3123 cERROR(1,("Send error in SessSetup = %d",rc));
3125 cFYI(1,("CIFS Session Established successfully"));
3126 pSesInfo->status = CifsGood;