4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/net.h>
23 #include <linux/string.h>
24 #include <linux/list.h>
25 #include <linux/wait.h>
26 #include <linux/ipv6.h>
27 #include <linux/pagemap.h>
28 #include <linux/ctype.h>
29 #include <linux/utsname.h>
30 #include <linux/mempool.h>
31 #include <linux/delay.h>
32 #include <asm/uaccess.h>
33 #include <asm/processor.h>
36 #include "cifsproto.h"
37 #include "cifs_unicode.h"
38 #include "cifs_debug.h"
39 #include "cifs_fs_sb.h"
42 #include "rfc1002pdu.h"
45 #define RFC1001_PORT 139
47 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
49 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
52 extern mempool_t *cifs_req_poolp;
60 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
61 char *iocharset; /* local code page for mapping to and from Unicode */
62 char source_rfc1001_name[16]; /* netbios name of client */
72 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
73 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
74 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
76 unsigned remap:1; /* set to remap seven reserved chars in filenames */
80 unsigned short int port;
83 static int ipv4_connect(struct sockaddr_in *psin_server,
84 struct socket **csocket,
86 static int ipv6_connect(struct sockaddr_in6 *psin_server,
87 struct socket **csocket);
91 * cifs tcp session reconnection
93 * mark tcp session as reconnecting so temporarily locked
94 * mark all smb sessions as reconnecting for tcp session
95 * reconnect tcp session
96 * wake up waiters on reconnection? - (not needed currently)
100 cifs_reconnect(struct TCP_Server_Info *server)
103 struct list_head *tmp;
104 struct cifsSesInfo *ses;
105 struct cifsTconInfo *tcon;
106 struct mid_q_entry * mid_entry;
108 spin_lock(&GlobalMid_Lock);
109 if(server->tcpStatus == CifsExiting) {
110 /* the demux thread will exit normally
111 next time through the loop */
112 spin_unlock(&GlobalMid_Lock);
115 server->tcpStatus = CifsNeedReconnect;
116 spin_unlock(&GlobalMid_Lock);
119 cFYI(1, ("Reconnecting tcp session "));
121 /* before reconnecting the tcp session, mark the smb session (uid)
122 and the tid bad so they are not used until reconnected */
123 read_lock(&GlobalSMBSeslock);
124 list_for_each(tmp, &GlobalSMBSessionList) {
125 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
127 if (ses->server == server) {
128 ses->status = CifsNeedReconnect;
132 /* else tcp and smb sessions need reconnection */
134 list_for_each(tmp, &GlobalTreeConnectionList) {
135 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
136 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
137 tcon->tidStatus = CifsNeedReconnect;
140 read_unlock(&GlobalSMBSeslock);
141 /* do not want to be sending data on a socket we are freeing */
142 down(&server->tcpSem);
143 if(server->ssocket) {
144 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
145 server->ssocket->flags));
146 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
147 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
148 server->ssocket->flags));
149 sock_release(server->ssocket);
150 server->ssocket = NULL;
153 spin_lock(&GlobalMid_Lock);
154 list_for_each(tmp, &server->pending_mid_q) {
155 mid_entry = list_entry(tmp, struct
159 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
160 /* Mark other intransit requests as needing
161 retry so we do not immediately mark the
162 session bad again (ie after we reconnect
163 below) as they timeout too */
164 mid_entry->midState = MID_RETRY_NEEDED;
168 spin_unlock(&GlobalMid_Lock);
171 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
173 if(server->protocolType == IPV6) {
174 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
176 rc = ipv4_connect(&server->addr.sockAddr,
178 server->workstation_RFC1001_name);
181 set_current_state(TASK_INTERRUPTIBLE);
182 schedule_timeout(3 * HZ);
184 atomic_inc(&tcpSesReconnectCount);
185 spin_lock(&GlobalMid_Lock);
186 if(server->tcpStatus != CifsExiting)
187 server->tcpStatus = CifsGood;
188 server->sequence_number = 0;
189 spin_unlock(&GlobalMid_Lock);
190 /* atomic_set(&server->inFlight,0);*/
191 wake_up(&server->response_q);
198 cifs_demultiplex_thread(struct TCP_Server_Info *server)
201 unsigned int pdu_length, total_read;
202 struct smb_hdr *smb_buffer = NULL;
203 struct smb_hdr *bigbuf = NULL;
204 struct smb_hdr *smallbuf = NULL;
205 struct msghdr smb_msg;
207 struct socket *csocket = server->ssocket;
208 struct list_head *tmp;
209 struct cifsSesInfo *ses;
210 struct task_struct *task_to_wake = NULL;
211 struct mid_q_entry *mid_entry;
213 int isLargeBuf = FALSE;
216 allow_signal(SIGKILL);
217 current->flags |= PF_MEMALLOC;
218 server->tsk = current; /* save process info to wake at shutdown */
219 cFYI(1, ("Demultiplex PID: %d", current->pid));
220 write_lock(&GlobalSMBSeslock);
221 atomic_inc(&tcpSesAllocCount);
222 length = tcpSesAllocCount.counter;
223 write_unlock(&GlobalSMBSeslock);
225 mempool_resize(cifs_req_poolp,
226 length + cifs_min_rcv,
230 while (server->tcpStatus != CifsExiting) {
231 if (bigbuf == NULL) {
232 bigbuf = cifs_buf_get();
234 cERROR(1,("No memory for large SMB response"));
236 /* retry will check if exiting */
239 } else if(isLargeBuf) {
240 /* we are reusing a dirtry large buf, clear its start */
241 memset(bigbuf, 0, sizeof (struct smb_hdr));
244 if (smallbuf == NULL) {
245 smallbuf = cifs_small_buf_get();
246 if(smallbuf == NULL) {
247 cERROR(1,("No memory for SMB response"));
249 /* retry will check if exiting */
252 /* beginning of smb buffer is cleared in our buf_get */
253 } else /* if existing small buf clear beginning */
254 memset(smallbuf, 0, sizeof (struct smb_hdr));
257 smb_buffer = smallbuf;
258 iov.iov_base = smb_buffer;
260 smb_msg.msg_control = NULL;
261 smb_msg.msg_controllen = 0;
263 kernel_recvmsg(csocket, &smb_msg,
264 &iov, 1, 4, 0 /* BB see socket.h flags */);
266 if(server->tcpStatus == CifsExiting) {
268 } else if (server->tcpStatus == CifsNeedReconnect) {
269 cFYI(1,("Reconnecting after server stopped responding"));
270 cifs_reconnect(server);
271 cFYI(1,("call to reconnect done"));
272 csocket = server->ssocket;
274 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
275 msleep(1); /* minimum sleep to prevent looping
276 allowing socket to clear and app threads to set
277 tcpStatus CifsNeedReconnect if server hung */
279 } else if (length <= 0) {
280 if(server->tcpStatus == CifsNew) {
281 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
282 /* some servers kill the TCP session rather than
283 returning an SMB negprot error, in which
284 case reconnecting here is not going to help,
285 and so simply return error to mount */
288 if(length == -EINTR) {
289 cFYI(1,("cifsd thread killed"));
292 cFYI(1,("Reconnecting after unexpected peek error %d",length));
293 cifs_reconnect(server);
294 csocket = server->ssocket;
295 wake_up(&server->response_q);
297 } else if (length < 4) {
299 ("Frame less than four bytes received %d bytes long.",
301 cifs_reconnect(server);
302 csocket = server->ssocket;
303 wake_up(&server->response_q);
307 /* the right amount was read from socket - 4 bytes */
309 pdu_length = ntohl(smb_buffer->smb_buf_length);
310 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
312 temp = (char *) smb_buffer;
313 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
314 cFYI(0,("Received 4 byte keep alive packet"));
315 } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
316 cFYI(1,("Good RFC 1002 session rsp"));
317 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
318 /* we get this from Windows 98 instead of
319 an error on SMB negprot response */
320 cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4]));
321 if(server->tcpStatus == CifsNew) {
322 /* if nack on negprot (rather than
323 ret of smb negprot error) reconnecting
324 not going to help, ret error to mount */
327 /* give server a second to
328 clean up before reconnect attempt */
330 /* always try 445 first on reconnect
331 since we get NACK on some if we ever
332 connected to port 139 (the NACK is
333 since we do not begin with RFC1001
334 session initialize frame) */
335 server->addr.sockAddr.sin_port =
337 cifs_reconnect(server);
338 csocket = server->ssocket;
339 wake_up(&server->response_q);
342 } else if (temp[0] != (char) 0) {
343 cERROR(1,("Unknown RFC 1002 frame"));
344 cifs_dump_mem(" Received Data: ", temp, length);
345 cifs_reconnect(server);
346 csocket = server->ssocket;
348 } else { /* we have an SMB response */
349 if((pdu_length > CIFSMaxBufSize +
350 MAX_CIFS_HDR_SIZE - 4) ||
351 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
353 ("Invalid size SMB length %d and pdu_length %d",
354 length, pdu_length+4));
355 cifs_reconnect(server);
356 csocket = server->ssocket;
357 wake_up(&server->response_q);
359 } else { /* length ok */
362 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
364 memcpy(bigbuf, smallbuf, 4);
368 iov.iov_base = 4 + (char *)smb_buffer;
369 iov.iov_len = pdu_length;
371 total_read < pdu_length;
372 total_read += length) {
373 length = kernel_recvmsg(csocket, &smb_msg,
375 pdu_length - total_read, 0);
376 if((server->tcpStatus == CifsExiting) ||
377 (length == -EINTR)) {
381 } else if (server->tcpStatus ==
383 cifs_reconnect(server);
384 csocket = server->ssocket;
385 /* Reconnect wakes up rspns q */
386 /* Now we will reread sock */
389 } else if ((length == -ERESTARTSYS) ||
390 (length == -EAGAIN)) {
391 msleep(1); /* minimum sleep to prevent looping
392 allowing socket to clear and app threads to set
393 tcpStatus CifsNeedReconnect if server hung */
395 } else if (length <= 0) {
396 cERROR(1,("Received no data, expecting %d",
397 pdu_length - total_read));
398 cifs_reconnect(server);
399 csocket = server->ssocket;
406 else if(reconnect == 1)
409 length += 4; /* account for rfc1002 hdr */
412 dump_smb(smb_buffer, length);
414 (smb_buffer, smb_buffer->Mid, total_read+4)) {
415 cERROR(1, ("Bad SMB Received "));
421 spin_lock(&GlobalMid_Lock);
422 list_for_each(tmp, &server->pending_mid_q) {
423 mid_entry = list_entry(tmp, struct mid_q_entry,
426 if ((mid_entry->mid == smb_buffer->Mid)
427 && (mid_entry->midState ==
428 MID_REQUEST_SUBMITTED)
429 && (mid_entry->command ==
430 smb_buffer->Command)) {
431 cFYI(1,("Found Mid 0x%x wake up"
433 /* BB FIXME - missing code here BB */
434 /* check_2nd_t2(smb_buffer); */
435 task_to_wake = mid_entry->tsk;
436 mid_entry->resp_buf =
438 mid_entry->midState =
439 MID_RESPONSE_RECEIVED;
441 mid_entry->largeBuf = 1;
443 mid_entry->largeBuf = 0;
446 spin_unlock(&GlobalMid_Lock);
452 smb_buffer = NULL; /* will be freed by users thread after he is done */
453 wake_up_process(task_to_wake);
454 } else if (is_valid_oplock_break(smb_buffer) == FALSE) {
455 cERROR(1, ("No task to wake, unknown frame rcvd!"));
456 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
460 spin_lock(&GlobalMid_Lock);
461 server->tcpStatus = CifsExiting;
463 atomic_set(&server->inFlight, 0);
464 spin_unlock(&GlobalMid_Lock);
465 /* Although there should not be any requests blocked on
466 this queue it can not hurt to be paranoid and try to wake up requests
467 that may haven been blocked when more than 50 at time were on the wire
468 to the same server - they now will see the session is in exit state
469 and get out of SendReceive. */
470 wake_up_all(&server->request_q);
471 /* give those requests time to exit */
474 if(server->ssocket) {
475 sock_release(csocket);
476 server->ssocket = NULL;
478 /* buffer usuallly freed in free_mid - need to free it here on exit */
480 cifs_buf_release(bigbuf);
481 if (smallbuf != NULL)
482 cifs_small_buf_release(smallbuf);
484 read_lock(&GlobalSMBSeslock);
485 if (list_empty(&server->pending_mid_q)) {
486 /* loop through server session structures attached to this and
488 list_for_each(tmp, &GlobalSMBSessionList) {
490 list_entry(tmp, struct cifsSesInfo,
492 if (ses->server == server) {
493 ses->status = CifsExiting;
497 read_unlock(&GlobalSMBSeslock);
499 spin_lock(&GlobalMid_Lock);
500 list_for_each(tmp, &server->pending_mid_q) {
501 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
502 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
504 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
505 task_to_wake = mid_entry->tsk;
507 wake_up_process(task_to_wake);
511 spin_unlock(&GlobalMid_Lock);
512 read_unlock(&GlobalSMBSeslock);
513 /* 1/8th of sec is more than enough time for them to exit */
517 if (list_empty(&server->pending_mid_q)) {
518 /* mpx threads have not exited yet give them
519 at least the smb send timeout time for long ops */
520 cFYI(1, ("Wait for exit from demultiplex thread"));
522 /* if threads still have not exited they are probably never
523 coming home not much else we can do but free the memory */
527 write_lock(&GlobalSMBSeslock);
528 atomic_dec(&tcpSesAllocCount);
529 length = tcpSesAllocCount.counter;
530 write_unlock(&GlobalSMBSeslock);
532 mempool_resize(cifs_req_poolp,
533 length + cifs_min_rcv,
542 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
546 unsigned int temp_len, i, j;
552 memset(vol->source_rfc1001_name,0x20,15);
553 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
554 /* does not have to be a perfect mapping since the field is
555 informational, only used for servers that do not support
556 port 445 and it can be overridden at mount time */
557 vol->source_rfc1001_name[i] =
558 toupper(system_utsname.nodename[i]);
560 vol->source_rfc1001_name[15] = 0;
562 vol->linux_uid = current->uid; /* current->euid instead? */
563 vol->linux_gid = current->gid;
564 vol->dir_mode = S_IRWXUGO;
565 /* 2767 perms indicate mandatory locking support */
566 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
568 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
574 if(strncmp(options,"sep=",4) == 0) {
575 if(options[4] != 0) {
576 separator[0] = options[4];
579 cFYI(1,("Null separator not allowed"));
583 while ((data = strsep(&options, separator)) != NULL) {
586 if ((value = strchr(data, '=')) != NULL)
589 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
591 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
593 } else if (strnicmp(data, "user", 4) == 0) {
594 if (!value || !*value) {
596 "CIFS: invalid or missing username\n");
597 return 1; /* needs_arg; */
599 if (strnlen(value, 200) < 200) {
600 vol->username = value;
602 printk(KERN_WARNING "CIFS: username too long\n");
605 } else if (strnicmp(data, "pass", 4) == 0) {
607 vol->password = NULL;
609 } else if(value[0] == 0) {
610 /* check if string begins with double comma
611 since that would mean the password really
612 does start with a comma, and would not
613 indicate an empty string */
614 if(value[1] != separator[0]) {
615 vol->password = NULL;
619 temp_len = strlen(value);
620 /* removed password length check, NTLM passwords
621 can be arbitrarily long */
623 /* if comma in password, the string will be
624 prematurely null terminated. Commas in password are
625 specified across the cifs mount interface by a double
626 comma ie ,, and a comma used as in other cases ie ','
627 as a parameter delimiter/separator is single and due
628 to the strsep above is temporarily zeroed. */
630 /* NB: password legally can have multiple commas and
631 the only illegal character in a password is null */
633 if ((value[temp_len] == 0) &&
634 (value[temp_len+1] == separator[0])) {
636 value[temp_len] = separator[0];
637 temp_len+=2; /* move after the second comma */
638 while(value[temp_len] != 0) {
639 if (value[temp_len] == separator[0]) {
640 if (value[temp_len+1] ==
642 /* skip second comma */
645 /* single comma indicating start
652 if(value[temp_len] == 0) {
656 /* point option to start of next parm */
657 options = value + temp_len + 1;
659 /* go from value to value + temp_len condensing
660 double commas to singles. Note that this ends up
661 allocating a few bytes too many, which is ok */
662 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
663 if(vol->password == NULL) {
664 printk("CIFS: no memory for pass\n");
667 for(i=0,j=0;i<temp_len;i++,j++) {
668 vol->password[j] = value[i];
669 if(value[i] == separator[0]
670 && value[i+1] == separator[0]) {
671 /* skip second comma */
675 vol->password[j] = 0;
677 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
678 if(vol->password == NULL) {
679 printk("CIFS: no memory for pass\n");
682 strcpy(vol->password, value);
684 } else if (strnicmp(data, "ip", 2) == 0) {
685 if (!value || !*value) {
687 } else if (strnlen(value, 35) < 35) {
690 printk(KERN_WARNING "CIFS: ip address too long\n");
693 } else if ((strnicmp(data, "unc", 3) == 0)
694 || (strnicmp(data, "target", 6) == 0)
695 || (strnicmp(data, "path", 4) == 0)) {
696 if (!value || !*value) {
698 "CIFS: invalid path to network resource\n");
699 return 1; /* needs_arg; */
701 if ((temp_len = strnlen(value, 300)) < 300) {
702 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
705 strcpy(vol->UNC,value);
706 if (strncmp(vol->UNC, "//", 2) == 0) {
709 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
711 "CIFS: UNC Path does not begin with // or \\\\ \n");
715 printk(KERN_WARNING "CIFS: UNC name too long\n");
718 } else if ((strnicmp(data, "domain", 3) == 0)
719 || (strnicmp(data, "workgroup", 5) == 0)) {
720 if (!value || !*value) {
721 printk(KERN_WARNING "CIFS: invalid domain name\n");
722 return 1; /* needs_arg; */
724 /* BB are there cases in which a comma can be valid in
725 a domain name and need special handling? */
726 if (strnlen(value, 65) < 65) {
727 vol->domainname = value;
728 cFYI(1, ("Domain name set"));
730 printk(KERN_WARNING "CIFS: domain name too long\n");
733 } else if (strnicmp(data, "iocharset", 9) == 0) {
734 if (!value || !*value) {
735 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
736 return 1; /* needs_arg; */
738 if (strnlen(value, 65) < 65) {
739 if(strnicmp(value,"default",7))
740 vol->iocharset = value;
741 /* if iocharset not set load_nls_default used by caller */
742 cFYI(1, ("iocharset set to %s",value));
744 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
747 } else if (strnicmp(data, "uid", 3) == 0) {
748 if (value && *value) {
750 simple_strtoul(value, &value, 0);
752 } else if (strnicmp(data, "gid", 3) == 0) {
753 if (value && *value) {
755 simple_strtoul(value, &value, 0);
757 } else if (strnicmp(data, "file_mode", 4) == 0) {
758 if (value && *value) {
760 simple_strtoul(value, &value, 0);
762 } else if (strnicmp(data, "dir_mode", 4) == 0) {
763 if (value && *value) {
765 simple_strtoul(value, &value, 0);
767 } else if (strnicmp(data, "dirmode", 4) == 0) {
768 if (value && *value) {
770 simple_strtoul(value, &value, 0);
772 } else if (strnicmp(data, "port", 4) == 0) {
773 if (value && *value) {
775 simple_strtoul(value, &value, 0);
777 } else if (strnicmp(data, "rsize", 5) == 0) {
778 if (value && *value) {
780 simple_strtoul(value, &value, 0);
782 } else if (strnicmp(data, "wsize", 5) == 0) {
783 if (value && *value) {
785 simple_strtoul(value, &value, 0);
787 } else if (strnicmp(data, "sockopt", 5) == 0) {
788 if (value && *value) {
790 simple_strtoul(value, &value, 0);
792 } else if (strnicmp(data, "netbiosname", 4) == 0) {
793 if (!value || !*value || (*value == ' ')) {
794 cFYI(1,("invalid (empty) netbiosname specified"));
796 memset(vol->source_rfc1001_name,0x20,15);
798 /* BB are there cases in which a comma can be
799 valid in this workstation netbios name (and need
800 special handling)? */
802 /* We do not uppercase netbiosname for user */
806 vol->source_rfc1001_name[i] = value[i];
808 /* The string has 16th byte zero still from
809 set at top of the function */
810 if((i==15) && (value[i] != 0))
811 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
813 } else if (strnicmp(data, "credentials", 4) == 0) {
815 } else if (strnicmp(data, "version", 3) == 0) {
817 } else if (strnicmp(data, "guest",5) == 0) {
819 } else if (strnicmp(data, "rw", 2) == 0) {
821 } else if ((strnicmp(data, "suid", 4) == 0) ||
822 (strnicmp(data, "nosuid", 6) == 0) ||
823 (strnicmp(data, "exec", 4) == 0) ||
824 (strnicmp(data, "noexec", 6) == 0) ||
825 (strnicmp(data, "nodev", 5) == 0) ||
826 (strnicmp(data, "noauto", 6) == 0) ||
827 (strnicmp(data, "dev", 3) == 0)) {
828 /* The mount tool or mount.cifs helper (if present)
829 uses these opts to set flags, and the flags are read
830 by the kernel vfs layer before we get here (ie
831 before read super) so there is no point trying to
832 parse these options again and set anything and it
833 is ok to just ignore them */
835 } else if (strnicmp(data, "ro", 2) == 0) {
837 } else if (strnicmp(data, "hard", 4) == 0) {
839 } else if (strnicmp(data, "soft", 4) == 0) {
841 } else if (strnicmp(data, "perm", 4) == 0) {
843 } else if (strnicmp(data, "noperm", 6) == 0) {
845 } else if (strnicmp(data, "mapchars", 8) == 0) {
847 } else if (strnicmp(data, "nomapchars", 10) == 0) {
849 } else if (strnicmp(data, "setuids", 7) == 0) {
851 } else if (strnicmp(data, "nosetuids", 9) == 0) {
853 } else if (strnicmp(data, "nohard", 6) == 0) {
855 } else if (strnicmp(data, "nosoft", 6) == 0) {
857 } else if (strnicmp(data, "nointr", 6) == 0) {
859 } else if (strnicmp(data, "intr", 4) == 0) {
861 } else if (strnicmp(data, "serverino",7) == 0) {
863 } else if (strnicmp(data, "noserverino",9) == 0) {
865 } else if (strnicmp(data, "acl",3) == 0) {
867 } else if (strnicmp(data, "noacl",5) == 0) {
869 } else if (strnicmp(data, "direct",6) == 0) {
871 } else if (strnicmp(data, "forcedirectio",13) == 0) {
873 } else if (strnicmp(data, "in6_addr",8) == 0) {
874 if (!value || !*value) {
875 vol->in6_addr = NULL;
876 } else if (strnlen(value, 49) == 48) {
877 vol->in6_addr = value;
879 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
882 } else if (strnicmp(data, "noac", 4) == 0) {
883 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
885 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
887 if (vol->UNC == NULL) {
888 if(devname == NULL) {
889 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
892 if ((temp_len = strnlen(devname, 300)) < 300) {
893 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
896 strcpy(vol->UNC,devname);
897 if (strncmp(vol->UNC, "//", 2) == 0) {
900 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
901 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
905 printk(KERN_WARNING "CIFS: UNC name too long\n");
909 if(vol->UNCip == NULL)
910 vol->UNCip = &vol->UNC[2];
915 static struct cifsSesInfo *
916 cifs_find_tcp_session(struct in_addr * target_ip_addr,
917 struct in6_addr *target_ip6_addr,
918 char *userName, struct TCP_Server_Info **psrvTcp)
920 struct list_head *tmp;
921 struct cifsSesInfo *ses;
923 read_lock(&GlobalSMBSeslock);
925 list_for_each(tmp, &GlobalSMBSessionList) {
926 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
928 if((target_ip_addr &&
929 (ses->server->addr.sockAddr.sin_addr.s_addr
930 == target_ip_addr->s_addr)) || (target_ip6_addr
931 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
932 target_ip6_addr,sizeof(*target_ip6_addr)))){
933 /* BB lock server and tcp session and increment use count here?? */
934 *psrvTcp = ses->server; /* found a match on the TCP session */
935 /* BB check if reconnection needed */
937 (ses->userName, userName,
938 MAX_USERNAME_SIZE) == 0){
939 read_unlock(&GlobalSMBSeslock);
940 return ses; /* found exact match on both tcp and SMB sessions */
944 /* else tcp and smb sessions need reconnection */
946 read_unlock(&GlobalSMBSeslock);
950 static struct cifsTconInfo *
951 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
953 struct list_head *tmp;
954 struct cifsTconInfo *tcon;
956 read_lock(&GlobalSMBSeslock);
957 list_for_each(tmp, &GlobalTreeConnectionList) {
958 cFYI(1, ("Next tcon - "));
959 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
961 if (tcon->ses->server) {
963 (" old ip addr: %x == new ip %x ?",
964 tcon->ses->server->addr.sockAddr.sin_addr.
965 s_addr, new_target_ip_addr));
966 if (tcon->ses->server->addr.sockAddr.sin_addr.
967 s_addr == new_target_ip_addr) {
968 /* BB lock tcon and server and tcp session and increment use count here? */
969 /* found a match on the TCP session */
970 /* BB check if reconnection needed */
971 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
972 tcon->treeName, uncName));
974 (tcon->treeName, uncName,
975 MAX_TREE_SIZE) == 0) {
977 ("Matched UNC, old user: %s == new: %s ?",
978 tcon->treeName, uncName));
980 (tcon->ses->userName,
982 MAX_USERNAME_SIZE) == 0) {
983 read_unlock(&GlobalSMBSeslock);
984 return tcon;/* also matched user (smb session)*/
991 read_unlock(&GlobalSMBSeslock);
996 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
997 const char *old_path, const struct nls_table *nls_codepage,
1000 unsigned char *referrals = NULL;
1001 unsigned int num_referrals;
1004 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1005 &num_referrals, &referrals, remap);
1007 /* BB Add in code to: if valid refrl, if not ip address contact
1008 the helper that resolves tcp names, mount to it, try to
1009 tcon to it unmount it if fail */
1018 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1019 const char *old_path, const struct nls_table *nls_codepage,
1020 unsigned int *pnum_referrals,
1021 unsigned char ** preferrals, int remap)
1026 *pnum_referrals = 0;
1028 if (pSesInfo->ipc_tid == 0) {
1029 temp_unc = kmalloc(2 /* for slashes */ +
1030 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1031 + 1 + 4 /* slash IPC$ */ + 2,
1033 if (temp_unc == NULL)
1037 strcpy(temp_unc + 2, pSesInfo->serverName);
1038 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1039 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1041 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1045 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1046 pnum_referrals, nls_codepage, remap);
1051 /* See RFC1001 section 14 on representation of Netbios names */
1052 static void rfc1002mangle(char * target,char * source, unsigned int length)
1056 for(i=0,j=0;i<(length);i++) {
1057 /* mask a nibble at a time and encode */
1058 target[j] = 'A' + (0x0F & (source[i] >> 4));
1059 target[j+1] = 'A' + (0x0F & source[i]);
1067 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1068 char * netbios_name)
1072 __be16 orig_port = 0;
1074 if(*csocket == NULL) {
1075 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1077 cERROR(1, ("Error %d creating socket",rc));
1081 /* BB other socket options to set KEEPALIVE, NODELAY? */
1082 cFYI(1,("Socket created"));
1083 (*csocket)->sk->sk_allocation = GFP_NOFS;
1087 psin_server->sin_family = AF_INET;
1088 if(psin_server->sin_port) { /* user overrode default port */
1089 rc = (*csocket)->ops->connect(*csocket,
1090 (struct sockaddr *) psin_server,
1091 sizeof (struct sockaddr_in),0);
1097 /* save original port so we can retry user specified port
1098 later if fall back ports fail this time */
1099 orig_port = psin_server->sin_port;
1101 /* do not retry on the same port we just failed on */
1102 if(psin_server->sin_port != htons(CIFS_PORT)) {
1103 psin_server->sin_port = htons(CIFS_PORT);
1105 rc = (*csocket)->ops->connect(*csocket,
1106 (struct sockaddr *) psin_server,
1107 sizeof (struct sockaddr_in),0);
1113 psin_server->sin_port = htons(RFC1001_PORT);
1114 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1115 psin_server, sizeof (struct sockaddr_in),0);
1120 /* give up here - unless we want to retry on different
1121 protocol families some day */
1124 psin_server->sin_port = orig_port;
1125 cFYI(1,("Error %d connecting to server via ipv4",rc));
1126 sock_release(*csocket);
1130 /* Eventually check for other socket options to change from
1131 the default. sock_setsockopt not used because it expects
1132 user space buffer */
1133 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1135 /* send RFC1001 sessinit */
1137 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1138 /* some servers require RFC1001 sessinit before sending
1139 negprot - BB check reconnection in case where second
1140 sessinit is sent but no second negprot */
1141 struct rfc1002_session_packet * ses_init_buf;
1142 struct smb_hdr * smb_buf;
1143 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1145 ses_init_buf->trailer.session_req.called_len = 32;
1146 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1147 DEFAULT_CIFS_CALLED_NAME,16);
1148 ses_init_buf->trailer.session_req.calling_len = 32;
1149 /* calling name ends in null (byte 16) from old smb
1151 if(netbios_name && (netbios_name[0] !=0)) {
1152 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1155 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1156 "LINUX_CIFS_CLNT",16);
1158 ses_init_buf->trailer.session_req.scope1 = 0;
1159 ses_init_buf->trailer.session_req.scope2 = 0;
1160 smb_buf = (struct smb_hdr *)ses_init_buf;
1161 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1162 smb_buf->smb_buf_length = 0x81000044;
1163 rc = smb_send(*csocket, smb_buf, 0x44,
1164 (struct sockaddr *)psin_server);
1165 kfree(ses_init_buf);
1167 /* else the negprot may still work without this
1168 even though malloc failed */
1176 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1180 __be16 orig_port = 0;
1182 if(*csocket == NULL) {
1183 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1185 cERROR(1, ("Error %d creating ipv6 socket",rc));
1189 /* BB other socket options to set KEEPALIVE, NODELAY? */
1190 cFYI(1,("ipv6 Socket created"));
1191 (*csocket)->sk->sk_allocation = GFP_NOFS;
1195 psin_server->sin6_family = AF_INET6;
1197 if(psin_server->sin6_port) { /* user overrode default port */
1198 rc = (*csocket)->ops->connect(*csocket,
1199 (struct sockaddr *) psin_server,
1200 sizeof (struct sockaddr_in6),0);
1206 /* save original port so we can retry user specified port
1207 later if fall back ports fail this time */
1209 orig_port = psin_server->sin6_port;
1210 /* do not retry on the same port we just failed on */
1211 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1212 psin_server->sin6_port = htons(CIFS_PORT);
1214 rc = (*csocket)->ops->connect(*csocket,
1215 (struct sockaddr *) psin_server,
1216 sizeof (struct sockaddr_in6),0);
1222 psin_server->sin6_port = htons(RFC1001_PORT);
1223 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1224 psin_server, sizeof (struct sockaddr_in6),0);
1229 /* give up here - unless we want to retry on different
1230 protocol families some day */
1233 psin_server->sin6_port = orig_port;
1234 cFYI(1,("Error %d connecting to server via ipv6",rc));
1235 sock_release(*csocket);
1239 /* Eventually check for other socket options to change from
1240 the default. sock_setsockopt not used because it expects
1241 user space buffer */
1242 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1248 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1249 char *mount_data, const char *devname)
1253 int address_type = AF_INET;
1254 struct socket *csocket = NULL;
1255 struct sockaddr_in sin_server;
1256 struct sockaddr_in6 sin_server6;
1257 struct smb_vol volume_info;
1258 struct cifsSesInfo *pSesInfo = NULL;
1259 struct cifsSesInfo *existingCifsSes = NULL;
1260 struct cifsTconInfo *tcon = NULL;
1261 struct TCP_Server_Info *srvTcp = NULL;
1265 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1267 memset(&volume_info,0,sizeof(struct smb_vol));
1268 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1270 kfree(volume_info.UNC);
1271 if(volume_info.password)
1272 kfree(volume_info.password);
1277 if (volume_info.username) {
1278 /* BB fixme parse for domain name here */
1279 cFYI(1, ("Username: %s ", volume_info.username));
1282 cifserror("No username specified ");
1283 /* In userspace mount helper we can get user name from alternate
1284 locations such as env variables and files on disk */
1286 kfree(volume_info.UNC);
1287 if(volume_info.password)
1288 kfree(volume_info.password);
1293 if (volume_info.UNCip && volume_info.UNC) {
1294 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1297 /* not ipv4 address, try ipv6 */
1298 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1300 address_type = AF_INET6;
1302 address_type = AF_INET;
1306 /* we failed translating address */
1308 kfree(volume_info.UNC);
1309 if(volume_info.password)
1310 kfree(volume_info.password);
1315 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1318 } else if (volume_info.UNCip){
1319 /* BB using ip addr as server name connect to the DFS root below */
1320 cERROR(1,("Connecting to DFS root not implemented yet"));
1322 kfree(volume_info.UNC);
1323 if(volume_info.password)
1324 kfree(volume_info.password);
1327 } else /* which servers DFS root would we conect to */ {
1329 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1331 kfree(volume_info.UNC);
1332 if(volume_info.password)
1333 kfree(volume_info.password);
1338 /* this is needed for ASCII cp to Unicode converts */
1339 if(volume_info.iocharset == NULL) {
1340 cifs_sb->local_nls = load_nls_default();
1341 /* load_nls_default can not return null */
1343 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1344 if(cifs_sb->local_nls == NULL) {
1345 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1347 kfree(volume_info.UNC);
1348 if(volume_info.password)
1349 kfree(volume_info.password);
1355 if(address_type == AF_INET)
1356 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1357 NULL /* no ipv6 addr */,
1358 volume_info.username, &srvTcp);
1359 else if(address_type == AF_INET6)
1360 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1361 &sin_server6.sin6_addr,
1362 volume_info.username, &srvTcp);
1365 kfree(volume_info.UNC);
1366 if(volume_info.password)
1367 kfree(volume_info.password);
1374 cFYI(1, ("Existing tcp session with server found "));
1375 } else { /* create socket */
1376 if(volume_info.port)
1377 sin_server.sin_port = htons(volume_info.port);
1379 sin_server.sin_port = 0;
1380 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1383 ("Error connecting to IPv4 socket. Aborting operation"));
1385 sock_release(csocket);
1387 kfree(volume_info.UNC);
1388 if(volume_info.password)
1389 kfree(volume_info.password);
1394 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1395 if (srvTcp == NULL) {
1397 sock_release(csocket);
1399 kfree(volume_info.UNC);
1400 if(volume_info.password)
1401 kfree(volume_info.password);
1405 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1406 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1407 atomic_set(&srvTcp->inFlight,0);
1408 /* BB Add code for ipv6 case too */
1409 srvTcp->ssocket = csocket;
1410 srvTcp->protocolType = IPV4;
1411 init_waitqueue_head(&srvTcp->response_q);
1412 init_waitqueue_head(&srvTcp->request_q);
1413 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1414 /* at this point we are the only ones with the pointer
1415 to the struct since the kernel thread not created yet
1416 so no need to spinlock this init of tcpStatus */
1417 srvTcp->tcpStatus = CifsNew;
1418 init_MUTEX(&srvTcp->tcpSem);
1419 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1420 CLONE_FS | CLONE_FILES | CLONE_VM);
1423 sock_release(csocket);
1425 kfree(volume_info.UNC);
1426 if(volume_info.password)
1427 kfree(volume_info.password);
1432 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1433 srvTcp->sequence_number = 0;
1437 if (existingCifsSes) {
1438 pSesInfo = existingCifsSes;
1439 cFYI(1, ("Existing smb sess found "));
1440 if(volume_info.password)
1441 kfree(volume_info.password);
1442 /* volume_info.UNC freed at end of function */
1444 cFYI(1, ("Existing smb sess not found "));
1445 pSesInfo = sesInfoAlloc();
1446 if (pSesInfo == NULL)
1449 pSesInfo->server = srvTcp;
1450 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1451 NIPQUAD(sin_server.sin_addr.s_addr));
1455 /* volume_info.password freed at unmount */
1456 if (volume_info.password)
1457 pSesInfo->password = volume_info.password;
1458 if (volume_info.username)
1459 strncpy(pSesInfo->userName,
1460 volume_info.username,MAX_USERNAME_SIZE);
1461 if (volume_info.domainname)
1462 strncpy(pSesInfo->domainName,
1463 volume_info.domainname,MAX_USERNAME_SIZE);
1464 pSesInfo->linux_uid = volume_info.linux_uid;
1465 down(&pSesInfo->sesSem);
1466 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1467 up(&pSesInfo->sesSem);
1469 atomic_inc(&srvTcp->socketUseCount);
1471 if(volume_info.password)
1472 kfree(volume_info.password);
1475 /* search for existing tcon to this server share */
1477 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1478 cifs_sb->rsize = volume_info.rsize;
1480 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1481 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1482 cifs_sb->wsize = volume_info.wsize;
1484 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1485 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1486 cifs_sb->rsize = PAGE_CACHE_SIZE;
1487 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1489 cifs_sb->mnt_uid = volume_info.linux_uid;
1490 cifs_sb->mnt_gid = volume_info.linux_gid;
1491 cifs_sb->mnt_file_mode = volume_info.file_mode;
1492 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1493 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1495 if(volume_info.noperm)
1496 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1497 if(volume_info.setuids)
1498 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1499 if(volume_info.server_ino)
1500 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1501 if(volume_info.remap)
1502 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1503 if(volume_info.no_xattr)
1504 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1505 if(volume_info.direct_io) {
1506 cERROR(1,("mounting share using direct i/o"));
1507 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1511 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1512 volume_info.username);
1514 cFYI(1, ("Found match on UNC path "));
1515 /* we can have only one retry value for a connection
1516 to a share so for resources mounted more than once
1517 to the same server share the last value passed in
1518 for the retry flag is used */
1519 tcon->retry = volume_info.retry;
1521 tcon = tconInfoAlloc();
1525 /* check for null share name ie connect to dfs root */
1527 /* BB check if this works for exactly length three strings */
1528 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1529 && (strchr(volume_info.UNC + 3, '/') ==
1531 rc = connect_to_dfs_path(xid, pSesInfo,
1532 "", cifs_sb->local_nls,
1533 cifs_sb->mnt_cifs_flags &
1534 CIFS_MOUNT_MAP_SPECIAL_CHR);
1536 kfree(volume_info.UNC);
1540 rc = CIFSTCon(xid, pSesInfo,
1542 tcon, cifs_sb->local_nls);
1543 cFYI(1, ("CIFS Tcon rc = %d", rc));
1546 atomic_inc(&pSesInfo->inUse);
1547 tcon->retry = volume_info.retry;
1553 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1554 sb->s_maxbytes = (u64) 1 << 63;
1556 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1559 sb->s_time_gran = 100;
1561 /* on error free sesinfo and tcon struct if needed */
1563 /* if session setup failed, use count is zero but
1564 we still need to free cifsd thread */
1565 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1566 spin_lock(&GlobalMid_Lock);
1567 srvTcp->tcpStatus = CifsExiting;
1568 spin_unlock(&GlobalMid_Lock);
1570 send_sig(SIGKILL,srvTcp->tsk,1);
1572 /* If find_unc succeeded then rc == 0 so we can not end */
1573 if (tcon) /* up accidently freeing someone elses tcon struct */
1575 if (existingCifsSes == NULL) {
1577 if ((pSesInfo->server) &&
1578 (pSesInfo->status == CifsGood)) {
1580 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1581 /* if the socketUseCount is now zero */
1582 if((temp_rc == -ESHUTDOWN) &&
1583 (pSesInfo->server->tsk))
1584 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1586 cFYI(1, ("No session or bad tcon"));
1587 sesInfoFree(pSesInfo);
1588 /* pSesInfo = NULL; */
1592 atomic_inc(&tcon->useCount);
1593 cifs_sb->tcon = tcon;
1594 tcon->ses = pSesInfo;
1596 /* do not care if following two calls succeed - informational only */
1597 CIFSSMBQFSDeviceInfo(xid, tcon);
1598 CIFSSMBQFSAttributeInfo(xid, tcon);
1599 if (tcon->ses->capabilities & CAP_UNIX) {
1600 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1601 if(!volume_info.no_psx_acl) {
1602 if(CIFS_UNIX_POSIX_ACL_CAP &
1603 le64_to_cpu(tcon->fsUnixInfo.Capability))
1604 cFYI(1,("server negotiated posix acl support"));
1605 sb->s_flags |= MS_POSIXACL;
1611 /* volume_info.password is freed above when existing session found
1612 (in which case it is not needed anymore) but when new sesion is created
1613 the password ptr is put in the new session structure (in which case the
1614 password will be freed at unmount time) */
1616 kfree(volume_info.UNC);
1622 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1623 char session_key[CIFS_SESSION_KEY_SIZE],
1624 const struct nls_table *nls_codepage)
1626 struct smb_hdr *smb_buffer;
1627 struct smb_hdr *smb_buffer_response;
1628 SESSION_SETUP_ANDX *pSMB;
1629 SESSION_SETUP_ANDX *pSMBr;
1634 int remaining_words = 0;
1635 int bytes_returned = 0;
1640 cFYI(1, ("In sesssetup "));
1643 user = ses->userName;
1644 domain = ses->domainName;
1645 smb_buffer = cifs_buf_get();
1646 if (smb_buffer == NULL) {
1649 smb_buffer_response = smb_buffer;
1650 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1652 /* send SMBsessionSetup here */
1653 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1654 NULL /* no tCon exists yet */ , 13 /* wct */ );
1656 pSMB->req_no_secext.AndXCommand = 0xFF;
1657 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1658 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1660 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1661 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1663 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1664 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1665 if (ses->capabilities & CAP_UNICODE) {
1666 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1667 capabilities |= CAP_UNICODE;
1669 if (ses->capabilities & CAP_STATUS32) {
1670 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1671 capabilities |= CAP_STATUS32;
1673 if (ses->capabilities & CAP_DFS) {
1674 smb_buffer->Flags2 |= SMBFLG2_DFS;
1675 capabilities |= CAP_DFS;
1677 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1679 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1680 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1682 pSMB->req_no_secext.CaseSensitivePasswordLength =
1683 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1684 bcc_ptr = pByteArea(smb_buffer);
1685 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1686 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1687 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1688 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1690 if (ses->capabilities & CAP_UNICODE) {
1691 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1696 bytes_returned = 0; /* skill null user */
1699 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1701 /* convert number of 16 bit words to bytes */
1702 bcc_ptr += 2 * bytes_returned;
1703 bcc_ptr += 2; /* trailing null */
1706 cifs_strtoUCS((wchar_t *) bcc_ptr,
1707 "CIFS_LINUX_DOM", 32, nls_codepage);
1710 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1712 bcc_ptr += 2 * bytes_returned;
1715 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1717 bcc_ptr += 2 * bytes_returned;
1719 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1721 bcc_ptr += 2 * bytes_returned;
1724 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1726 bcc_ptr += 2 * bytes_returned;
1730 strncpy(bcc_ptr, user, 200);
1731 bcc_ptr += strnlen(user, 200);
1735 if (domain == NULL) {
1736 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1737 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1739 strncpy(bcc_ptr, domain, 64);
1740 bcc_ptr += strnlen(domain, 64);
1744 strcpy(bcc_ptr, "Linux version ");
1745 bcc_ptr += strlen("Linux version ");
1746 strcpy(bcc_ptr, system_utsname.release);
1747 bcc_ptr += strlen(system_utsname.release) + 1;
1748 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1749 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1751 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1752 smb_buffer->smb_buf_length += count;
1753 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1755 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1756 &bytes_returned, 1);
1758 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1759 } else if ((smb_buffer_response->WordCount == 3)
1760 || (smb_buffer_response->WordCount == 4)) {
1761 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1762 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1763 if (action & GUEST_LOGIN)
1764 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1765 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1766 cFYI(1, ("UID = %d ", ses->Suid));
1767 /* response can have either 3 or 4 word count - Samba sends 3 */
1768 bcc_ptr = pByteArea(smb_buffer_response);
1769 if ((pSMBr->resp.hdr.WordCount == 3)
1770 || ((pSMBr->resp.hdr.WordCount == 4)
1771 && (blob_len < pSMBr->resp.ByteCount))) {
1772 if (pSMBr->resp.hdr.WordCount == 4)
1773 bcc_ptr += blob_len;
1775 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1776 if ((long) (bcc_ptr) % 2) {
1778 (BCC(smb_buffer_response) - 1) /2;
1779 bcc_ptr++; /* Unicode strings must be word aligned */
1782 BCC(smb_buffer_response) / 2;
1785 UniStrnlen((wchar_t *) bcc_ptr,
1786 remaining_words - 1);
1787 /* We look for obvious messed up bcc or strings in response so we do not go off
1788 the end since (at least) WIN2K and Windows XP have a major bug in not null
1789 terminating last Unicode string in response */
1790 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1791 if(ses->serverOS == NULL)
1792 goto sesssetup_nomem;
1793 cifs_strfromUCS_le(ses->serverOS,
1794 (wchar_t *)bcc_ptr, len,nls_codepage);
1795 bcc_ptr += 2 * (len + 1);
1796 remaining_words -= len + 1;
1797 ses->serverOS[2 * len] = 0;
1798 ses->serverOS[1 + (2 * len)] = 0;
1799 if (remaining_words > 0) {
1800 len = UniStrnlen((wchar_t *)bcc_ptr,
1802 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
1803 if(ses->serverNOS == NULL)
1804 goto sesssetup_nomem;
1805 cifs_strfromUCS_le(ses->serverNOS,
1806 (wchar_t *)bcc_ptr,len,nls_codepage);
1807 bcc_ptr += 2 * (len + 1);
1808 ses->serverNOS[2 * len] = 0;
1809 ses->serverNOS[1 + (2 * len)] = 0;
1810 if(strncmp(ses->serverNOS,
1811 "NT LAN Manager 4",16) == 0) {
1812 cFYI(1,("NT4 server"));
1813 ses->flags |= CIFS_SES_NT4;
1815 remaining_words -= len + 1;
1816 if (remaining_words > 0) {
1817 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1818 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1820 kcalloc(1, 2*(len+1),GFP_KERNEL);
1821 if(ses->serverDomain == NULL)
1822 goto sesssetup_nomem;
1823 cifs_strfromUCS_le(ses->serverDomain,
1824 (wchar_t *)bcc_ptr,len,nls_codepage);
1825 bcc_ptr += 2 * (len + 1);
1826 ses->serverDomain[2*len] = 0;
1827 ses->serverDomain[1+(2*len)] = 0;
1828 } /* else no more room so create dummy domain string */
1831 kcalloc(1, 2, GFP_KERNEL);
1832 } else { /* no room so create dummy domain and NOS string */
1833 /* if these kcallocs fail not much we
1834 can do, but better to not fail the
1837 kcalloc(1, 2, GFP_KERNEL);
1839 kcalloc(1, 2, GFP_KERNEL);
1841 } else { /* ASCII */
1842 len = strnlen(bcc_ptr, 1024);
1843 if (((long) bcc_ptr + len) - (long)
1844 pByteArea(smb_buffer_response)
1845 <= BCC(smb_buffer_response)) {
1846 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
1847 if(ses->serverOS == NULL)
1848 goto sesssetup_nomem;
1849 strncpy(ses->serverOS,bcc_ptr, len);
1852 bcc_ptr[0] = 0; /* null terminate the string */
1855 len = strnlen(bcc_ptr, 1024);
1856 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
1857 if(ses->serverNOS == NULL)
1858 goto sesssetup_nomem;
1859 strncpy(ses->serverNOS, bcc_ptr, len);
1864 len = strnlen(bcc_ptr, 1024);
1865 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
1866 if(ses->serverDomain == NULL)
1867 goto sesssetup_nomem;
1868 strncpy(ses->serverDomain, bcc_ptr, len);
1874 ("Variable field of length %d extends beyond end of smb ",
1879 (" Security Blob Length extends beyond end of SMB"));
1883 (" Invalid Word count %d: ",
1884 smb_buffer_response->WordCount));
1887 sesssetup_nomem: /* do not return an error on nomem for the info strings,
1888 since that could make reconnection harder, and
1889 reconnection might be needed to free memory */
1891 cifs_buf_release(smb_buffer);
1897 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1898 char *SecurityBlob,int SecurityBlobLength,
1899 const struct nls_table *nls_codepage)
1901 struct smb_hdr *smb_buffer;
1902 struct smb_hdr *smb_buffer_response;
1903 SESSION_SETUP_ANDX *pSMB;
1904 SESSION_SETUP_ANDX *pSMBr;
1909 int remaining_words = 0;
1910 int bytes_returned = 0;
1915 cFYI(1, ("In spnego sesssetup "));
1918 user = ses->userName;
1919 domain = ses->domainName;
1921 smb_buffer = cifs_buf_get();
1922 if (smb_buffer == NULL) {
1925 smb_buffer_response = smb_buffer;
1926 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1928 /* send SMBsessionSetup here */
1929 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1930 NULL /* no tCon exists yet */ , 12 /* wct */ );
1931 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
1932 pSMB->req.AndXCommand = 0xFF;
1933 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1934 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1936 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1937 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1939 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1940 CAP_EXTENDED_SECURITY;
1941 if (ses->capabilities & CAP_UNICODE) {
1942 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1943 capabilities |= CAP_UNICODE;
1945 if (ses->capabilities & CAP_STATUS32) {
1946 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1947 capabilities |= CAP_STATUS32;
1949 if (ses->capabilities & CAP_DFS) {
1950 smb_buffer->Flags2 |= SMBFLG2_DFS;
1951 capabilities |= CAP_DFS;
1953 pSMB->req.Capabilities = cpu_to_le32(capabilities);
1955 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
1956 bcc_ptr = pByteArea(smb_buffer);
1957 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
1958 bcc_ptr += SecurityBlobLength;
1960 if (ses->capabilities & CAP_UNICODE) {
1961 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
1966 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
1967 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
1968 bcc_ptr += 2; /* trailing null */
1971 cifs_strtoUCS((wchar_t *) bcc_ptr,
1972 "CIFS_LINUX_DOM", 32, nls_codepage);
1975 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1977 bcc_ptr += 2 * bytes_returned;
1980 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1982 bcc_ptr += 2 * bytes_returned;
1984 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
1986 bcc_ptr += 2 * bytes_returned;
1989 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1991 bcc_ptr += 2 * bytes_returned;
1994 strncpy(bcc_ptr, user, 200);
1995 bcc_ptr += strnlen(user, 200);
1998 if (domain == NULL) {
1999 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2000 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2002 strncpy(bcc_ptr, domain, 64);
2003 bcc_ptr += strnlen(domain, 64);
2007 strcpy(bcc_ptr, "Linux version ");
2008 bcc_ptr += strlen("Linux version ");
2009 strcpy(bcc_ptr, system_utsname.release);
2010 bcc_ptr += strlen(system_utsname.release) + 1;
2011 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2012 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2014 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2015 smb_buffer->smb_buf_length += count;
2016 pSMB->req.ByteCount = cpu_to_le16(count);
2018 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2019 &bytes_returned, 1);
2021 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2022 } else if ((smb_buffer_response->WordCount == 3)
2023 || (smb_buffer_response->WordCount == 4)) {
2024 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2026 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2027 if (action & GUEST_LOGIN)
2028 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2030 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2031 cFYI(1, ("UID = %d ", ses->Suid));
2032 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2034 /* BB Fix below to make endian neutral !! */
2036 if ((pSMBr->resp.hdr.WordCount == 3)
2037 || ((pSMBr->resp.hdr.WordCount == 4)
2039 pSMBr->resp.ByteCount))) {
2040 if (pSMBr->resp.hdr.WordCount == 4) {
2044 ("Security Blob Length %d ",
2048 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2049 if ((long) (bcc_ptr) % 2) {
2051 (BCC(smb_buffer_response)
2053 bcc_ptr++; /* Unicode strings must be word aligned */
2057 (smb_buffer_response) / 2;
2060 UniStrnlen((wchar_t *) bcc_ptr,
2061 remaining_words - 1);
2062 /* We look for obvious messed up bcc or strings in response so we do not go off
2063 the end since (at least) WIN2K and Windows XP have a major bug in not null
2064 terminating last Unicode string in response */
2066 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2067 cifs_strfromUCS_le(ses->serverOS,
2071 bcc_ptr += 2 * (len + 1);
2072 remaining_words -= len + 1;
2073 ses->serverOS[2 * len] = 0;
2074 ses->serverOS[1 + (2 * len)] = 0;
2075 if (remaining_words > 0) {
2076 len = UniStrnlen((wchar_t *)bcc_ptr,
2080 kcalloc(1, 2 * (len + 1),
2082 cifs_strfromUCS_le(ses->serverNOS,
2086 bcc_ptr += 2 * (len + 1);
2087 ses->serverNOS[2 * len] = 0;
2088 ses->serverNOS[1 + (2 * len)] = 0;
2089 remaining_words -= len + 1;
2090 if (remaining_words > 0) {
2091 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2092 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2093 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2094 cifs_strfromUCS_le(ses->serverDomain,
2098 bcc_ptr += 2*(len+1);
2099 ses->serverDomain[2*len] = 0;
2100 ses->serverDomain[1+(2*len)] = 0;
2101 } /* else no more room so create dummy domain string */
2104 kcalloc(1, 2,GFP_KERNEL);
2105 } else { /* no room so create dummy domain and NOS string */
2106 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2107 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2109 } else { /* ASCII */
2111 len = strnlen(bcc_ptr, 1024);
2112 if (((long) bcc_ptr + len) - (long)
2113 pByteArea(smb_buffer_response)
2114 <= BCC(smb_buffer_response)) {
2115 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2116 strncpy(ses->serverOS, bcc_ptr, len);
2119 bcc_ptr[0] = 0; /* null terminate the string */
2122 len = strnlen(bcc_ptr, 1024);
2123 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2124 strncpy(ses->serverNOS, bcc_ptr, len);
2129 len = strnlen(bcc_ptr, 1024);
2130 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2131 strncpy(ses->serverDomain, bcc_ptr, len);
2137 ("Variable field of length %d extends beyond end of smb ",
2142 (" Security Blob Length extends beyond end of SMB"));
2145 cERROR(1, ("No session structure passed in."));
2149 (" Invalid Word count %d: ",
2150 smb_buffer_response->WordCount));
2155 cifs_buf_release(smb_buffer);
2161 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2162 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2163 const struct nls_table *nls_codepage)
2165 struct smb_hdr *smb_buffer;
2166 struct smb_hdr *smb_buffer_response;
2167 SESSION_SETUP_ANDX *pSMB;
2168 SESSION_SETUP_ANDX *pSMBr;
2172 int remaining_words = 0;
2173 int bytes_returned = 0;
2175 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2176 PNEGOTIATE_MESSAGE SecurityBlob;
2177 PCHALLENGE_MESSAGE SecurityBlob2;
2178 __u32 negotiate_flags, capabilities;
2181 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2184 domain = ses->domainName;
2185 *pNTLMv2_flag = FALSE;
2186 smb_buffer = cifs_buf_get();
2187 if (smb_buffer == NULL) {
2190 smb_buffer_response = smb_buffer;
2191 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2192 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2194 /* send SMBsessionSetup here */
2195 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2196 NULL /* no tCon exists yet */ , 12 /* wct */ );
2197 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2198 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2200 pSMB->req.AndXCommand = 0xFF;
2201 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2202 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2204 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2205 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2207 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2208 CAP_EXTENDED_SECURITY;
2209 if (ses->capabilities & CAP_UNICODE) {
2210 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2211 capabilities |= CAP_UNICODE;
2213 if (ses->capabilities & CAP_STATUS32) {
2214 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2215 capabilities |= CAP_STATUS32;
2217 if (ses->capabilities & CAP_DFS) {
2218 smb_buffer->Flags2 |= SMBFLG2_DFS;
2219 capabilities |= CAP_DFS;
2221 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2223 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2224 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2225 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2226 SecurityBlob->MessageType = NtLmNegotiate;
2228 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2229 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2230 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2232 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2234 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2235 /* setup pointers to domain name and workstation name */
2236 bcc_ptr += SecurityBlobLength;
2238 SecurityBlob->WorkstationName.Buffer = 0;
2239 SecurityBlob->WorkstationName.Length = 0;
2240 SecurityBlob->WorkstationName.MaximumLength = 0;
2242 if (domain == NULL) {
2243 SecurityBlob->DomainName.Buffer = 0;
2244 SecurityBlob->DomainName.Length = 0;
2245 SecurityBlob->DomainName.MaximumLength = 0;
2248 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2249 strncpy(bcc_ptr, domain, 63);
2250 len = strnlen(domain, 64);
2251 SecurityBlob->DomainName.MaximumLength =
2253 SecurityBlob->DomainName.Buffer =
2254 cpu_to_le32((long) &SecurityBlob->
2256 (long) &SecurityBlob->Signature);
2258 SecurityBlobLength += len;
2259 SecurityBlob->DomainName.Length =
2262 if (ses->capabilities & CAP_UNICODE) {
2263 if ((long) bcc_ptr % 2) {
2269 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2271 bcc_ptr += 2 * bytes_returned;
2273 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2275 bcc_ptr += 2 * bytes_returned;
2276 bcc_ptr += 2; /* null terminate Linux version */
2278 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2280 bcc_ptr += 2 * bytes_returned;
2283 bcc_ptr += 2; /* null terminate network opsys string */
2286 bcc_ptr += 2; /* null domain */
2287 } else { /* ASCII */
2288 strcpy(bcc_ptr, "Linux version ");
2289 bcc_ptr += strlen("Linux version ");
2290 strcpy(bcc_ptr, system_utsname.release);
2291 bcc_ptr += strlen(system_utsname.release) + 1;
2292 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2293 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2294 bcc_ptr++; /* empty domain field */
2297 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2298 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2299 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2300 smb_buffer->smb_buf_length += count;
2301 pSMB->req.ByteCount = cpu_to_le16(count);
2303 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2304 &bytes_returned, 1);
2306 if (smb_buffer_response->Status.CifsError ==
2307 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2311 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2312 } else if ((smb_buffer_response->WordCount == 3)
2313 || (smb_buffer_response->WordCount == 4)) {
2314 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2315 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2317 if (action & GUEST_LOGIN)
2318 cFYI(1, (" Guest login"));
2319 /* Do we want to set anything in SesInfo struct when guest login? */
2321 bcc_ptr = pByteArea(smb_buffer_response);
2322 /* response can have either 3 or 4 word count - Samba sends 3 */
2324 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2325 if (SecurityBlob2->MessageType != NtLmChallenge) {
2327 ("Unexpected NTLMSSP message type received %d",
2328 SecurityBlob2->MessageType));
2330 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2331 cFYI(1, ("UID = %d ", ses->Suid));
2332 if ((pSMBr->resp.hdr.WordCount == 3)
2333 || ((pSMBr->resp.hdr.WordCount == 4)
2335 pSMBr->resp.ByteCount))) {
2337 if (pSMBr->resp.hdr.WordCount == 4) {
2338 bcc_ptr += blob_len;
2340 ("Security Blob Length %d ",
2344 cFYI(1, ("NTLMSSP Challenge rcvd "));
2346 memcpy(ses->server->cryptKey,
2347 SecurityBlob2->Challenge,
2348 CIFS_CRYPTO_KEY_SIZE);
2349 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2350 *pNTLMv2_flag = TRUE;
2352 if((SecurityBlob2->NegotiateFlags &
2353 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2354 || (sign_CIFS_PDUs > 1))
2355 ses->server->secMode |=
2356 SECMODE_SIGN_REQUIRED;
2357 if ((SecurityBlob2->NegotiateFlags &
2358 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2359 ses->server->secMode |=
2360 SECMODE_SIGN_ENABLED;
2362 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2363 if ((long) (bcc_ptr) % 2) {
2365 (BCC(smb_buffer_response)
2367 bcc_ptr++; /* Unicode strings must be word aligned */
2371 (smb_buffer_response) / 2;
2374 UniStrnlen((wchar_t *) bcc_ptr,
2375 remaining_words - 1);
2376 /* We look for obvious messed up bcc or strings in response so we do not go off
2377 the end since (at least) WIN2K and Windows XP have a major bug in not null
2378 terminating last Unicode string in response */
2380 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2381 cifs_strfromUCS_le(ses->serverOS,
2385 bcc_ptr += 2 * (len + 1);
2386 remaining_words -= len + 1;
2387 ses->serverOS[2 * len] = 0;
2388 ses->serverOS[1 + (2 * len)] = 0;
2389 if (remaining_words > 0) {
2390 len = UniStrnlen((wchar_t *)
2395 kcalloc(1, 2 * (len + 1),
2397 cifs_strfromUCS_le(ses->
2403 bcc_ptr += 2 * (len + 1);
2404 ses->serverNOS[2 * len] = 0;
2407 remaining_words -= len + 1;
2408 if (remaining_words > 0) {
2409 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2410 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2435 } /* else no more room so create dummy domain string */
2440 } else { /* no room so create dummy domain and NOS string */
2442 kcalloc(1, 2, GFP_KERNEL);
2444 kcalloc(1, 2, GFP_KERNEL);
2446 } else { /* ASCII */
2447 len = strnlen(bcc_ptr, 1024);
2448 if (((long) bcc_ptr + len) - (long)
2449 pByteArea(smb_buffer_response)
2450 <= BCC(smb_buffer_response)) {
2454 strncpy(ses->serverOS,
2458 bcc_ptr[0] = 0; /* null terminate string */
2461 len = strnlen(bcc_ptr, 1024);
2465 strncpy(ses->serverNOS, bcc_ptr, len);
2470 len = strnlen(bcc_ptr, 1024);
2474 strncpy(ses->serverDomain, bcc_ptr, len);
2480 ("Variable field of length %d extends beyond end of smb ",
2485 (" Security Blob Length extends beyond end of SMB"));
2488 cERROR(1, ("No session structure passed in."));
2492 (" Invalid Word count %d: ",
2493 smb_buffer_response->WordCount));
2498 cifs_buf_release(smb_buffer);
2503 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2504 char *ntlm_session_key, int ntlmv2_flag,
2505 const struct nls_table *nls_codepage)
2507 struct smb_hdr *smb_buffer;
2508 struct smb_hdr *smb_buffer_response;
2509 SESSION_SETUP_ANDX *pSMB;
2510 SESSION_SETUP_ANDX *pSMBr;
2515 int remaining_words = 0;
2516 int bytes_returned = 0;
2518 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2519 PAUTHENTICATE_MESSAGE SecurityBlob;
2520 __u32 negotiate_flags, capabilities;
2523 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2526 user = ses->userName;
2527 domain = ses->domainName;
2528 smb_buffer = cifs_buf_get();
2529 if (smb_buffer == NULL) {
2532 smb_buffer_response = smb_buffer;
2533 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2534 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2536 /* send SMBsessionSetup here */
2537 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2538 NULL /* no tCon exists yet */ , 12 /* wct */ );
2539 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2540 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2541 pSMB->req.AndXCommand = 0xFF;
2542 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2543 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2545 pSMB->req.hdr.Uid = ses->Suid;
2547 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2548 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2550 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2551 CAP_EXTENDED_SECURITY;
2552 if (ses->capabilities & CAP_UNICODE) {
2553 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2554 capabilities |= CAP_UNICODE;
2556 if (ses->capabilities & CAP_STATUS32) {
2557 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2558 capabilities |= CAP_STATUS32;
2560 if (ses->capabilities & CAP_DFS) {
2561 smb_buffer->Flags2 |= SMBFLG2_DFS;
2562 capabilities |= CAP_DFS;
2564 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2566 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2567 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2568 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2569 SecurityBlob->MessageType = NtLmAuthenticate;
2570 bcc_ptr += SecurityBlobLength;
2572 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2573 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2574 0x80000000 | NTLMSSP_NEGOTIATE_128;
2576 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2578 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2580 /* setup pointers to domain name and workstation name */
2582 SecurityBlob->WorkstationName.Buffer = 0;
2583 SecurityBlob->WorkstationName.Length = 0;
2584 SecurityBlob->WorkstationName.MaximumLength = 0;
2585 SecurityBlob->SessionKey.Length = 0;
2586 SecurityBlob->SessionKey.MaximumLength = 0;
2587 SecurityBlob->SessionKey.Buffer = 0;
2589 SecurityBlob->LmChallengeResponse.Length = 0;
2590 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2591 SecurityBlob->LmChallengeResponse.Buffer = 0;
2593 SecurityBlob->NtChallengeResponse.Length =
2594 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2595 SecurityBlob->NtChallengeResponse.MaximumLength =
2596 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2597 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2598 SecurityBlob->NtChallengeResponse.Buffer =
2599 cpu_to_le32(SecurityBlobLength);
2600 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2601 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2603 if (ses->capabilities & CAP_UNICODE) {
2604 if (domain == NULL) {
2605 SecurityBlob->DomainName.Buffer = 0;
2606 SecurityBlob->DomainName.Length = 0;
2607 SecurityBlob->DomainName.MaximumLength = 0;
2610 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2613 SecurityBlob->DomainName.MaximumLength =
2615 SecurityBlob->DomainName.Buffer =
2616 cpu_to_le32(SecurityBlobLength);
2618 SecurityBlobLength += len;
2619 SecurityBlob->DomainName.Length =
2623 SecurityBlob->UserName.Buffer = 0;
2624 SecurityBlob->UserName.Length = 0;
2625 SecurityBlob->UserName.MaximumLength = 0;
2628 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2631 SecurityBlob->UserName.MaximumLength =
2633 SecurityBlob->UserName.Buffer =
2634 cpu_to_le32(SecurityBlobLength);
2636 SecurityBlobLength += len;
2637 SecurityBlob->UserName.Length =
2641 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2642 SecurityBlob->WorkstationName.Length *= 2;
2643 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2644 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2645 bcc_ptr += SecurityBlob->WorkstationName.Length;
2646 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2647 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2649 if ((long) bcc_ptr % 2) {
2654 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2656 bcc_ptr += 2 * bytes_returned;
2658 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2660 bcc_ptr += 2 * bytes_returned;
2661 bcc_ptr += 2; /* null term version string */
2663 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2665 bcc_ptr += 2 * bytes_returned;
2668 bcc_ptr += 2; /* null terminate network opsys string */
2671 bcc_ptr += 2; /* null domain */
2672 } else { /* ASCII */
2673 if (domain == NULL) {
2674 SecurityBlob->DomainName.Buffer = 0;
2675 SecurityBlob->DomainName.Length = 0;
2676 SecurityBlob->DomainName.MaximumLength = 0;
2679 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2680 strncpy(bcc_ptr, domain, 63);
2681 len = strnlen(domain, 64);
2682 SecurityBlob->DomainName.MaximumLength =
2684 SecurityBlob->DomainName.Buffer =
2685 cpu_to_le32(SecurityBlobLength);
2687 SecurityBlobLength += len;
2688 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2691 SecurityBlob->UserName.Buffer = 0;
2692 SecurityBlob->UserName.Length = 0;
2693 SecurityBlob->UserName.MaximumLength = 0;
2696 strncpy(bcc_ptr, user, 63);
2697 len = strnlen(user, 64);
2698 SecurityBlob->UserName.MaximumLength =
2700 SecurityBlob->UserName.Buffer =
2701 cpu_to_le32(SecurityBlobLength);
2703 SecurityBlobLength += len;
2704 SecurityBlob->UserName.Length = cpu_to_le16(len);
2706 /* BB fill in our workstation name if known BB */
2708 strcpy(bcc_ptr, "Linux version ");
2709 bcc_ptr += strlen("Linux version ");
2710 strcpy(bcc_ptr, system_utsname.release);
2711 bcc_ptr += strlen(system_utsname.release) + 1;
2712 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2713 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2714 bcc_ptr++; /* null domain */
2717 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2718 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2719 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2720 smb_buffer->smb_buf_length += count;
2721 pSMB->req.ByteCount = cpu_to_le16(count);
2723 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2724 &bytes_returned, 1);
2726 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2727 } else if ((smb_buffer_response->WordCount == 3)
2728 || (smb_buffer_response->WordCount == 4)) {
2729 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2731 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2732 if (action & GUEST_LOGIN)
2733 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2734 /* if(SecurityBlob2->MessageType != NtLm??){
2735 cFYI("Unexpected message type on auth response is %d "));
2739 ("Does UID on challenge %d match auth response UID %d ",
2740 ses->Suid, smb_buffer_response->Uid));
2741 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2742 bcc_ptr = pByteArea(smb_buffer_response);
2743 /* response can have either 3 or 4 word count - Samba sends 3 */
2744 if ((pSMBr->resp.hdr.WordCount == 3)
2745 || ((pSMBr->resp.hdr.WordCount == 4)
2747 pSMBr->resp.ByteCount))) {
2748 if (pSMBr->resp.hdr.WordCount == 4) {
2752 ("Security Blob Length %d ",
2757 ("NTLMSSP response to Authenticate "));
2759 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2760 if ((long) (bcc_ptr) % 2) {
2762 (BCC(smb_buffer_response)
2764 bcc_ptr++; /* Unicode strings must be word aligned */
2766 remaining_words = BCC(smb_buffer_response) / 2;
2769 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2770 /* We look for obvious messed up bcc or strings in response so we do not go off
2771 the end since (at least) WIN2K and Windows XP have a major bug in not null
2772 terminating last Unicode string in response */
2774 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2775 cifs_strfromUCS_le(ses->serverOS,
2779 bcc_ptr += 2 * (len + 1);
2780 remaining_words -= len + 1;
2781 ses->serverOS[2 * len] = 0;
2782 ses->serverOS[1 + (2 * len)] = 0;
2783 if (remaining_words > 0) {
2784 len = UniStrnlen((wchar_t *)
2789 kcalloc(1, 2 * (len + 1),
2791 cifs_strfromUCS_le(ses->
2797 bcc_ptr += 2 * (len + 1);
2798 ses->serverNOS[2 * len] = 0;
2799 ses->serverNOS[1+(2*len)] = 0;
2800 remaining_words -= len + 1;
2801 if (remaining_words > 0) {
2802 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2803 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2828 } /* else no more room so create dummy domain string */
2830 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
2831 } else { /* no room so create dummy domain and NOS string */
2832 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2833 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2835 } else { /* ASCII */
2836 len = strnlen(bcc_ptr, 1024);
2837 if (((long) bcc_ptr + len) -
2838 (long) pByteArea(smb_buffer_response)
2839 <= BCC(smb_buffer_response)) {
2840 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2841 strncpy(ses->serverOS,bcc_ptr, len);
2844 bcc_ptr[0] = 0; /* null terminate the string */
2847 len = strnlen(bcc_ptr, 1024);
2848 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
2849 strncpy(ses->serverNOS, bcc_ptr, len);
2854 len = strnlen(bcc_ptr, 1024);
2855 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
2856 strncpy(ses->serverDomain, bcc_ptr, len);
2862 ("Variable field of length %d extends beyond end of smb ",
2867 (" Security Blob Length extends beyond end of SMB"));
2870 cERROR(1, ("No session structure passed in."));
2874 (" Invalid Word count %d: ",
2875 smb_buffer_response->WordCount));
2880 cifs_buf_release(smb_buffer);
2886 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
2887 const char *tree, struct cifsTconInfo *tcon,
2888 const struct nls_table *nls_codepage)
2890 struct smb_hdr *smb_buffer;
2891 struct smb_hdr *smb_buffer_response;
2894 unsigned char *bcc_ptr;
2902 smb_buffer = cifs_buf_get();
2903 if (smb_buffer == NULL) {
2906 smb_buffer_response = smb_buffer;
2908 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
2909 NULL /*no tid */ , 4 /*wct */ );
2910 smb_buffer->Uid = ses->Suid;
2911 pSMB = (TCONX_REQ *) smb_buffer;
2912 pSMBr = (TCONX_RSP *) smb_buffer_response;
2914 pSMB->AndXCommand = 0xFF;
2915 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
2916 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
2917 bcc_ptr = &pSMB->Password[0];
2918 bcc_ptr++; /* skip password */
2920 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2921 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2923 if (ses->capabilities & CAP_STATUS32) {
2924 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2926 if (ses->capabilities & CAP_DFS) {
2927 smb_buffer->Flags2 |= SMBFLG2_DFS;
2929 if (ses->capabilities & CAP_UNICODE) {
2930 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2932 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
2933 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
2934 bcc_ptr += 2; /* skip trailing null */
2935 } else { /* ASCII */
2937 strcpy(bcc_ptr, tree);
2938 bcc_ptr += strlen(tree) + 1;
2940 strcpy(bcc_ptr, "?????");
2941 bcc_ptr += strlen("?????");
2943 count = bcc_ptr - &pSMB->Password[0];
2944 pSMB->hdr.smb_buf_length += count;
2945 pSMB->ByteCount = cpu_to_le16(count);
2947 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
2949 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
2950 /* above now done in SendReceive */
2951 if ((rc == 0) && (tcon != NULL)) {
2952 tcon->tidStatus = CifsGood;
2953 tcon->tid = smb_buffer_response->Tid;
2954 bcc_ptr = pByteArea(smb_buffer_response);
2955 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
2956 /* skip service field (NB: this field is always ASCII) */
2957 bcc_ptr += length + 1;
2958 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
2959 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2960 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
2961 if ((bcc_ptr + (2 * length)) -
2962 pByteArea(smb_buffer_response) <=
2963 BCC(smb_buffer_response)) {
2964 if(tcon->nativeFileSystem)
2965 kfree(tcon->nativeFileSystem);
2966 tcon->nativeFileSystem =
2967 kcalloc(1, length + 2, GFP_KERNEL);
2968 cifs_strfromUCS_le(tcon->nativeFileSystem,
2969 (wchar_t *) bcc_ptr,
2970 length, nls_codepage);
2971 bcc_ptr += 2 * length;
2972 bcc_ptr[0] = 0; /* null terminate the string */
2976 /* else do not bother copying these informational fields */
2978 length = strnlen(bcc_ptr, 1024);
2979 if ((bcc_ptr + length) -
2980 pByteArea(smb_buffer_response) <=
2981 BCC(smb_buffer_response)) {
2982 if(tcon->nativeFileSystem)
2983 kfree(tcon->nativeFileSystem);
2984 tcon->nativeFileSystem =
2985 kcalloc(1, length + 1, GFP_KERNEL);
2986 strncpy(tcon->nativeFileSystem, bcc_ptr,
2989 /* else do not bother copying these informational fields */
2991 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
2992 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
2993 } else if ((rc == 0) && tcon == NULL) {
2994 /* all we need to save for IPC$ connection */
2995 ses->ipc_tid = smb_buffer_response->Tid;
2999 cifs_buf_release(smb_buffer);
3004 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3008 struct cifsSesInfo *ses = NULL;
3009 struct task_struct *cifsd_task;
3013 if (cifs_sb->tcon) {
3014 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3015 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3020 tconInfoFree(cifs_sb->tcon);
3021 if ((ses) && (ses->server)) {
3022 /* save off task so we do not refer to ses later */
3023 cifsd_task = ses->server->tsk;
3024 cFYI(1, ("About to do SMBLogoff "));
3025 rc = CIFSSMBLogoff(xid, ses);
3029 } else if (rc == -ESHUTDOWN) {
3030 cFYI(1,("Waking up socket by sending it signal"));
3032 send_sig(SIGKILL,cifsd_task,1);
3034 } /* else - we have an smb session
3035 left on this socket do not kill cifsd */
3037 cFYI(1, ("No session or bad tcon"));
3040 cifs_sb->tcon = NULL;
3042 set_current_state(TASK_INTERRUPTIBLE);
3043 schedule_timeout(HZ / 2);
3049 return rc; /* BB check if we should always return zero here */
3052 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3053 struct nls_table * nls_info)
3056 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3057 int ntlmv2_flag = FALSE;
3060 /* what if server changes its buffer size after dropping the session? */
3061 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3062 rc = CIFSSMBNegotiate(xid, pSesInfo);
3063 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3064 rc = CIFSSMBNegotiate(xid, pSesInfo);
3069 spin_lock(&GlobalMid_Lock);
3070 if(pSesInfo->server->tcpStatus != CifsExiting)
3071 pSesInfo->server->tcpStatus = CifsGood;
3074 spin_unlock(&GlobalMid_Lock);
3080 pSesInfo->capabilities = pSesInfo->server->capabilities;
3081 if(linuxExtEnabled == 0)
3082 pSesInfo->capabilities &= (~CAP_UNIX);
3083 /* pSesInfo->sequence_number = 0;*/
3084 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3085 pSesInfo->server->secMode,
3086 pSesInfo->server->capabilities,
3087 pSesInfo->server->timeZone));
3088 if (extended_security
3089 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3090 && (pSesInfo->server->secType == NTLMSSP)) {
3091 cFYI(1, ("New style sesssetup "));
3092 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3093 NULL /* security blob */,
3094 0 /* blob length */,
3096 } else if (extended_security
3097 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3098 && (pSesInfo->server->secType == RawNTLMSSP)) {
3099 cFYI(1, ("NTLMSSP sesssetup "));
3100 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3107 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3108 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3113 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3115 CalcNTLMv2_response(pSesInfo,v2_response);
3117 cifs_calculate_ntlmv2_mac_key(
3118 pSesInfo->server->mac_signing_key,
3119 response, ntlm_session_key, */
3121 /* BB Put dummy sig in SessSetup PDU? */
3128 SMBNTencrypt(pSesInfo->password,
3129 pSesInfo->server->cryptKey,
3133 cifs_calculate_mac_key(
3134 pSesInfo->server->mac_signing_key,
3136 pSesInfo->password);
3138 /* for better security the weaker lanman hash not sent
3139 in AuthSessSetup so we no longer calculate it */
3141 rc = CIFSNTLMSSPAuthSessSetup(xid,
3147 } else { /* old style NTLM 0.12 session setup */
3148 SMBNTencrypt(pSesInfo->password,
3149 pSesInfo->server->cryptKey,
3153 cifs_calculate_mac_key(
3154 pSesInfo->server->mac_signing_key,
3155 ntlm_session_key, pSesInfo->password);
3157 rc = CIFSSessSetup(xid, pSesInfo,
3158 ntlm_session_key, nls_info);
3161 cERROR(1,("Send error in SessSetup = %d",rc));
3163 cFYI(1,("CIFS Session Established successfully"));
3164 pSesInfo->status = CifsGood;