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;
401 spin_unlock(&GlobalMid_Lock);
407 smb_buffer = NULL; /* will be freed by users thread after he is done */
408 wake_up_process(task_to_wake);
409 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
410 cERROR(1, ("No task to wake, unknown frame rcvd!"));
411 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
416 ("Frame less than four bytes received %d bytes long.",
418 cifs_reconnect(server);
419 csocket = server->ssocket;
420 wake_up(&server->response_q);
424 spin_lock(&GlobalMid_Lock);
425 server->tcpStatus = CifsExiting;
427 atomic_set(&server->inFlight, 0);
428 spin_unlock(&GlobalMid_Lock);
429 /* Although there should not be any requests blocked on
430 this queue it can not hurt to be paranoid and try to wake up requests
431 that may haven been blocked when more than 50 at time were on the wire
432 to the same server - they now will see the session is in exit state
433 and get out of SendReceive. */
434 wake_up_all(&server->request_q);
435 /* give those requests time to exit */
438 if(server->ssocket) {
439 sock_release(csocket);
440 server->ssocket = NULL;
442 /* buffer usuallly freed in free_mid - need to free it here on exit */
444 cifs_buf_release(bigbuf);
445 if (smallbuf != NULL)
446 cifs_small_buf_release(smallbuf);
448 read_lock(&GlobalSMBSeslock);
449 if (list_empty(&server->pending_mid_q)) {
450 /* loop through server session structures attached to this and mark them dead */
451 list_for_each(tmp, &GlobalSMBSessionList) {
453 list_entry(tmp, struct cifsSesInfo,
455 if (ses->server == server) {
456 ses->status = CifsExiting;
460 read_unlock(&GlobalSMBSeslock);
462 spin_lock(&GlobalMid_Lock);
463 list_for_each(tmp, &server->pending_mid_q) {
464 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
465 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
467 (" Clearing Mid 0x%x - waking up ",mid_entry->mid));
468 task_to_wake = mid_entry->tsk;
470 wake_up_process(task_to_wake);
474 spin_unlock(&GlobalMid_Lock);
475 read_unlock(&GlobalSMBSeslock);
476 /* 1/8th of sec is more than enough time for them to exit */
480 if (list_empty(&server->pending_mid_q)) {
481 /* mpx threads have not exited yet give them
482 at least the smb send timeout time for long ops */
483 cFYI(1, ("Wait for exit from demultiplex thread"));
485 /* if threads still have not exited they are probably never
486 coming home not much else we can do but free the memory */
490 write_lock(&GlobalSMBSeslock);
491 atomic_dec(&tcpSesAllocCount);
492 length = tcpSesAllocCount.counter;
493 write_unlock(&GlobalSMBSeslock);
495 mempool_resize(cifs_req_poolp,
496 length + cifs_min_rcv,
505 cifs_kcalloc(size_t size, unsigned int __nocast type)
508 addr = kmalloc(size, type);
510 memset(addr, 0, size);
515 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
519 unsigned int temp_len, i, j;
525 memset(vol->source_rfc1001_name,0x20,15);
526 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
527 /* does not have to be a perfect mapping since the field is
528 informational, only used for servers that do not support
529 port 445 and it can be overridden at mount time */
530 vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]);
532 vol->source_rfc1001_name[15] = 0;
534 vol->linux_uid = current->uid; /* current->euid instead? */
535 vol->linux_gid = current->gid;
536 vol->dir_mode = S_IRWXUGO;
537 /* 2767 perms indicate mandatory locking support */
538 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
540 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
546 if(strncmp(options,"sep=",4) == 0) {
547 if(options[4] != 0) {
548 separator[0] = options[4];
551 cFYI(1,("Null separator not allowed"));
555 while ((data = strsep(&options, separator)) != NULL) {
558 if ((value = strchr(data, '=')) != NULL)
561 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
563 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
565 } else if (strnicmp(data, "user", 4) == 0) {
566 if (!value || !*value) {
568 "CIFS: invalid or missing username\n");
569 return 1; /* needs_arg; */
571 if (strnlen(value, 200) < 200) {
572 vol->username = value;
574 printk(KERN_WARNING "CIFS: username too long\n");
577 } else if (strnicmp(data, "pass", 4) == 0) {
579 vol->password = NULL;
581 } else if(value[0] == 0) {
582 /* check if string begins with double comma
583 since that would mean the password really
584 does start with a comma, and would not
585 indicate an empty string */
586 if(value[1] != separator[0]) {
587 vol->password = NULL;
591 temp_len = strlen(value);
592 /* removed password length check, NTLM passwords
593 can be arbitrarily long */
595 /* if comma in password, the string will be
596 prematurely null terminated. Commas in password are
597 specified across the cifs mount interface by a double
598 comma ie ,, and a comma used as in other cases ie ','
599 as a parameter delimiter/separator is single and due
600 to the strsep above is temporarily zeroed. */
602 /* NB: password legally can have multiple commas and
603 the only illegal character in a password is null */
605 if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) {
607 value[temp_len] = separator[0];
608 temp_len+=2; /* move after the second comma */
609 while(value[temp_len] != 0) {
610 if (value[temp_len] == separator[0]) {
611 if (value[temp_len+1] == separator[0]) {
612 temp_len++; /* skip second comma */
614 /* single comma indicating start
621 if(value[temp_len] == 0) {
625 /* point option to start of next parm */
626 options = value + temp_len + 1;
628 /* go from value to value + temp_len condensing
629 double commas to singles. Note that this ends up
630 allocating a few bytes too many, which is ok */
631 vol->password = cifs_kcalloc(temp_len, GFP_KERNEL);
632 for(i=0,j=0;i<temp_len;i++,j++) {
633 vol->password[j] = value[i];
634 if(value[i] == separator[0] && value[i+1] == separator[0]) {
635 /* skip second comma */
639 vol->password[j] = 0;
641 vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL);
642 strcpy(vol->password, value);
644 } else if (strnicmp(data, "ip", 2) == 0) {
645 if (!value || !*value) {
647 } else if (strnlen(value, 35) < 35) {
650 printk(KERN_WARNING "CIFS: ip address too long\n");
653 } else if ((strnicmp(data, "unc", 3) == 0)
654 || (strnicmp(data, "target", 6) == 0)
655 || (strnicmp(data, "path", 4) == 0)) {
656 if (!value || !*value) {
658 "CIFS: invalid path to network resource\n");
659 return 1; /* needs_arg; */
661 if ((temp_len = strnlen(value, 300)) < 300) {
662 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
665 strcpy(vol->UNC,value);
666 if (strncmp(vol->UNC, "//", 2) == 0) {
669 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
671 "CIFS: UNC Path does not begin with // or \\\\ \n");
675 printk(KERN_WARNING "CIFS: UNC name too long\n");
678 } else if ((strnicmp(data, "domain", 3) == 0)
679 || (strnicmp(data, "workgroup", 5) == 0)) {
680 if (!value || !*value) {
681 printk(KERN_WARNING "CIFS: invalid domain name\n");
682 return 1; /* needs_arg; */
684 /* BB are there cases in which a comma can be valid in
685 a domain name and need special handling? */
686 if (strnlen(value, 65) < 65) {
687 vol->domainname = value;
688 cFYI(1, ("Domain name set"));
690 printk(KERN_WARNING "CIFS: domain name too long\n");
693 } else if (strnicmp(data, "iocharset", 9) == 0) {
694 if (!value || !*value) {
695 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
696 return 1; /* needs_arg; */
698 if (strnlen(value, 65) < 65) {
699 if(strnicmp(value,"default",7))
700 vol->iocharset = value;
701 /* if iocharset not set load_nls_default used by caller */
702 cFYI(1, ("iocharset set to %s",value));
704 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
707 } else if (strnicmp(data, "uid", 3) == 0) {
708 if (value && *value) {
710 simple_strtoul(value, &value, 0);
712 } else if (strnicmp(data, "gid", 3) == 0) {
713 if (value && *value) {
715 simple_strtoul(value, &value, 0);
717 } else if (strnicmp(data, "file_mode", 4) == 0) {
718 if (value && *value) {
720 simple_strtoul(value, &value, 0);
722 } else if (strnicmp(data, "dir_mode", 4) == 0) {
723 if (value && *value) {
725 simple_strtoul(value, &value, 0);
727 } else if (strnicmp(data, "dirmode", 4) == 0) {
728 if (value && *value) {
730 simple_strtoul(value, &value, 0);
732 } else if (strnicmp(data, "port", 4) == 0) {
733 if (value && *value) {
735 simple_strtoul(value, &value, 0);
737 } else if (strnicmp(data, "rsize", 5) == 0) {
738 if (value && *value) {
740 simple_strtoul(value, &value, 0);
742 } else if (strnicmp(data, "wsize", 5) == 0) {
743 if (value && *value) {
745 simple_strtoul(value, &value, 0);
747 } else if (strnicmp(data, "sockopt", 5) == 0) {
748 if (value && *value) {
750 simple_strtoul(value, &value, 0);
752 } else if (strnicmp(data, "netbiosname", 4) == 0) {
753 if (!value || !*value || (*value == ' ')) {
754 cFYI(1,("invalid (empty) netbiosname specified"));
756 memset(vol->source_rfc1001_name,0x20,15);
758 /* BB are there cases in which a comma can be
759 valid in this workstation netbios name (and need
760 special handling)? */
762 /* We do not uppercase netbiosname for user */
766 vol->source_rfc1001_name[i] = value[i];
768 /* The string has 16th byte zero still from
769 set at top of the function */
770 if((i==15) && (value[i] != 0))
771 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
773 } else if (strnicmp(data, "credentials", 4) == 0) {
775 } else if (strnicmp(data, "version", 3) == 0) {
777 } else if (strnicmp(data, "guest",5) == 0) {
779 } else if (strnicmp(data, "rw", 2) == 0) {
781 } else if ((strnicmp(data, "suid", 4) == 0) ||
782 (strnicmp(data, "nosuid", 6) == 0) ||
783 (strnicmp(data, "exec", 4) == 0) ||
784 (strnicmp(data, "noexec", 6) == 0) ||
785 (strnicmp(data, "nodev", 5) == 0) ||
786 (strnicmp(data, "noauto", 6) == 0) ||
787 (strnicmp(data, "dev", 3) == 0)) {
788 /* The mount tool or mount.cifs helper (if present)
789 uses these opts to set flags, and the flags are read
790 by the kernel vfs layer before we get here (ie
791 before read super) so there is no point trying to
792 parse these options again and set anything and it
793 is ok to just ignore them */
795 } else if (strnicmp(data, "ro", 2) == 0) {
797 } else if (strnicmp(data, "hard", 4) == 0) {
799 } else if (strnicmp(data, "soft", 4) == 0) {
801 } else if (strnicmp(data, "perm", 4) == 0) {
803 } else if (strnicmp(data, "noperm", 6) == 0) {
805 } else if (strnicmp(data, "mapchars", 8) == 0) {
807 } else if (strnicmp(data, "nomapchars", 10) == 0) {
809 } else if (strnicmp(data, "setuids", 7) == 0) {
811 } else if (strnicmp(data, "nosetuids", 9) == 0) {
813 } else if (strnicmp(data, "nohard", 6) == 0) {
815 } else if (strnicmp(data, "nosoft", 6) == 0) {
817 } else if (strnicmp(data, "nointr", 6) == 0) {
819 } else if (strnicmp(data, "intr", 4) == 0) {
821 } else if (strnicmp(data, "serverino",7) == 0) {
823 } else if (strnicmp(data, "noserverino",9) == 0) {
825 } else if (strnicmp(data, "acl",3) == 0) {
827 } else if (strnicmp(data, "noacl",5) == 0) {
829 } else if (strnicmp(data, "direct",6) == 0) {
831 } else if (strnicmp(data, "forcedirectio",13) == 0) {
833 } else if (strnicmp(data, "in6_addr",8) == 0) {
834 if (!value || !*value) {
835 vol->in6_addr = NULL;
836 } else if (strnlen(value, 49) == 48) {
837 vol->in6_addr = value;
839 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
842 } else if (strnicmp(data, "noac", 4) == 0) {
843 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
845 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
847 if (vol->UNC == NULL) {
848 if(devname == NULL) {
849 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
852 if ((temp_len = strnlen(devname, 300)) < 300) {
853 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
856 strcpy(vol->UNC,devname);
857 if (strncmp(vol->UNC, "//", 2) == 0) {
860 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
861 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
865 printk(KERN_WARNING "CIFS: UNC name too long\n");
869 if(vol->UNCip == NULL)
870 vol->UNCip = &vol->UNC[2];
875 static struct cifsSesInfo *
876 cifs_find_tcp_session(struct in_addr * target_ip_addr,
877 struct in6_addr *target_ip6_addr,
878 char *userName, struct TCP_Server_Info **psrvTcp)
880 struct list_head *tmp;
881 struct cifsSesInfo *ses;
883 read_lock(&GlobalSMBSeslock);
885 list_for_each(tmp, &GlobalSMBSessionList) {
886 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
888 if((target_ip_addr &&
889 (ses->server->addr.sockAddr.sin_addr.s_addr
890 == target_ip_addr->s_addr)) || (target_ip6_addr
891 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
892 target_ip6_addr,sizeof(*target_ip6_addr)))){
893 /* BB lock server and tcp session and increment use count here?? */
894 *psrvTcp = ses->server; /* found a match on the TCP session */
895 /* BB check if reconnection needed */
897 (ses->userName, userName,
898 MAX_USERNAME_SIZE) == 0){
899 read_unlock(&GlobalSMBSeslock);
900 return ses; /* found exact match on both tcp and SMB sessions */
904 /* else tcp and smb sessions need reconnection */
906 read_unlock(&GlobalSMBSeslock);
910 static struct cifsTconInfo *
911 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
913 struct list_head *tmp;
914 struct cifsTconInfo *tcon;
916 read_lock(&GlobalSMBSeslock);
917 list_for_each(tmp, &GlobalTreeConnectionList) {
918 cFYI(1, ("Next tcon - "));
919 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
921 if (tcon->ses->server) {
923 (" old ip addr: %x == new ip %x ?",
924 tcon->ses->server->addr.sockAddr.sin_addr.
925 s_addr, new_target_ip_addr));
926 if (tcon->ses->server->addr.sockAddr.sin_addr.
927 s_addr == new_target_ip_addr) {
928 /* BB lock tcon and server and tcp session and increment use count here? */
929 /* found a match on the TCP session */
930 /* BB check if reconnection needed */
931 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
932 tcon->treeName, uncName));
934 (tcon->treeName, uncName,
935 MAX_TREE_SIZE) == 0) {
937 ("Matched UNC, old user: %s == new: %s ?",
938 tcon->treeName, uncName));
940 (tcon->ses->userName,
942 MAX_USERNAME_SIZE) == 0) {
943 read_unlock(&GlobalSMBSeslock);
944 return tcon;/* also matched user (smb session)*/
951 read_unlock(&GlobalSMBSeslock);
956 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
957 const char *old_path, const struct nls_table *nls_codepage,
960 unsigned char *referrals = NULL;
961 unsigned int num_referrals;
964 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
965 &num_referrals, &referrals, remap);
967 /* BB Add in code to: if valid refrl, if not ip address contact
968 the helper that resolves tcp names, mount to it, try to
969 tcon to it unmount it if fail */
978 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
979 const char *old_path, const struct nls_table *nls_codepage,
980 unsigned int *pnum_referrals,
981 unsigned char ** preferrals, int remap)
988 if (pSesInfo->ipc_tid == 0) {
989 temp_unc = kmalloc(2 /* for slashes */ +
990 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
991 + 1 + 4 /* slash IPC$ */ + 2,
993 if (temp_unc == NULL)
997 strcpy(temp_unc + 2, pSesInfo->serverName);
998 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
999 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1001 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1005 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1006 pnum_referrals, nls_codepage, remap);
1011 /* See RFC1001 section 14 on representation of Netbios names */
1012 static void rfc1002mangle(char * target,char * source, unsigned int length)
1016 for(i=0,j=0;i<(length);i++) {
1017 /* mask a nibble at a time and encode */
1018 target[j] = 'A' + (0x0F & (source[i] >> 4));
1019 target[j+1] = 'A' + (0x0F & source[i]);
1027 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1028 char * netbios_name)
1032 __be16 orig_port = 0;
1034 if(*csocket == NULL) {
1035 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1037 cERROR(1, ("Error %d creating socket",rc));
1041 /* BB other socket options to set KEEPALIVE, NODELAY? */
1042 cFYI(1,("Socket created"));
1043 (*csocket)->sk->sk_allocation = GFP_NOFS;
1047 psin_server->sin_family = AF_INET;
1048 if(psin_server->sin_port) { /* user overrode default port */
1049 rc = (*csocket)->ops->connect(*csocket,
1050 (struct sockaddr *) psin_server,
1051 sizeof (struct sockaddr_in),0);
1057 /* save original port so we can retry user specified port
1058 later if fall back ports fail this time */
1059 orig_port = psin_server->sin_port;
1061 /* do not retry on the same port we just failed on */
1062 if(psin_server->sin_port != htons(CIFS_PORT)) {
1063 psin_server->sin_port = htons(CIFS_PORT);
1065 rc = (*csocket)->ops->connect(*csocket,
1066 (struct sockaddr *) psin_server,
1067 sizeof (struct sockaddr_in),0);
1073 psin_server->sin_port = htons(RFC1001_PORT);
1074 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1075 psin_server, sizeof (struct sockaddr_in),0);
1080 /* give up here - unless we want to retry on different
1081 protocol families some day */
1084 psin_server->sin_port = orig_port;
1085 cFYI(1,("Error %d connecting to server via ipv4",rc));
1086 sock_release(*csocket);
1090 /* Eventually check for other socket options to change from
1091 the default. sock_setsockopt not used because it expects
1092 user space buffer */
1093 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1095 /* send RFC1001 sessinit */
1097 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1098 /* some servers require RFC1001 sessinit before sending
1099 negprot - BB check reconnection in case where second
1100 sessinit is sent but no second negprot */
1101 struct rfc1002_session_packet * ses_init_buf;
1102 struct smb_hdr * smb_buf;
1103 ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1105 ses_init_buf->trailer.session_req.called_len = 32;
1106 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1107 DEFAULT_CIFS_CALLED_NAME,16);
1108 ses_init_buf->trailer.session_req.calling_len = 32;
1109 /* calling name ends in null (byte 16) from old smb
1111 if(netbios_name && (netbios_name[0] !=0)) {
1112 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1115 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1116 "LINUX_CIFS_CLNT",16);
1118 ses_init_buf->trailer.session_req.scope1 = 0;
1119 ses_init_buf->trailer.session_req.scope2 = 0;
1120 smb_buf = (struct smb_hdr *)ses_init_buf;
1121 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1122 smb_buf->smb_buf_length = 0x81000044;
1123 rc = smb_send(*csocket, smb_buf, 0x44,
1124 (struct sockaddr *)psin_server);
1125 kfree(ses_init_buf);
1127 /* else the negprot may still work without this
1128 even though malloc failed */
1136 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1140 __be16 orig_port = 0;
1142 if(*csocket == NULL) {
1143 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1145 cERROR(1, ("Error %d creating ipv6 socket",rc));
1149 /* BB other socket options to set KEEPALIVE, NODELAY? */
1150 cFYI(1,("ipv6 Socket created"));
1151 (*csocket)->sk->sk_allocation = GFP_NOFS;
1155 psin_server->sin6_family = AF_INET6;
1157 if(psin_server->sin6_port) { /* user overrode default port */
1158 rc = (*csocket)->ops->connect(*csocket,
1159 (struct sockaddr *) psin_server,
1160 sizeof (struct sockaddr_in6),0);
1166 /* save original port so we can retry user specified port
1167 later if fall back ports fail this time */
1169 orig_port = psin_server->sin6_port;
1170 /* do not retry on the same port we just failed on */
1171 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1172 psin_server->sin6_port = htons(CIFS_PORT);
1174 rc = (*csocket)->ops->connect(*csocket,
1175 (struct sockaddr *) psin_server,
1176 sizeof (struct sockaddr_in6),0);
1182 psin_server->sin6_port = htons(RFC1001_PORT);
1183 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1184 psin_server, sizeof (struct sockaddr_in6),0);
1189 /* give up here - unless we want to retry on different
1190 protocol families some day */
1193 psin_server->sin6_port = orig_port;
1194 cFYI(1,("Error %d connecting to server via ipv6",rc));
1195 sock_release(*csocket);
1199 /* Eventually check for other socket options to change from
1200 the default. sock_setsockopt not used because it expects
1201 user space buffer */
1202 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1208 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1209 char *mount_data, const char *devname)
1213 int address_type = AF_INET;
1214 struct socket *csocket = NULL;
1215 struct sockaddr_in sin_server;
1216 struct sockaddr_in6 sin_server6;
1217 struct smb_vol volume_info;
1218 struct cifsSesInfo *pSesInfo = NULL;
1219 struct cifsSesInfo *existingCifsSes = NULL;
1220 struct cifsTconInfo *tcon = NULL;
1221 struct TCP_Server_Info *srvTcp = NULL;
1225 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1227 memset(&volume_info,0,sizeof(struct smb_vol));
1228 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1230 kfree(volume_info.UNC);
1231 if(volume_info.password)
1232 kfree(volume_info.password);
1237 if (volume_info.username) {
1238 /* BB fixme parse for domain name here */
1239 cFYI(1, ("Username: %s ", volume_info.username));
1242 cifserror("No username specified ");
1243 /* In userspace mount helper we can get user name from alternate
1244 locations such as env variables and files on disk */
1246 kfree(volume_info.UNC);
1247 if(volume_info.password)
1248 kfree(volume_info.password);
1253 if (volume_info.UNCip && volume_info.UNC) {
1254 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1257 /* not ipv4 address, try ipv6 */
1258 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1260 address_type = AF_INET6;
1262 address_type = AF_INET;
1266 /* we failed translating address */
1268 kfree(volume_info.UNC);
1269 if(volume_info.password)
1270 kfree(volume_info.password);
1275 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1278 } else if (volume_info.UNCip){
1279 /* BB using ip addr as server name connect to the DFS root below */
1280 cERROR(1,("Connecting to DFS root not implemented yet"));
1282 kfree(volume_info.UNC);
1283 if(volume_info.password)
1284 kfree(volume_info.password);
1287 } else /* which servers DFS root would we conect to */ {
1289 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1291 kfree(volume_info.UNC);
1292 if(volume_info.password)
1293 kfree(volume_info.password);
1298 /* this is needed for ASCII cp to Unicode converts */
1299 if(volume_info.iocharset == NULL) {
1300 cifs_sb->local_nls = load_nls_default();
1301 /* load_nls_default can not return null */
1303 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1304 if(cifs_sb->local_nls == NULL) {
1305 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1307 kfree(volume_info.UNC);
1308 if(volume_info.password)
1309 kfree(volume_info.password);
1315 if(address_type == AF_INET)
1316 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1317 NULL /* no ipv6 addr */,
1318 volume_info.username, &srvTcp);
1319 else if(address_type == AF_INET6)
1320 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1321 &sin_server6.sin6_addr,
1322 volume_info.username, &srvTcp);
1325 kfree(volume_info.UNC);
1326 if(volume_info.password)
1327 kfree(volume_info.password);
1334 cFYI(1, ("Existing tcp session with server found "));
1335 } else { /* create socket */
1336 if(volume_info.port)
1337 sin_server.sin_port = htons(volume_info.port);
1339 sin_server.sin_port = 0;
1340 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1343 ("Error connecting to IPv4 socket. Aborting operation"));
1345 sock_release(csocket);
1347 kfree(volume_info.UNC);
1348 if(volume_info.password)
1349 kfree(volume_info.password);
1354 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1355 if (srvTcp == NULL) {
1357 sock_release(csocket);
1359 kfree(volume_info.UNC);
1360 if(volume_info.password)
1361 kfree(volume_info.password);
1365 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1366 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1367 atomic_set(&srvTcp->inFlight,0);
1368 /* BB Add code for ipv6 case too */
1369 srvTcp->ssocket = csocket;
1370 srvTcp->protocolType = IPV4;
1371 init_waitqueue_head(&srvTcp->response_q);
1372 init_waitqueue_head(&srvTcp->request_q);
1373 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1374 /* at this point we are the only ones with the pointer
1375 to the struct since the kernel thread not created yet
1376 so no need to spinlock this init of tcpStatus */
1377 srvTcp->tcpStatus = CifsNew;
1378 init_MUTEX(&srvTcp->tcpSem);
1379 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1380 CLONE_FS | CLONE_FILES | CLONE_VM);
1383 sock_release(csocket);
1385 kfree(volume_info.UNC);
1386 if(volume_info.password)
1387 kfree(volume_info.password);
1392 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1393 srvTcp->sequence_number = 0;
1397 if (existingCifsSes) {
1398 pSesInfo = existingCifsSes;
1399 cFYI(1, ("Existing smb sess found "));
1400 if(volume_info.password)
1401 kfree(volume_info.password);
1402 /* volume_info.UNC freed at end of function */
1404 cFYI(1, ("Existing smb sess not found "));
1405 pSesInfo = sesInfoAlloc();
1406 if (pSesInfo == NULL)
1409 pSesInfo->server = srvTcp;
1410 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1411 NIPQUAD(sin_server.sin_addr.s_addr));
1415 /* volume_info.password freed at unmount */
1416 if (volume_info.password)
1417 pSesInfo->password = volume_info.password;
1418 if (volume_info.username)
1419 strncpy(pSesInfo->userName,
1420 volume_info.username,MAX_USERNAME_SIZE);
1421 if (volume_info.domainname)
1422 strncpy(pSesInfo->domainName,
1423 volume_info.domainname,MAX_USERNAME_SIZE);
1424 pSesInfo->linux_uid = volume_info.linux_uid;
1425 down(&pSesInfo->sesSem);
1426 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1427 up(&pSesInfo->sesSem);
1429 atomic_inc(&srvTcp->socketUseCount);
1431 if(volume_info.password)
1432 kfree(volume_info.password);
1435 /* search for existing tcon to this server share */
1437 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1438 cifs_sb->rsize = volume_info.rsize;
1440 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1441 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1442 cifs_sb->wsize = volume_info.wsize;
1444 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1445 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1446 cifs_sb->rsize = PAGE_CACHE_SIZE;
1447 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1449 cifs_sb->mnt_uid = volume_info.linux_uid;
1450 cifs_sb->mnt_gid = volume_info.linux_gid;
1451 cifs_sb->mnt_file_mode = volume_info.file_mode;
1452 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1453 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1455 if(volume_info.noperm)
1456 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1457 if(volume_info.setuids)
1458 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1459 if(volume_info.server_ino)
1460 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1461 if(volume_info.remap)
1462 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1463 if(volume_info.no_xattr)
1464 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1465 if(volume_info.direct_io) {
1466 cERROR(1,("mounting share using direct i/o"));
1467 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1471 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1472 volume_info.username);
1474 cFYI(1, ("Found match on UNC path "));
1475 /* we can have only one retry value for a connection
1476 to a share so for resources mounted more than once
1477 to the same server share the last value passed in
1478 for the retry flag is used */
1479 tcon->retry = volume_info.retry;
1481 tcon = tconInfoAlloc();
1485 /* check for null share name ie connect to dfs root */
1487 /* BB check if this works for exactly length three strings */
1488 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1489 && (strchr(volume_info.UNC + 3, '/') ==
1491 rc = connect_to_dfs_path(xid, pSesInfo,
1492 "", cifs_sb->local_nls,
1493 cifs_sb->mnt_cifs_flags &
1494 CIFS_MOUNT_MAP_SPECIAL_CHR);
1496 kfree(volume_info.UNC);
1500 rc = CIFSTCon(xid, pSesInfo,
1502 tcon, cifs_sb->local_nls);
1503 cFYI(1, ("CIFS Tcon rc = %d", rc));
1506 atomic_inc(&pSesInfo->inUse);
1507 tcon->retry = volume_info.retry;
1513 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1514 sb->s_maxbytes = (u64) 1 << 63;
1516 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1519 sb->s_time_gran = 100;
1521 /* on error free sesinfo and tcon struct if needed */
1523 /* if session setup failed, use count is zero but
1524 we still need to free cifsd thread */
1525 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1526 spin_lock(&GlobalMid_Lock);
1527 srvTcp->tcpStatus = CifsExiting;
1528 spin_unlock(&GlobalMid_Lock);
1530 send_sig(SIGKILL,srvTcp->tsk,1);
1532 /* If find_unc succeeded then rc == 0 so we can not end */
1533 if (tcon) /* up accidently freeing someone elses tcon struct */
1535 if (existingCifsSes == NULL) {
1537 if ((pSesInfo->server) &&
1538 (pSesInfo->status == CifsGood)) {
1540 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1541 /* if the socketUseCount is now zero */
1542 if((temp_rc == -ESHUTDOWN) &&
1543 (pSesInfo->server->tsk))
1544 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1546 cFYI(1, ("No session or bad tcon"));
1547 sesInfoFree(pSesInfo);
1548 /* pSesInfo = NULL; */
1552 atomic_inc(&tcon->useCount);
1553 cifs_sb->tcon = tcon;
1554 tcon->ses = pSesInfo;
1556 /* do not care if following two calls succeed - informational only */
1557 CIFSSMBQFSDeviceInfo(xid, tcon);
1558 CIFSSMBQFSAttributeInfo(xid, tcon);
1559 if (tcon->ses->capabilities & CAP_UNIX) {
1560 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1561 if(!volume_info.no_psx_acl) {
1562 if(CIFS_UNIX_POSIX_ACL_CAP &
1563 le64_to_cpu(tcon->fsUnixInfo.Capability))
1564 cFYI(1,("server negotiated posix acl support"));
1565 sb->s_flags |= MS_POSIXACL;
1571 /* volume_info.password is freed above when existing session found
1572 (in which case it is not needed anymore) but when new sesion is created
1573 the password ptr is put in the new session structure (in which case the
1574 password will be freed at unmount time) */
1576 kfree(volume_info.UNC);
1582 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1583 char session_key[CIFS_SESSION_KEY_SIZE],
1584 const struct nls_table *nls_codepage)
1586 struct smb_hdr *smb_buffer;
1587 struct smb_hdr *smb_buffer_response;
1588 SESSION_SETUP_ANDX *pSMB;
1589 SESSION_SETUP_ANDX *pSMBr;
1594 int remaining_words = 0;
1595 int bytes_returned = 0;
1600 cFYI(1, ("In sesssetup "));
1603 user = ses->userName;
1604 domain = ses->domainName;
1605 smb_buffer = cifs_buf_get();
1606 if (smb_buffer == NULL) {
1609 smb_buffer_response = smb_buffer;
1610 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1612 /* send SMBsessionSetup here */
1613 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1614 NULL /* no tCon exists yet */ , 13 /* wct */ );
1616 pSMB->req_no_secext.AndXCommand = 0xFF;
1617 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1618 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1620 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1621 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1623 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1624 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1625 if (ses->capabilities & CAP_UNICODE) {
1626 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1627 capabilities |= CAP_UNICODE;
1629 if (ses->capabilities & CAP_STATUS32) {
1630 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1631 capabilities |= CAP_STATUS32;
1633 if (ses->capabilities & CAP_DFS) {
1634 smb_buffer->Flags2 |= SMBFLG2_DFS;
1635 capabilities |= CAP_DFS;
1637 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1639 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1640 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1642 pSMB->req_no_secext.CaseSensitivePasswordLength =
1643 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1644 bcc_ptr = pByteArea(smb_buffer);
1645 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1646 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1647 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1648 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1650 if (ses->capabilities & CAP_UNICODE) {
1651 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1656 bytes_returned = 0; /* skill null user */
1659 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1661 /* convert number of 16 bit words to bytes */
1662 bcc_ptr += 2 * bytes_returned;
1663 bcc_ptr += 2; /* trailing null */
1666 cifs_strtoUCS((wchar_t *) bcc_ptr,
1667 "CIFS_LINUX_DOM", 32, nls_codepage);
1670 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1672 bcc_ptr += 2 * bytes_returned;
1675 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1677 bcc_ptr += 2 * bytes_returned;
1679 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1681 bcc_ptr += 2 * bytes_returned;
1684 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1686 bcc_ptr += 2 * bytes_returned;
1690 strncpy(bcc_ptr, user, 200);
1691 bcc_ptr += strnlen(user, 200);
1695 if (domain == NULL) {
1696 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1697 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1699 strncpy(bcc_ptr, domain, 64);
1700 bcc_ptr += strnlen(domain, 64);
1704 strcpy(bcc_ptr, "Linux version ");
1705 bcc_ptr += strlen("Linux version ");
1706 strcpy(bcc_ptr, system_utsname.release);
1707 bcc_ptr += strlen(system_utsname.release) + 1;
1708 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1709 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1711 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1712 smb_buffer->smb_buf_length += count;
1713 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1715 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1716 &bytes_returned, 1);
1718 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1719 } else if ((smb_buffer_response->WordCount == 3)
1720 || (smb_buffer_response->WordCount == 4)) {
1721 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1722 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1723 if (action & GUEST_LOGIN)
1724 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1725 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1726 cFYI(1, ("UID = %d ", ses->Suid));
1727 /* response can have either 3 or 4 word count - Samba sends 3 */
1728 bcc_ptr = pByteArea(smb_buffer_response);
1729 if ((pSMBr->resp.hdr.WordCount == 3)
1730 || ((pSMBr->resp.hdr.WordCount == 4)
1731 && (blob_len < pSMBr->resp.ByteCount))) {
1732 if (pSMBr->resp.hdr.WordCount == 4)
1733 bcc_ptr += blob_len;
1735 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1736 if ((long) (bcc_ptr) % 2) {
1738 (BCC(smb_buffer_response) - 1) /2;
1739 bcc_ptr++; /* Unicode strings must be word aligned */
1742 BCC(smb_buffer_response) / 2;
1745 UniStrnlen((wchar_t *) bcc_ptr,
1746 remaining_words - 1);
1747 /* We look for obvious messed up bcc or strings in response so we do not go off
1748 the end since (at least) WIN2K and Windows XP have a major bug in not null
1749 terminating last Unicode string in response */
1750 ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
1751 cifs_strfromUCS_le(ses->serverOS,
1752 (wchar_t *)bcc_ptr, len,nls_codepage);
1753 bcc_ptr += 2 * (len + 1);
1754 remaining_words -= len + 1;
1755 ses->serverOS[2 * len] = 0;
1756 ses->serverOS[1 + (2 * len)] = 0;
1757 if (remaining_words > 0) {
1758 len = UniStrnlen((wchar_t *)bcc_ptr,
1760 ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL);
1761 cifs_strfromUCS_le(ses->serverNOS,
1762 (wchar_t *)bcc_ptr,len,nls_codepage);
1763 bcc_ptr += 2 * (len + 1);
1764 ses->serverNOS[2 * len] = 0;
1765 ses->serverNOS[1 + (2 * len)] = 0;
1766 if(strncmp(ses->serverNOS,
1767 "NT LAN Manager 4",16) == 0) {
1768 cFYI(1,("NT4 server"));
1769 ses->flags |= CIFS_SES_NT4;
1771 remaining_words -= len + 1;
1772 if (remaining_words > 0) {
1773 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1774 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1776 cifs_kcalloc(2*(len+1),GFP_KERNEL);
1777 cifs_strfromUCS_le(ses->serverDomain,
1778 (wchar_t *)bcc_ptr,len,nls_codepage);
1779 bcc_ptr += 2 * (len + 1);
1780 ses->serverDomain[2*len] = 0;
1781 ses->serverDomain[1+(2*len)] = 0;
1782 } /* else no more room so create dummy domain string */
1787 } else { /* no room so create dummy domain and NOS string */
1789 cifs_kcalloc(2, GFP_KERNEL);
1791 cifs_kcalloc(2, GFP_KERNEL);
1793 } else { /* ASCII */
1794 len = strnlen(bcc_ptr, 1024);
1795 if (((long) bcc_ptr + len) - (long)
1796 pByteArea(smb_buffer_response)
1797 <= BCC(smb_buffer_response)) {
1798 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1799 strncpy(ses->serverOS,bcc_ptr, len);
1802 bcc_ptr[0] = 0; /* null terminate the string */
1805 len = strnlen(bcc_ptr, 1024);
1806 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
1807 strncpy(ses->serverNOS, bcc_ptr, len);
1812 len = strnlen(bcc_ptr, 1024);
1813 ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL);
1814 strncpy(ses->serverDomain, bcc_ptr, len);
1820 ("Variable field of length %d extends beyond end of smb ",
1825 (" Security Blob Length extends beyond end of SMB"));
1829 (" Invalid Word count %d: ",
1830 smb_buffer_response->WordCount));
1835 cifs_buf_release(smb_buffer);
1841 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1842 char *SecurityBlob,int SecurityBlobLength,
1843 const struct nls_table *nls_codepage)
1845 struct smb_hdr *smb_buffer;
1846 struct smb_hdr *smb_buffer_response;
1847 SESSION_SETUP_ANDX *pSMB;
1848 SESSION_SETUP_ANDX *pSMBr;
1853 int remaining_words = 0;
1854 int bytes_returned = 0;
1859 cFYI(1, ("In spnego sesssetup "));
1862 user = ses->userName;
1863 domain = ses->domainName;
1865 smb_buffer = cifs_buf_get();
1866 if (smb_buffer == NULL) {
1869 smb_buffer_response = smb_buffer;
1870 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1872 /* send SMBsessionSetup here */
1873 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1874 NULL /* no tCon exists yet */ , 12 /* wct */ );
1875 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1876 pSMB->req.AndXCommand = 0xFF;
1877 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1878 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1880 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1881 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1883 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1884 CAP_EXTENDED_SECURITY;
1885 if (ses->capabilities & CAP_UNICODE) {
1886 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1887 capabilities |= CAP_UNICODE;
1889 if (ses->capabilities & CAP_STATUS32) {
1890 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1891 capabilities |= CAP_STATUS32;
1893 if (ses->capabilities & CAP_DFS) {
1894 smb_buffer->Flags2 |= SMBFLG2_DFS;
1895 capabilities |= CAP_DFS;
1897 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1899 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1900 bcc_ptr = pByteArea(smb_buffer);
1901 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1902 bcc_ptr += SecurityBlobLength;
1904 if (ses->capabilities & CAP_UNICODE) {
1905 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1910 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1911 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1912 bcc_ptr += 2; /* trailing null */
1915 cifs_strtoUCS((wchar_t *) bcc_ptr,
1916 "CIFS_LINUX_DOM", 32, nls_codepage);
1919 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1921 bcc_ptr += 2 * bytes_returned;
1924 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1926 bcc_ptr += 2 * bytes_returned;
1928 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
1930 bcc_ptr += 2 * bytes_returned;
1933 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1935 bcc_ptr += 2 * bytes_returned;
1938 strncpy(bcc_ptr, user, 200);
1939 bcc_ptr += strnlen(user, 200);
1942 if (domain == NULL) {
1943 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1944 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1946 strncpy(bcc_ptr, domain, 64);
1947 bcc_ptr += strnlen(domain, 64);
1951 strcpy(bcc_ptr, "Linux version ");
1952 bcc_ptr += strlen("Linux version ");
1953 strcpy(bcc_ptr, system_utsname.release);
1954 bcc_ptr += strlen(system_utsname.release) + 1;
1955 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1956 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1958 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1959 smb_buffer->smb_buf_length += count;
1960 pSMB->req.ByteCount = cpu_to_le16(count);
1962 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1963 &bytes_returned, 1);
1965 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
1966 } else if ((smb_buffer_response->WordCount == 3)
1967 || (smb_buffer_response->WordCount == 4)) {
1968 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1970 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1971 if (action & GUEST_LOGIN)
1972 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
1974 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1975 cFYI(1, ("UID = %d ", ses->Suid));
1976 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
1978 /* BB Fix below to make endian neutral !! */
1980 if ((pSMBr->resp.hdr.WordCount == 3)
1981 || ((pSMBr->resp.hdr.WordCount == 4)
1983 pSMBr->resp.ByteCount))) {
1984 if (pSMBr->resp.hdr.WordCount == 4) {
1988 ("Security Blob Length %d ",
1992 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1993 if ((long) (bcc_ptr) % 2) {
1995 (BCC(smb_buffer_response)
1997 bcc_ptr++; /* Unicode strings must be word aligned */
2001 (smb_buffer_response) / 2;
2004 UniStrnlen((wchar_t *) bcc_ptr,
2005 remaining_words - 1);
2006 /* We look for obvious messed up bcc or strings in response so we do not go off
2007 the end since (at least) WIN2K and Windows XP have a major bug in not null
2008 terminating last Unicode string in response */
2010 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2011 cifs_strfromUCS_le(ses->serverOS,
2015 bcc_ptr += 2 * (len + 1);
2016 remaining_words -= len + 1;
2017 ses->serverOS[2 * len] = 0;
2018 ses->serverOS[1 + (2 * len)] = 0;
2019 if (remaining_words > 0) {
2020 len = UniStrnlen((wchar_t *)bcc_ptr,
2024 cifs_kcalloc(2 * (len + 1),
2026 cifs_strfromUCS_le(ses->serverNOS,
2030 bcc_ptr += 2 * (len + 1);
2031 ses->serverNOS[2 * len] = 0;
2032 ses->serverNOS[1 + (2 * len)] = 0;
2033 remaining_words -= len + 1;
2034 if (remaining_words > 0) {
2035 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2036 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2037 ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL);
2038 cifs_strfromUCS_le(ses->serverDomain,
2042 bcc_ptr += 2*(len+1);
2043 ses->serverDomain[2*len] = 0;
2044 ses->serverDomain[1+(2*len)] = 0;
2045 } /* else no more room so create dummy domain string */
2048 cifs_kcalloc(2,GFP_KERNEL);
2049 } else { /* no room so create dummy domain and NOS string */
2050 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2051 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2053 } else { /* ASCII */
2055 len = strnlen(bcc_ptr, 1024);
2056 if (((long) bcc_ptr + len) - (long)
2057 pByteArea(smb_buffer_response)
2058 <= BCC(smb_buffer_response)) {
2059 ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL);
2060 strncpy(ses->serverOS, bcc_ptr, len);
2063 bcc_ptr[0] = 0; /* null terminate the string */
2066 len = strnlen(bcc_ptr, 1024);
2067 ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2068 strncpy(ses->serverNOS, bcc_ptr, len);
2073 len = strnlen(bcc_ptr, 1024);
2074 ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL);
2075 strncpy(ses->serverDomain, bcc_ptr, len);
2081 ("Variable field of length %d extends beyond end of smb ",
2086 (" Security Blob Length extends beyond end of SMB"));
2089 cERROR(1, ("No session structure passed in."));
2093 (" Invalid Word count %d: ",
2094 smb_buffer_response->WordCount));
2099 cifs_buf_release(smb_buffer);
2105 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2106 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2107 const struct nls_table *nls_codepage)
2109 struct smb_hdr *smb_buffer;
2110 struct smb_hdr *smb_buffer_response;
2111 SESSION_SETUP_ANDX *pSMB;
2112 SESSION_SETUP_ANDX *pSMBr;
2116 int remaining_words = 0;
2117 int bytes_returned = 0;
2119 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2120 PNEGOTIATE_MESSAGE SecurityBlob;
2121 PCHALLENGE_MESSAGE SecurityBlob2;
2122 __u32 negotiate_flags, capabilities;
2125 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2128 domain = ses->domainName;
2129 *pNTLMv2_flag = FALSE;
2130 smb_buffer = cifs_buf_get();
2131 if (smb_buffer == NULL) {
2134 smb_buffer_response = smb_buffer;
2135 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2136 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2138 /* send SMBsessionSetup here */
2139 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2140 NULL /* no tCon exists yet */ , 12 /* wct */ );
2141 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2142 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2144 pSMB->req.AndXCommand = 0xFF;
2145 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2146 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2148 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2149 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2151 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2152 CAP_EXTENDED_SECURITY;
2153 if (ses->capabilities & CAP_UNICODE) {
2154 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2155 capabilities |= CAP_UNICODE;
2157 if (ses->capabilities & CAP_STATUS32) {
2158 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2159 capabilities |= CAP_STATUS32;
2161 if (ses->capabilities & CAP_DFS) {
2162 smb_buffer->Flags2 |= SMBFLG2_DFS;
2163 capabilities |= CAP_DFS;
2165 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2167 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2168 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2169 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2170 SecurityBlob->MessageType = NtLmNegotiate;
2172 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2173 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2174 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2176 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2178 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2179 /* setup pointers to domain name and workstation name */
2180 bcc_ptr += SecurityBlobLength;
2182 SecurityBlob->WorkstationName.Buffer = 0;
2183 SecurityBlob->WorkstationName.Length = 0;
2184 SecurityBlob->WorkstationName.MaximumLength = 0;
2186 if (domain == NULL) {
2187 SecurityBlob->DomainName.Buffer = 0;
2188 SecurityBlob->DomainName.Length = 0;
2189 SecurityBlob->DomainName.MaximumLength = 0;
2192 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2193 strncpy(bcc_ptr, domain, 63);
2194 len = strnlen(domain, 64);
2195 SecurityBlob->DomainName.MaximumLength =
2197 SecurityBlob->DomainName.Buffer =
2198 cpu_to_le32((long) &SecurityBlob->
2200 (long) &SecurityBlob->Signature);
2202 SecurityBlobLength += len;
2203 SecurityBlob->DomainName.Length =
2206 if (ses->capabilities & CAP_UNICODE) {
2207 if ((long) bcc_ptr % 2) {
2213 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2215 bcc_ptr += 2 * bytes_returned;
2217 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2219 bcc_ptr += 2 * bytes_returned;
2220 bcc_ptr += 2; /* null terminate Linux version */
2222 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2224 bcc_ptr += 2 * bytes_returned;
2227 bcc_ptr += 2; /* null terminate network opsys string */
2230 bcc_ptr += 2; /* null domain */
2231 } else { /* ASCII */
2232 strcpy(bcc_ptr, "Linux version ");
2233 bcc_ptr += strlen("Linux version ");
2234 strcpy(bcc_ptr, system_utsname.release);
2235 bcc_ptr += strlen(system_utsname.release) + 1;
2236 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2237 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2238 bcc_ptr++; /* empty domain field */
2241 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2242 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2243 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2244 smb_buffer->smb_buf_length += count;
2245 pSMB->req.ByteCount = cpu_to_le16(count);
2247 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2248 &bytes_returned, 1);
2250 if (smb_buffer_response->Status.CifsError ==
2251 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2255 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2256 } else if ((smb_buffer_response->WordCount == 3)
2257 || (smb_buffer_response->WordCount == 4)) {
2258 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2259 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2261 if (action & GUEST_LOGIN)
2262 cFYI(1, (" Guest login"));
2263 /* Do we want to set anything in SesInfo struct when guest login? */
2265 bcc_ptr = pByteArea(smb_buffer_response);
2266 /* response can have either 3 or 4 word count - Samba sends 3 */
2268 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2269 if (SecurityBlob2->MessageType != NtLmChallenge) {
2271 ("Unexpected NTLMSSP message type received %d",
2272 SecurityBlob2->MessageType));
2274 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2275 cFYI(1, ("UID = %d ", ses->Suid));
2276 if ((pSMBr->resp.hdr.WordCount == 3)
2277 || ((pSMBr->resp.hdr.WordCount == 4)
2279 pSMBr->resp.ByteCount))) {
2281 if (pSMBr->resp.hdr.WordCount == 4) {
2282 bcc_ptr += blob_len;
2284 ("Security Blob Length %d ",
2288 cFYI(1, ("NTLMSSP Challenge rcvd "));
2290 memcpy(ses->server->cryptKey,
2291 SecurityBlob2->Challenge,
2292 CIFS_CRYPTO_KEY_SIZE);
2293 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2294 *pNTLMv2_flag = TRUE;
2296 if((SecurityBlob2->NegotiateFlags &
2297 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2298 || (sign_CIFS_PDUs > 1))
2299 ses->server->secMode |=
2300 SECMODE_SIGN_REQUIRED;
2301 if ((SecurityBlob2->NegotiateFlags &
2302 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2303 ses->server->secMode |=
2304 SECMODE_SIGN_ENABLED;
2306 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2307 if ((long) (bcc_ptr) % 2) {
2309 (BCC(smb_buffer_response)
2311 bcc_ptr++; /* Unicode strings must be word aligned */
2315 (smb_buffer_response) / 2;
2318 UniStrnlen((wchar_t *) bcc_ptr,
2319 remaining_words - 1);
2320 /* We look for obvious messed up bcc or strings in response so we do not go off
2321 the end since (at least) WIN2K and Windows XP have a major bug in not null
2322 terminating last Unicode string in response */
2324 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2325 cifs_strfromUCS_le(ses->serverOS,
2329 bcc_ptr += 2 * (len + 1);
2330 remaining_words -= len + 1;
2331 ses->serverOS[2 * len] = 0;
2332 ses->serverOS[1 + (2 * len)] = 0;
2333 if (remaining_words > 0) {
2334 len = UniStrnlen((wchar_t *)
2339 cifs_kcalloc(2 * (len + 1),
2341 cifs_strfromUCS_le(ses->
2347 bcc_ptr += 2 * (len + 1);
2348 ses->serverNOS[2 * len] = 0;
2351 remaining_words -= len + 1;
2352 if (remaining_words > 0) {
2353 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2354 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2379 } /* else no more room so create dummy domain string */
2384 } else { /* no room so create dummy domain and NOS string */
2386 cifs_kcalloc(2, GFP_KERNEL);
2388 cifs_kcalloc(2, GFP_KERNEL);
2390 } else { /* ASCII */
2391 len = strnlen(bcc_ptr, 1024);
2392 if (((long) bcc_ptr + len) - (long)
2393 pByteArea(smb_buffer_response)
2394 <= BCC(smb_buffer_response)) {
2396 cifs_kcalloc(len + 1,
2398 strncpy(ses->serverOS,
2402 bcc_ptr[0] = 0; /* null terminate string */
2405 len = strnlen(bcc_ptr, 1024);
2407 cifs_kcalloc(len + 1,
2409 strncpy(ses->serverNOS, bcc_ptr, len);
2414 len = strnlen(bcc_ptr, 1024);
2416 cifs_kcalloc(len + 1,
2418 strncpy(ses->serverDomain, bcc_ptr, len);
2424 ("Variable field of length %d extends beyond end of smb ",
2429 (" Security Blob Length extends beyond end of SMB"));
2432 cERROR(1, ("No session structure passed in."));
2436 (" Invalid Word count %d: ",
2437 smb_buffer_response->WordCount));
2442 cifs_buf_release(smb_buffer);
2447 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2448 char *ntlm_session_key, int ntlmv2_flag,
2449 const struct nls_table *nls_codepage)
2451 struct smb_hdr *smb_buffer;
2452 struct smb_hdr *smb_buffer_response;
2453 SESSION_SETUP_ANDX *pSMB;
2454 SESSION_SETUP_ANDX *pSMBr;
2459 int remaining_words = 0;
2460 int bytes_returned = 0;
2462 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2463 PAUTHENTICATE_MESSAGE SecurityBlob;
2464 __u32 negotiate_flags, capabilities;
2467 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2470 user = ses->userName;
2471 domain = ses->domainName;
2472 smb_buffer = cifs_buf_get();
2473 if (smb_buffer == NULL) {
2476 smb_buffer_response = smb_buffer;
2477 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2478 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2480 /* send SMBsessionSetup here */
2481 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2482 NULL /* no tCon exists yet */ , 12 /* wct */ );
2483 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2484 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2485 pSMB->req.AndXCommand = 0xFF;
2486 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2487 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2489 pSMB->req.hdr.Uid = ses->Suid;
2491 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2492 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2494 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2495 CAP_EXTENDED_SECURITY;
2496 if (ses->capabilities & CAP_UNICODE) {
2497 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2498 capabilities |= CAP_UNICODE;
2500 if (ses->capabilities & CAP_STATUS32) {
2501 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2502 capabilities |= CAP_STATUS32;
2504 if (ses->capabilities & CAP_DFS) {
2505 smb_buffer->Flags2 |= SMBFLG2_DFS;
2506 capabilities |= CAP_DFS;
2508 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2510 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2511 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2512 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2513 SecurityBlob->MessageType = NtLmAuthenticate;
2514 bcc_ptr += SecurityBlobLength;
2516 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2517 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2518 0x80000000 | NTLMSSP_NEGOTIATE_128;
2520 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2522 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2524 /* setup pointers to domain name and workstation name */
2526 SecurityBlob->WorkstationName.Buffer = 0;
2527 SecurityBlob->WorkstationName.Length = 0;
2528 SecurityBlob->WorkstationName.MaximumLength = 0;
2529 SecurityBlob->SessionKey.Length = 0;
2530 SecurityBlob->SessionKey.MaximumLength = 0;
2531 SecurityBlob->SessionKey.Buffer = 0;
2533 SecurityBlob->LmChallengeResponse.Length = 0;
2534 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2535 SecurityBlob->LmChallengeResponse.Buffer = 0;
2537 SecurityBlob->NtChallengeResponse.Length =
2538 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2539 SecurityBlob->NtChallengeResponse.MaximumLength =
2540 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2541 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2542 SecurityBlob->NtChallengeResponse.Buffer =
2543 cpu_to_le32(SecurityBlobLength);
2544 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2545 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2547 if (ses->capabilities & CAP_UNICODE) {
2548 if (domain == NULL) {
2549 SecurityBlob->DomainName.Buffer = 0;
2550 SecurityBlob->DomainName.Length = 0;
2551 SecurityBlob->DomainName.MaximumLength = 0;
2554 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2557 SecurityBlob->DomainName.MaximumLength =
2559 SecurityBlob->DomainName.Buffer =
2560 cpu_to_le32(SecurityBlobLength);
2562 SecurityBlobLength += len;
2563 SecurityBlob->DomainName.Length =
2567 SecurityBlob->UserName.Buffer = 0;
2568 SecurityBlob->UserName.Length = 0;
2569 SecurityBlob->UserName.MaximumLength = 0;
2572 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2575 SecurityBlob->UserName.MaximumLength =
2577 SecurityBlob->UserName.Buffer =
2578 cpu_to_le32(SecurityBlobLength);
2580 SecurityBlobLength += len;
2581 SecurityBlob->UserName.Length =
2585 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2586 SecurityBlob->WorkstationName.Length *= 2;
2587 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2588 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2589 bcc_ptr += SecurityBlob->WorkstationName.Length;
2590 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2591 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2593 if ((long) bcc_ptr % 2) {
2598 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2600 bcc_ptr += 2 * bytes_returned;
2602 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2604 bcc_ptr += 2 * bytes_returned;
2605 bcc_ptr += 2; /* null term version string */
2607 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2609 bcc_ptr += 2 * bytes_returned;
2612 bcc_ptr += 2; /* null terminate network opsys string */
2615 bcc_ptr += 2; /* null domain */
2616 } else { /* ASCII */
2617 if (domain == NULL) {
2618 SecurityBlob->DomainName.Buffer = 0;
2619 SecurityBlob->DomainName.Length = 0;
2620 SecurityBlob->DomainName.MaximumLength = 0;
2623 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2624 strncpy(bcc_ptr, domain, 63);
2625 len = strnlen(domain, 64);
2626 SecurityBlob->DomainName.MaximumLength =
2628 SecurityBlob->DomainName.Buffer =
2629 cpu_to_le32(SecurityBlobLength);
2631 SecurityBlobLength += len;
2632 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2635 SecurityBlob->UserName.Buffer = 0;
2636 SecurityBlob->UserName.Length = 0;
2637 SecurityBlob->UserName.MaximumLength = 0;
2640 strncpy(bcc_ptr, user, 63);
2641 len = strnlen(user, 64);
2642 SecurityBlob->UserName.MaximumLength =
2644 SecurityBlob->UserName.Buffer =
2645 cpu_to_le32(SecurityBlobLength);
2647 SecurityBlobLength += len;
2648 SecurityBlob->UserName.Length = cpu_to_le16(len);
2650 /* BB fill in our workstation name if known BB */
2652 strcpy(bcc_ptr, "Linux version ");
2653 bcc_ptr += strlen("Linux version ");
2654 strcpy(bcc_ptr, system_utsname.release);
2655 bcc_ptr += strlen(system_utsname.release) + 1;
2656 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2657 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2658 bcc_ptr++; /* null domain */
2661 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2662 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2663 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2664 smb_buffer->smb_buf_length += count;
2665 pSMB->req.ByteCount = cpu_to_le16(count);
2667 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2668 &bytes_returned, 1);
2670 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2671 } else if ((smb_buffer_response->WordCount == 3)
2672 || (smb_buffer_response->WordCount == 4)) {
2673 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2675 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2676 if (action & GUEST_LOGIN)
2677 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2678 /* if(SecurityBlob2->MessageType != NtLm??){
2679 cFYI("Unexpected message type on auth response is %d "));
2683 ("Does UID on challenge %d match auth response UID %d ",
2684 ses->Suid, smb_buffer_response->Uid));
2685 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2686 bcc_ptr = pByteArea(smb_buffer_response);
2687 /* response can have either 3 or 4 word count - Samba sends 3 */
2688 if ((pSMBr->resp.hdr.WordCount == 3)
2689 || ((pSMBr->resp.hdr.WordCount == 4)
2691 pSMBr->resp.ByteCount))) {
2692 if (pSMBr->resp.hdr.WordCount == 4) {
2696 ("Security Blob Length %d ",
2701 ("NTLMSSP response to Authenticate "));
2703 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2704 if ((long) (bcc_ptr) % 2) {
2706 (BCC(smb_buffer_response)
2708 bcc_ptr++; /* Unicode strings must be word aligned */
2710 remaining_words = BCC(smb_buffer_response) / 2;
2713 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2714 /* We look for obvious messed up bcc or strings in response so we do not go off
2715 the end since (at least) WIN2K and Windows XP have a major bug in not null
2716 terminating last Unicode string in response */
2718 cifs_kcalloc(2 * (len + 1), GFP_KERNEL);
2719 cifs_strfromUCS_le(ses->serverOS,
2723 bcc_ptr += 2 * (len + 1);
2724 remaining_words -= len + 1;
2725 ses->serverOS[2 * len] = 0;
2726 ses->serverOS[1 + (2 * len)] = 0;
2727 if (remaining_words > 0) {
2728 len = UniStrnlen((wchar_t *)
2733 cifs_kcalloc(2 * (len + 1),
2735 cifs_strfromUCS_le(ses->
2741 bcc_ptr += 2 * (len + 1);
2742 ses->serverNOS[2 * len] = 0;
2743 ses->serverNOS[1+(2*len)] = 0;
2744 remaining_words -= len + 1;
2745 if (remaining_words > 0) {
2746 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2747 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2772 } /* else no more room so create dummy domain string */
2774 ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL);
2775 } else { /* no room so create dummy domain and NOS string */
2776 ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL);
2777 ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL);
2779 } else { /* ASCII */
2780 len = strnlen(bcc_ptr, 1024);
2781 if (((long) bcc_ptr + len) -
2782 (long) pByteArea(smb_buffer_response)
2783 <= BCC(smb_buffer_response)) {
2784 ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL);
2785 strncpy(ses->serverOS,bcc_ptr, len);
2788 bcc_ptr[0] = 0; /* null terminate the string */
2791 len = strnlen(bcc_ptr, 1024);
2792 ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL);
2793 strncpy(ses->serverNOS, bcc_ptr, len);
2798 len = strnlen(bcc_ptr, 1024);
2799 ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL);
2800 strncpy(ses->serverDomain, bcc_ptr, len);
2806 ("Variable field of length %d extends beyond end of smb ",
2811 (" Security Blob Length extends beyond end of SMB"));
2814 cERROR(1, ("No session structure passed in."));
2818 (" Invalid Word count %d: ",
2819 smb_buffer_response->WordCount));
2824 cifs_buf_release(smb_buffer);
2830 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2831 const char *tree, struct cifsTconInfo *tcon,
2832 const struct nls_table *nls_codepage)
2834 struct smb_hdr *smb_buffer;
2835 struct smb_hdr *smb_buffer_response;
2838 unsigned char *bcc_ptr;
2846 smb_buffer = cifs_buf_get();
2847 if (smb_buffer == NULL) {
2850 smb_buffer_response = smb_buffer;
2852 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2853 NULL /*no tid */ , 4 /*wct */ );
2854 smb_buffer->Uid = ses->Suid;
2855 pSMB = (TCONX_REQ *) smb_buffer;
2856 pSMBr = (TCONX_RSP *) smb_buffer_response;
2858 pSMB->AndXCommand = 0xFF;
2859 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2860 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2861 bcc_ptr = &pSMB->Password[0];
2862 bcc_ptr++; /* skip password */
2864 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2865 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2867 if (ses->capabilities & CAP_STATUS32) {
2868 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2870 if (ses->capabilities & CAP_DFS) {
2871 smb_buffer->Flags2 |= SMBFLG2_DFS;
2873 if (ses->capabilities & CAP_UNICODE) {
2874 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2876 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2877 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2878 bcc_ptr += 2; /* skip trailing null */
2879 } else { /* ASCII */
2881 strcpy(bcc_ptr, tree);
2882 bcc_ptr += strlen(tree) + 1;
2884 strcpy(bcc_ptr, "?????");
2885 bcc_ptr += strlen("?????");
2887 count = bcc_ptr - &pSMB->Password[0];
2888 pSMB->hdr.smb_buf_length += count;
2889 pSMB->ByteCount = cpu_to_le16(count);
2891 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2893 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2894 /* above now done in SendReceive */
2895 if ((rc == 0) && (tcon != NULL)) {
2896 tcon->tidStatus = CifsGood;
2897 tcon->tid = smb_buffer_response->Tid;
2898 bcc_ptr = pByteArea(smb_buffer_response);
2899 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2900 /* skip service field (NB: this field is always ASCII) */
2901 bcc_ptr += length + 1;
2902 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2903 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2904 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2905 if ((bcc_ptr + (2 * length)) -
2906 pByteArea(smb_buffer_response) <=
2907 BCC(smb_buffer_response)) {
2908 if(tcon->nativeFileSystem)
2909 kfree(tcon->nativeFileSystem);
2910 tcon->nativeFileSystem =
2911 cifs_kcalloc(length + 2, GFP_KERNEL);
2912 cifs_strfromUCS_le(tcon->nativeFileSystem,
2913 (wchar_t *) bcc_ptr,
2914 length, nls_codepage);
2915 bcc_ptr += 2 * length;
2916 bcc_ptr[0] = 0; /* null terminate the string */
2920 /* else do not bother copying these informational fields */
2922 length = strnlen(bcc_ptr, 1024);
2923 if ((bcc_ptr + length) -
2924 pByteArea(smb_buffer_response) <=
2925 BCC(smb_buffer_response)) {
2926 if(tcon->nativeFileSystem)
2927 kfree(tcon->nativeFileSystem);
2928 tcon->nativeFileSystem =
2929 cifs_kcalloc(length + 1, GFP_KERNEL);
2930 strncpy(tcon->nativeFileSystem, bcc_ptr,
2933 /* else do not bother copying these informational fields */
2935 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2936 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2937 } else if ((rc == 0) && tcon == NULL) {
2938 /* all we need to save for IPC$ connection */
2939 ses->ipc_tid = smb_buffer_response->Tid;
2943 cifs_buf_release(smb_buffer);
2948 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
2952 struct cifsSesInfo *ses = NULL;
2953 struct task_struct *cifsd_task;
2957 if (cifs_sb->tcon) {
2958 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
2959 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
2964 tconInfoFree(cifs_sb->tcon);
2965 if ((ses) && (ses->server)) {
2966 /* save off task so we do not refer to ses later */
2967 cifsd_task = ses->server->tsk;
2968 cFYI(1, ("About to do SMBLogoff "));
2969 rc = CIFSSMBLogoff(xid, ses);
2973 } else if (rc == -ESHUTDOWN) {
2974 cFYI(1,("Waking up socket by sending it signal"));
2976 send_sig(SIGKILL,cifsd_task,1);
2978 } /* else - we have an smb session
2979 left on this socket do not kill cifsd */
2981 cFYI(1, ("No session or bad tcon"));
2984 cifs_sb->tcon = NULL;
2986 set_current_state(TASK_INTERRUPTIBLE);
2987 schedule_timeout(HZ / 2);
2993 return rc; /* BB check if we should always return zero here */
2996 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
2997 struct nls_table * nls_info)
3000 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3001 int ntlmv2_flag = FALSE;
3004 /* what if server changes its buffer size after dropping the session? */
3005 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3006 rc = CIFSSMBNegotiate(xid, pSesInfo);
3007 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3008 rc = CIFSSMBNegotiate(xid, pSesInfo);
3013 spin_lock(&GlobalMid_Lock);
3014 if(pSesInfo->server->tcpStatus != CifsExiting)
3015 pSesInfo->server->tcpStatus = CifsGood;
3018 spin_unlock(&GlobalMid_Lock);
3024 pSesInfo->capabilities = pSesInfo->server->capabilities;
3025 if(linuxExtEnabled == 0)
3026 pSesInfo->capabilities &= (~CAP_UNIX);
3027 /* pSesInfo->sequence_number = 0;*/
3028 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3029 pSesInfo->server->secMode,
3030 pSesInfo->server->capabilities,
3031 pSesInfo->server->timeZone));
3032 if (extended_security
3033 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3034 && (pSesInfo->server->secType == NTLMSSP)) {
3035 cFYI(1, ("New style sesssetup "));
3036 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3037 NULL /* security blob */,
3038 0 /* blob length */,
3040 } else if (extended_security
3041 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3042 && (pSesInfo->server->secType == RawNTLMSSP)) {
3043 cFYI(1, ("NTLMSSP sesssetup "));
3044 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3051 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3052 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3057 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3059 CalcNTLMv2_response(pSesInfo,v2_response);
3061 cifs_calculate_ntlmv2_mac_key(
3062 pSesInfo->server->mac_signing_key,
3063 response, ntlm_session_key, */
3065 /* BB Put dummy sig in SessSetup PDU? */
3072 SMBNTencrypt(pSesInfo->password,
3073 pSesInfo->server->cryptKey,
3077 cifs_calculate_mac_key(
3078 pSesInfo->server->mac_signing_key,
3080 pSesInfo->password);
3082 /* for better security the weaker lanman hash not sent
3083 in AuthSessSetup so we no longer calculate it */
3085 rc = CIFSNTLMSSPAuthSessSetup(xid,
3091 } else { /* old style NTLM 0.12 session setup */
3092 SMBNTencrypt(pSesInfo->password,
3093 pSesInfo->server->cryptKey,
3097 cifs_calculate_mac_key(
3098 pSesInfo->server->mac_signing_key,
3099 ntlm_session_key, pSesInfo->password);
3101 rc = CIFSSessSetup(xid, pSesInfo,
3102 ntlm_session_key, nls_info);
3105 cERROR(1,("Send error in SessSetup = %d",rc));
3107 cFYI(1,("CIFS Session Established successfully"));
3108 pSesInfo->status = CifsGood;