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);
199 0 not a transact2, or all data present
200 >0 transact2 with that much data missing
201 -EINVAL = invalid transact2
204 static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
206 struct smb_t2_rsp * pSMBt;
208 int data_in_this_rsp;
211 if(pSMB->Command != SMB_COM_TRANSACTION2)
214 /* check for plausible wct, bcc and t2 data and parm sizes */
215 /* check for parm and data offset going beyond end of smb */
216 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
217 cFYI(1,("invalid transact2 word count"));
221 pSMBt = (struct smb_t2_rsp *)pSMB;
223 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
224 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
226 remaining = total_data_size - data_in_this_rsp;
230 else if(remaining < 0) {
231 cFYI(1,("total data %d smaller than data in frame %d",
232 total_data_size, data_in_this_rsp));
235 cFYI(1,("missing %d bytes from transact2, check next response",
237 if(total_data_size > maxBufSize) {
238 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
239 total_data_size,maxBufSize));
246 static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
248 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
249 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
254 char * data_area_of_target;
255 char * data_area_of_buf2;
258 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
260 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
261 cFYI(1,("total data sizes of primary and secondary t2 differ"));
264 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
266 remaining = total_data_size - total_in_buf;
271 if(remaining == 0) /* nothing to do, ignore */
274 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
275 if(remaining < total_in_buf2) {
276 cFYI(1,("transact2 2nd response contains too much data"));
279 /* find end of first SMB data area */
280 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
281 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
282 /* validate target area */
284 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
285 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
287 data_area_of_target += total_in_buf;
289 /* copy second buffer into end of first buffer */
290 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
291 total_in_buf += total_in_buf2;
292 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
293 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
294 byte_count += total_in_buf2;
295 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
297 byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
298 byte_count += total_in_buf2;
300 /* BB also add check that we are not beyond maximum buffer size */
302 pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
304 if(remaining == total_in_buf2) {
305 cFYI(1,("found the last secondary response"));
306 return 0; /* we are done */
307 } else /* more responses to go */
313 cifs_demultiplex_thread(struct TCP_Server_Info *server)
316 unsigned int pdu_length, total_read;
317 struct smb_hdr *smb_buffer = NULL;
318 struct smb_hdr *bigbuf = NULL;
319 struct smb_hdr *smallbuf = NULL;
320 struct msghdr smb_msg;
322 struct socket *csocket = server->ssocket;
323 struct list_head *tmp;
324 struct cifsSesInfo *ses;
325 struct task_struct *task_to_wake = NULL;
326 struct mid_q_entry *mid_entry;
328 int isLargeBuf = FALSE;
333 allow_signal(SIGKILL);
334 current->flags |= PF_MEMALLOC;
335 server->tsk = current; /* save process info to wake at shutdown */
336 cFYI(1, ("Demultiplex PID: %d", current->pid));
337 write_lock(&GlobalSMBSeslock);
338 atomic_inc(&tcpSesAllocCount);
339 length = tcpSesAllocCount.counter;
340 write_unlock(&GlobalSMBSeslock);
342 mempool_resize(cifs_req_poolp,
343 length + cifs_min_rcv,
347 while (server->tcpStatus != CifsExiting) {
348 if (bigbuf == NULL) {
349 bigbuf = cifs_buf_get();
351 cERROR(1,("No memory for large SMB response"));
353 /* retry will check if exiting */
356 } else if(isLargeBuf) {
357 /* we are reusing a dirtry large buf, clear its start */
358 memset(bigbuf, 0, sizeof (struct smb_hdr));
361 if (smallbuf == NULL) {
362 smallbuf = cifs_small_buf_get();
363 if(smallbuf == NULL) {
364 cERROR(1,("No memory for SMB response"));
366 /* retry will check if exiting */
369 /* beginning of smb buffer is cleared in our buf_get */
370 } else /* if existing small buf clear beginning */
371 memset(smallbuf, 0, sizeof (struct smb_hdr));
375 smb_buffer = smallbuf;
376 iov.iov_base = smb_buffer;
378 smb_msg.msg_control = NULL;
379 smb_msg.msg_controllen = 0;
381 kernel_recvmsg(csocket, &smb_msg,
382 &iov, 1, 4, 0 /* BB see socket.h flags */);
384 if(server->tcpStatus == CifsExiting) {
386 } else if (server->tcpStatus == CifsNeedReconnect) {
387 cFYI(1,("Reconnecting after server stopped responding"));
388 cifs_reconnect(server);
389 cFYI(1,("call to reconnect done"));
390 csocket = server->ssocket;
392 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
393 msleep(1); /* minimum sleep to prevent looping
394 allowing socket to clear and app threads to set
395 tcpStatus CifsNeedReconnect if server hung */
397 } else if (length <= 0) {
398 if(server->tcpStatus == CifsNew) {
399 cFYI(1,("tcp session abended prematurely (after SMBnegprot)"));
400 /* some servers kill the TCP session rather than
401 returning an SMB negprot error, in which
402 case reconnecting here is not going to help,
403 and so simply return error to mount */
406 if(length == -EINTR) {
407 cFYI(1,("cifsd thread killed"));
410 cFYI(1,("Reconnecting after unexpected peek error %d",length));
411 cifs_reconnect(server);
412 csocket = server->ssocket;
413 wake_up(&server->response_q);
415 } else if (length < 4) {
417 ("Frame less than four bytes received %d bytes long.",
419 cifs_reconnect(server);
420 csocket = server->ssocket;
421 wake_up(&server->response_q);
425 /* the right amount was read from socket - 4 bytes */
427 pdu_length = ntohl(smb_buffer->smb_buf_length);
428 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
430 temp = (char *) smb_buffer;
431 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
433 } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
434 cFYI(1,("Good RFC 1002 session rsp"));
436 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
437 /* we get this from Windows 98 instead of
438 an error on SMB negprot response */
439 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
441 if(server->tcpStatus == CifsNew) {
442 /* if nack on negprot (rather than
443 ret of smb negprot error) reconnecting
444 not going to help, ret error to mount */
447 /* give server a second to
448 clean up before reconnect attempt */
450 /* always try 445 first on reconnect
451 since we get NACK on some if we ever
452 connected to port 139 (the NACK is
453 since we do not begin with RFC1001
454 session initialize frame) */
455 server->addr.sockAddr.sin_port =
457 cifs_reconnect(server);
458 csocket = server->ssocket;
459 wake_up(&server->response_q);
462 } else if (temp[0] != (char) 0) {
463 cERROR(1,("Unknown RFC 1002 frame"));
464 cifs_dump_mem(" Received Data: ", temp, length);
465 cifs_reconnect(server);
466 csocket = server->ssocket;
470 /* else we have an SMB response */
471 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
472 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
473 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
474 length, pdu_length+4));
475 cifs_reconnect(server);
476 csocket = server->ssocket;
477 wake_up(&server->response_q);
484 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
486 memcpy(bigbuf, smallbuf, 4);
490 iov.iov_base = 4 + (char *)smb_buffer;
491 iov.iov_len = pdu_length;
492 for (total_read = 0; total_read < pdu_length;
493 total_read += length) {
494 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
495 pdu_length - total_read, 0);
496 if((server->tcpStatus == CifsExiting) ||
497 (length == -EINTR)) {
501 } else if (server->tcpStatus == CifsNeedReconnect) {
502 cifs_reconnect(server);
503 csocket = server->ssocket;
504 /* Reconnect wakes up rspns q */
505 /* Now we will reread sock */
508 } else if ((length == -ERESTARTSYS) ||
509 (length == -EAGAIN)) {
510 msleep(1); /* minimum sleep to prevent looping,
511 allowing socket to clear and app
512 threads to set tcpStatus
513 CifsNeedReconnect if server hung*/
515 } else if (length <= 0) {
516 cERROR(1,("Received no data, expecting %d",
517 pdu_length - total_read));
518 cifs_reconnect(server);
519 csocket = server->ssocket;
526 else if(reconnect == 1)
529 length += 4; /* account for rfc1002 hdr */
532 dump_smb(smb_buffer, length);
533 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
534 cERROR(1, ("Bad SMB Received "));
540 spin_lock(&GlobalMid_Lock);
541 list_for_each(tmp, &server->pending_mid_q) {
542 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
544 if ((mid_entry->mid == smb_buffer->Mid) &&
545 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
546 (mid_entry->command == smb_buffer->Command)) {
547 cFYI(1,("Found Mid 0x%x wake", mid_entry->mid));
549 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
550 /* We have a multipart transact2 resp */
551 if(mid_entry->resp_buf) {
552 /* merge response - fix up 1st*/
553 if(coalesce_t2(smb_buffer,
554 mid_entry->resp_buf)) {
558 /* all parts received */
563 cERROR(1,("1st trans2 resp needs bigbuf"));
564 /* BB maybe we can fix this up, switch
565 to already allocated large buffer? */
567 mid_entry->resp_buf =
569 mid_entry->largeBuf = 1;
576 mid_entry->resp_buf = smb_buffer;
578 mid_entry->largeBuf = 1;
580 mid_entry->largeBuf = 0;
582 task_to_wake = mid_entry->tsk;
583 mid_entry->midState = MID_RESPONSE_RECEIVED;
587 spin_unlock(&GlobalMid_Lock);
593 /* smb buffer freed by user thread when done */
594 wake_up_process(task_to_wake);
595 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
596 && (isMultiRsp == FALSE)) {
597 cERROR(1, ("No task to wake, unknown frame rcvd!"));
598 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
600 } /* end while !EXITING */
602 spin_lock(&GlobalMid_Lock);
603 server->tcpStatus = CifsExiting;
605 atomic_set(&server->inFlight, 0);
606 spin_unlock(&GlobalMid_Lock);
607 /* Although there should not be any requests blocked on
608 this queue it can not hurt to be paranoid and try to wake up requests
609 that may haven been blocked when more than 50 at time were on the wire
610 to the same server - they now will see the session is in exit state
611 and get out of SendReceive. */
612 wake_up_all(&server->request_q);
613 /* give those requests time to exit */
616 if(server->ssocket) {
617 sock_release(csocket);
618 server->ssocket = NULL;
620 /* buffer usuallly freed in free_mid - need to free it here on exit */
622 cifs_buf_release(bigbuf);
623 if (smallbuf != NULL)
624 cifs_small_buf_release(smallbuf);
626 read_lock(&GlobalSMBSeslock);
627 if (list_empty(&server->pending_mid_q)) {
628 /* loop through server session structures attached to this and
630 list_for_each(tmp, &GlobalSMBSessionList) {
632 list_entry(tmp, struct cifsSesInfo,
634 if (ses->server == server) {
635 ses->status = CifsExiting;
639 read_unlock(&GlobalSMBSeslock);
641 spin_lock(&GlobalMid_Lock);
642 list_for_each(tmp, &server->pending_mid_q) {
643 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
644 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
646 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
647 task_to_wake = mid_entry->tsk;
649 wake_up_process(task_to_wake);
653 spin_unlock(&GlobalMid_Lock);
654 read_unlock(&GlobalSMBSeslock);
655 /* 1/8th of sec is more than enough time for them to exit */
659 if (list_empty(&server->pending_mid_q)) {
660 /* mpx threads have not exited yet give them
661 at least the smb send timeout time for long ops */
662 cFYI(1, ("Wait for exit from demultiplex thread"));
664 /* if threads still have not exited they are probably never
665 coming home not much else we can do but free the memory */
669 write_lock(&GlobalSMBSeslock);
670 atomic_dec(&tcpSesAllocCount);
671 length = tcpSesAllocCount.counter;
672 write_unlock(&GlobalSMBSeslock);
674 mempool_resize(cifs_req_poolp,
675 length + cifs_min_rcv,
684 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
688 unsigned int temp_len, i, j;
694 memset(vol->source_rfc1001_name,0x20,15);
695 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
696 /* does not have to be a perfect mapping since the field is
697 informational, only used for servers that do not support
698 port 445 and it can be overridden at mount time */
699 vol->source_rfc1001_name[i] =
700 toupper(system_utsname.nodename[i]);
702 vol->source_rfc1001_name[15] = 0;
704 vol->linux_uid = current->uid; /* current->euid instead? */
705 vol->linux_gid = current->gid;
706 vol->dir_mode = S_IRWXUGO;
707 /* 2767 perms indicate mandatory locking support */
708 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
710 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
716 if(strncmp(options,"sep=",4) == 0) {
717 if(options[4] != 0) {
718 separator[0] = options[4];
721 cFYI(1,("Null separator not allowed"));
725 while ((data = strsep(&options, separator)) != NULL) {
728 if ((value = strchr(data, '=')) != NULL)
731 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
733 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
735 } else if (strnicmp(data, "user", 4) == 0) {
736 if (!value || !*value) {
738 "CIFS: invalid or missing username\n");
739 return 1; /* needs_arg; */
741 if (strnlen(value, 200) < 200) {
742 vol->username = value;
744 printk(KERN_WARNING "CIFS: username too long\n");
747 } else if (strnicmp(data, "pass", 4) == 0) {
749 vol->password = NULL;
751 } else if(value[0] == 0) {
752 /* check if string begins with double comma
753 since that would mean the password really
754 does start with a comma, and would not
755 indicate an empty string */
756 if(value[1] != separator[0]) {
757 vol->password = NULL;
761 temp_len = strlen(value);
762 /* removed password length check, NTLM passwords
763 can be arbitrarily long */
765 /* if comma in password, the string will be
766 prematurely null terminated. Commas in password are
767 specified across the cifs mount interface by a double
768 comma ie ,, and a comma used as in other cases ie ','
769 as a parameter delimiter/separator is single and due
770 to the strsep above is temporarily zeroed. */
772 /* NB: password legally can have multiple commas and
773 the only illegal character in a password is null */
775 if ((value[temp_len] == 0) &&
776 (value[temp_len+1] == separator[0])) {
778 value[temp_len] = separator[0];
779 temp_len+=2; /* move after the second comma */
780 while(value[temp_len] != 0) {
781 if (value[temp_len] == separator[0]) {
782 if (value[temp_len+1] ==
784 /* skip second comma */
787 /* single comma indicating start
794 if(value[temp_len] == 0) {
798 /* point option to start of next parm */
799 options = value + temp_len + 1;
801 /* go from value to value + temp_len condensing
802 double commas to singles. Note that this ends up
803 allocating a few bytes too many, which is ok */
804 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
805 if(vol->password == NULL) {
806 printk("CIFS: no memory for pass\n");
809 for(i=0,j=0;i<temp_len;i++,j++) {
810 vol->password[j] = value[i];
811 if(value[i] == separator[0]
812 && value[i+1] == separator[0]) {
813 /* skip second comma */
817 vol->password[j] = 0;
819 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
820 if(vol->password == NULL) {
821 printk("CIFS: no memory for pass\n");
824 strcpy(vol->password, value);
826 } else if (strnicmp(data, "ip", 2) == 0) {
827 if (!value || !*value) {
829 } else if (strnlen(value, 35) < 35) {
832 printk(KERN_WARNING "CIFS: ip address too long\n");
835 } else if ((strnicmp(data, "unc", 3) == 0)
836 || (strnicmp(data, "target", 6) == 0)
837 || (strnicmp(data, "path", 4) == 0)) {
838 if (!value || !*value) {
840 "CIFS: invalid path to network resource\n");
841 return 1; /* needs_arg; */
843 if ((temp_len = strnlen(value, 300)) < 300) {
844 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
847 strcpy(vol->UNC,value);
848 if (strncmp(vol->UNC, "//", 2) == 0) {
851 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
853 "CIFS: UNC Path does not begin with // or \\\\ \n");
857 printk(KERN_WARNING "CIFS: UNC name too long\n");
860 } else if ((strnicmp(data, "domain", 3) == 0)
861 || (strnicmp(data, "workgroup", 5) == 0)) {
862 if (!value || !*value) {
863 printk(KERN_WARNING "CIFS: invalid domain name\n");
864 return 1; /* needs_arg; */
866 /* BB are there cases in which a comma can be valid in
867 a domain name and need special handling? */
868 if (strnlen(value, 65) < 65) {
869 vol->domainname = value;
870 cFYI(1, ("Domain name set"));
872 printk(KERN_WARNING "CIFS: domain name too long\n");
875 } else if (strnicmp(data, "iocharset", 9) == 0) {
876 if (!value || !*value) {
877 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
878 return 1; /* needs_arg; */
880 if (strnlen(value, 65) < 65) {
881 if(strnicmp(value,"default",7))
882 vol->iocharset = value;
883 /* if iocharset not set load_nls_default used by caller */
884 cFYI(1, ("iocharset set to %s",value));
886 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
889 } else if (strnicmp(data, "uid", 3) == 0) {
890 if (value && *value) {
892 simple_strtoul(value, &value, 0);
894 } else if (strnicmp(data, "gid", 3) == 0) {
895 if (value && *value) {
897 simple_strtoul(value, &value, 0);
899 } else if (strnicmp(data, "file_mode", 4) == 0) {
900 if (value && *value) {
902 simple_strtoul(value, &value, 0);
904 } else if (strnicmp(data, "dir_mode", 4) == 0) {
905 if (value && *value) {
907 simple_strtoul(value, &value, 0);
909 } else if (strnicmp(data, "dirmode", 4) == 0) {
910 if (value && *value) {
912 simple_strtoul(value, &value, 0);
914 } else if (strnicmp(data, "port", 4) == 0) {
915 if (value && *value) {
917 simple_strtoul(value, &value, 0);
919 } else if (strnicmp(data, "rsize", 5) == 0) {
920 if (value && *value) {
922 simple_strtoul(value, &value, 0);
924 } else if (strnicmp(data, "wsize", 5) == 0) {
925 if (value && *value) {
927 simple_strtoul(value, &value, 0);
929 } else if (strnicmp(data, "sockopt", 5) == 0) {
930 if (value && *value) {
932 simple_strtoul(value, &value, 0);
934 } else if (strnicmp(data, "netbiosname", 4) == 0) {
935 if (!value || !*value || (*value == ' ')) {
936 cFYI(1,("invalid (empty) netbiosname specified"));
938 memset(vol->source_rfc1001_name,0x20,15);
940 /* BB are there cases in which a comma can be
941 valid in this workstation netbios name (and need
942 special handling)? */
944 /* We do not uppercase netbiosname for user */
948 vol->source_rfc1001_name[i] = value[i];
950 /* The string has 16th byte zero still from
951 set at top of the function */
952 if((i==15) && (value[i] != 0))
953 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
955 } else if (strnicmp(data, "credentials", 4) == 0) {
957 } else if (strnicmp(data, "version", 3) == 0) {
959 } else if (strnicmp(data, "guest",5) == 0) {
961 } else if (strnicmp(data, "rw", 2) == 0) {
963 } else if ((strnicmp(data, "suid", 4) == 0) ||
964 (strnicmp(data, "nosuid", 6) == 0) ||
965 (strnicmp(data, "exec", 4) == 0) ||
966 (strnicmp(data, "noexec", 6) == 0) ||
967 (strnicmp(data, "nodev", 5) == 0) ||
968 (strnicmp(data, "noauto", 6) == 0) ||
969 (strnicmp(data, "dev", 3) == 0)) {
970 /* The mount tool or mount.cifs helper (if present)
971 uses these opts to set flags, and the flags are read
972 by the kernel vfs layer before we get here (ie
973 before read super) so there is no point trying to
974 parse these options again and set anything and it
975 is ok to just ignore them */
977 } else if (strnicmp(data, "ro", 2) == 0) {
979 } else if (strnicmp(data, "hard", 4) == 0) {
981 } else if (strnicmp(data, "soft", 4) == 0) {
983 } else if (strnicmp(data, "perm", 4) == 0) {
985 } else if (strnicmp(data, "noperm", 6) == 0) {
987 } else if (strnicmp(data, "mapchars", 8) == 0) {
989 } else if (strnicmp(data, "nomapchars", 10) == 0) {
991 } else if (strnicmp(data, "setuids", 7) == 0) {
993 } else if (strnicmp(data, "nosetuids", 9) == 0) {
995 } else if (strnicmp(data, "nohard", 6) == 0) {
997 } else if (strnicmp(data, "nosoft", 6) == 0) {
999 } else if (strnicmp(data, "nointr", 6) == 0) {
1001 } else if (strnicmp(data, "intr", 4) == 0) {
1003 } else if (strnicmp(data, "serverino",7) == 0) {
1004 vol->server_ino = 1;
1005 } else if (strnicmp(data, "noserverino",9) == 0) {
1006 vol->server_ino = 0;
1007 } else if (strnicmp(data, "acl",3) == 0) {
1008 vol->no_psx_acl = 0;
1009 } else if (strnicmp(data, "noacl",5) == 0) {
1010 vol->no_psx_acl = 1;
1011 } else if (strnicmp(data, "direct",6) == 0) {
1013 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1015 } else if (strnicmp(data, "in6_addr",8) == 0) {
1016 if (!value || !*value) {
1017 vol->in6_addr = NULL;
1018 } else if (strnlen(value, 49) == 48) {
1019 vol->in6_addr = value;
1021 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1024 } else if (strnicmp(data, "noac", 4) == 0) {
1025 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1027 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1029 if (vol->UNC == NULL) {
1030 if(devname == NULL) {
1031 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1034 if ((temp_len = strnlen(devname, 300)) < 300) {
1035 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1036 if(vol->UNC == NULL)
1038 strcpy(vol->UNC,devname);
1039 if (strncmp(vol->UNC, "//", 2) == 0) {
1042 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1043 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1047 printk(KERN_WARNING "CIFS: UNC name too long\n");
1051 if(vol->UNCip == NULL)
1052 vol->UNCip = &vol->UNC[2];
1057 static struct cifsSesInfo *
1058 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1059 struct in6_addr *target_ip6_addr,
1060 char *userName, struct TCP_Server_Info **psrvTcp)
1062 struct list_head *tmp;
1063 struct cifsSesInfo *ses;
1065 read_lock(&GlobalSMBSeslock);
1067 list_for_each(tmp, &GlobalSMBSessionList) {
1068 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1070 if((target_ip_addr &&
1071 (ses->server->addr.sockAddr.sin_addr.s_addr
1072 == target_ip_addr->s_addr)) || (target_ip6_addr
1073 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1074 target_ip6_addr,sizeof(*target_ip6_addr)))){
1075 /* BB lock server and tcp session and increment use count here?? */
1076 *psrvTcp = ses->server; /* found a match on the TCP session */
1077 /* BB check if reconnection needed */
1079 (ses->userName, userName,
1080 MAX_USERNAME_SIZE) == 0){
1081 read_unlock(&GlobalSMBSeslock);
1082 return ses; /* found exact match on both tcp and SMB sessions */
1086 /* else tcp and smb sessions need reconnection */
1088 read_unlock(&GlobalSMBSeslock);
1092 static struct cifsTconInfo *
1093 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1095 struct list_head *tmp;
1096 struct cifsTconInfo *tcon;
1098 read_lock(&GlobalSMBSeslock);
1099 list_for_each(tmp, &GlobalTreeConnectionList) {
1100 cFYI(1, ("Next tcon - "));
1101 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1103 if (tcon->ses->server) {
1105 (" old ip addr: %x == new ip %x ?",
1106 tcon->ses->server->addr.sockAddr.sin_addr.
1107 s_addr, new_target_ip_addr));
1108 if (tcon->ses->server->addr.sockAddr.sin_addr.
1109 s_addr == new_target_ip_addr) {
1110 /* BB lock tcon and server and tcp session and increment use count here? */
1111 /* found a match on the TCP session */
1112 /* BB check if reconnection needed */
1113 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1114 tcon->treeName, uncName));
1116 (tcon->treeName, uncName,
1117 MAX_TREE_SIZE) == 0) {
1119 ("Matched UNC, old user: %s == new: %s ?",
1120 tcon->treeName, uncName));
1122 (tcon->ses->userName,
1124 MAX_USERNAME_SIZE) == 0) {
1125 read_unlock(&GlobalSMBSeslock);
1126 return tcon;/* also matched user (smb session)*/
1133 read_unlock(&GlobalSMBSeslock);
1138 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1139 const char *old_path, const struct nls_table *nls_codepage,
1142 unsigned char *referrals = NULL;
1143 unsigned int num_referrals;
1146 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1147 &num_referrals, &referrals, remap);
1149 /* BB Add in code to: if valid refrl, if not ip address contact
1150 the helper that resolves tcp names, mount to it, try to
1151 tcon to it unmount it if fail */
1160 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1161 const char *old_path, const struct nls_table *nls_codepage,
1162 unsigned int *pnum_referrals,
1163 unsigned char ** preferrals, int remap)
1168 *pnum_referrals = 0;
1170 if (pSesInfo->ipc_tid == 0) {
1171 temp_unc = kmalloc(2 /* for slashes */ +
1172 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1173 + 1 + 4 /* slash IPC$ */ + 2,
1175 if (temp_unc == NULL)
1179 strcpy(temp_unc + 2, pSesInfo->serverName);
1180 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1181 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1183 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1187 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1188 pnum_referrals, nls_codepage, remap);
1193 /* See RFC1001 section 14 on representation of Netbios names */
1194 static void rfc1002mangle(char * target,char * source, unsigned int length)
1198 for(i=0,j=0;i<(length);i++) {
1199 /* mask a nibble at a time and encode */
1200 target[j] = 'A' + (0x0F & (source[i] >> 4));
1201 target[j+1] = 'A' + (0x0F & source[i]);
1209 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1210 char * netbios_name)
1214 __be16 orig_port = 0;
1216 if(*csocket == NULL) {
1217 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1219 cERROR(1, ("Error %d creating socket",rc));
1223 /* BB other socket options to set KEEPALIVE, NODELAY? */
1224 cFYI(1,("Socket created"));
1225 (*csocket)->sk->sk_allocation = GFP_NOFS;
1229 psin_server->sin_family = AF_INET;
1230 if(psin_server->sin_port) { /* user overrode default port */
1231 rc = (*csocket)->ops->connect(*csocket,
1232 (struct sockaddr *) psin_server,
1233 sizeof (struct sockaddr_in),0);
1239 /* save original port so we can retry user specified port
1240 later if fall back ports fail this time */
1241 orig_port = psin_server->sin_port;
1243 /* do not retry on the same port we just failed on */
1244 if(psin_server->sin_port != htons(CIFS_PORT)) {
1245 psin_server->sin_port = htons(CIFS_PORT);
1247 rc = (*csocket)->ops->connect(*csocket,
1248 (struct sockaddr *) psin_server,
1249 sizeof (struct sockaddr_in),0);
1255 psin_server->sin_port = htons(RFC1001_PORT);
1256 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1257 psin_server, sizeof (struct sockaddr_in),0);
1262 /* give up here - unless we want to retry on different
1263 protocol families some day */
1266 psin_server->sin_port = orig_port;
1267 cFYI(1,("Error %d connecting to server via ipv4",rc));
1268 sock_release(*csocket);
1272 /* Eventually check for other socket options to change from
1273 the default. sock_setsockopt not used because it expects
1274 user space buffer */
1275 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1277 /* send RFC1001 sessinit */
1279 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1280 /* some servers require RFC1001 sessinit before sending
1281 negprot - BB check reconnection in case where second
1282 sessinit is sent but no second negprot */
1283 struct rfc1002_session_packet * ses_init_buf;
1284 struct smb_hdr * smb_buf;
1285 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1287 ses_init_buf->trailer.session_req.called_len = 32;
1288 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1289 DEFAULT_CIFS_CALLED_NAME,16);
1290 ses_init_buf->trailer.session_req.calling_len = 32;
1291 /* calling name ends in null (byte 16) from old smb
1293 if(netbios_name && (netbios_name[0] !=0)) {
1294 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1297 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1298 "LINUX_CIFS_CLNT",16);
1300 ses_init_buf->trailer.session_req.scope1 = 0;
1301 ses_init_buf->trailer.session_req.scope2 = 0;
1302 smb_buf = (struct smb_hdr *)ses_init_buf;
1303 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1304 smb_buf->smb_buf_length = 0x81000044;
1305 rc = smb_send(*csocket, smb_buf, 0x44,
1306 (struct sockaddr *)psin_server);
1307 kfree(ses_init_buf);
1309 /* else the negprot may still work without this
1310 even though malloc failed */
1318 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1322 __be16 orig_port = 0;
1324 if(*csocket == NULL) {
1325 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1327 cERROR(1, ("Error %d creating ipv6 socket",rc));
1331 /* BB other socket options to set KEEPALIVE, NODELAY? */
1332 cFYI(1,("ipv6 Socket created"));
1333 (*csocket)->sk->sk_allocation = GFP_NOFS;
1337 psin_server->sin6_family = AF_INET6;
1339 if(psin_server->sin6_port) { /* user overrode default port */
1340 rc = (*csocket)->ops->connect(*csocket,
1341 (struct sockaddr *) psin_server,
1342 sizeof (struct sockaddr_in6),0);
1348 /* save original port so we can retry user specified port
1349 later if fall back ports fail this time */
1351 orig_port = psin_server->sin6_port;
1352 /* do not retry on the same port we just failed on */
1353 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1354 psin_server->sin6_port = htons(CIFS_PORT);
1356 rc = (*csocket)->ops->connect(*csocket,
1357 (struct sockaddr *) psin_server,
1358 sizeof (struct sockaddr_in6),0);
1364 psin_server->sin6_port = htons(RFC1001_PORT);
1365 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1366 psin_server, sizeof (struct sockaddr_in6),0);
1371 /* give up here - unless we want to retry on different
1372 protocol families some day */
1375 psin_server->sin6_port = orig_port;
1376 cFYI(1,("Error %d connecting to server via ipv6",rc));
1377 sock_release(*csocket);
1381 /* Eventually check for other socket options to change from
1382 the default. sock_setsockopt not used because it expects
1383 user space buffer */
1384 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1390 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1391 char *mount_data, const char *devname)
1395 int address_type = AF_INET;
1396 struct socket *csocket = NULL;
1397 struct sockaddr_in sin_server;
1398 struct sockaddr_in6 sin_server6;
1399 struct smb_vol volume_info;
1400 struct cifsSesInfo *pSesInfo = NULL;
1401 struct cifsSesInfo *existingCifsSes = NULL;
1402 struct cifsTconInfo *tcon = NULL;
1403 struct TCP_Server_Info *srvTcp = NULL;
1407 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1409 memset(&volume_info,0,sizeof(struct smb_vol));
1410 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1412 kfree(volume_info.UNC);
1413 if(volume_info.password)
1414 kfree(volume_info.password);
1419 if (volume_info.username) {
1420 /* BB fixme parse for domain name here */
1421 cFYI(1, ("Username: %s ", volume_info.username));
1424 cifserror("No username specified ");
1425 /* In userspace mount helper we can get user name from alternate
1426 locations such as env variables and files on disk */
1428 kfree(volume_info.UNC);
1429 if(volume_info.password)
1430 kfree(volume_info.password);
1435 if (volume_info.UNCip && volume_info.UNC) {
1436 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1439 /* not ipv4 address, try ipv6 */
1440 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1442 address_type = AF_INET6;
1444 address_type = AF_INET;
1448 /* we failed translating address */
1450 kfree(volume_info.UNC);
1451 if(volume_info.password)
1452 kfree(volume_info.password);
1457 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1460 } else if (volume_info.UNCip){
1461 /* BB using ip addr as server name connect to the DFS root below */
1462 cERROR(1,("Connecting to DFS root not implemented yet"));
1464 kfree(volume_info.UNC);
1465 if(volume_info.password)
1466 kfree(volume_info.password);
1469 } else /* which servers DFS root would we conect to */ {
1471 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1473 kfree(volume_info.UNC);
1474 if(volume_info.password)
1475 kfree(volume_info.password);
1480 /* this is needed for ASCII cp to Unicode converts */
1481 if(volume_info.iocharset == NULL) {
1482 cifs_sb->local_nls = load_nls_default();
1483 /* load_nls_default can not return null */
1485 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1486 if(cifs_sb->local_nls == NULL) {
1487 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1489 kfree(volume_info.UNC);
1490 if(volume_info.password)
1491 kfree(volume_info.password);
1497 if(address_type == AF_INET)
1498 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1499 NULL /* no ipv6 addr */,
1500 volume_info.username, &srvTcp);
1501 else if(address_type == AF_INET6)
1502 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1503 &sin_server6.sin6_addr,
1504 volume_info.username, &srvTcp);
1507 kfree(volume_info.UNC);
1508 if(volume_info.password)
1509 kfree(volume_info.password);
1516 cFYI(1, ("Existing tcp session with server found "));
1517 } else { /* create socket */
1518 if(volume_info.port)
1519 sin_server.sin_port = htons(volume_info.port);
1521 sin_server.sin_port = 0;
1522 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1525 ("Error connecting to IPv4 socket. Aborting operation"));
1527 sock_release(csocket);
1529 kfree(volume_info.UNC);
1530 if(volume_info.password)
1531 kfree(volume_info.password);
1536 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1537 if (srvTcp == NULL) {
1539 sock_release(csocket);
1541 kfree(volume_info.UNC);
1542 if(volume_info.password)
1543 kfree(volume_info.password);
1547 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1548 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1549 atomic_set(&srvTcp->inFlight,0);
1550 /* BB Add code for ipv6 case too */
1551 srvTcp->ssocket = csocket;
1552 srvTcp->protocolType = IPV4;
1553 init_waitqueue_head(&srvTcp->response_q);
1554 init_waitqueue_head(&srvTcp->request_q);
1555 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1556 /* at this point we are the only ones with the pointer
1557 to the struct since the kernel thread not created yet
1558 so no need to spinlock this init of tcpStatus */
1559 srvTcp->tcpStatus = CifsNew;
1560 init_MUTEX(&srvTcp->tcpSem);
1561 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1562 CLONE_FS | CLONE_FILES | CLONE_VM);
1565 sock_release(csocket);
1567 kfree(volume_info.UNC);
1568 if(volume_info.password)
1569 kfree(volume_info.password);
1574 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1575 srvTcp->sequence_number = 0;
1579 if (existingCifsSes) {
1580 pSesInfo = existingCifsSes;
1581 cFYI(1, ("Existing smb sess found "));
1582 if(volume_info.password)
1583 kfree(volume_info.password);
1584 /* volume_info.UNC freed at end of function */
1586 cFYI(1, ("Existing smb sess not found "));
1587 pSesInfo = sesInfoAlloc();
1588 if (pSesInfo == NULL)
1591 pSesInfo->server = srvTcp;
1592 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1593 NIPQUAD(sin_server.sin_addr.s_addr));
1597 /* volume_info.password freed at unmount */
1598 if (volume_info.password)
1599 pSesInfo->password = volume_info.password;
1600 if (volume_info.username)
1601 strncpy(pSesInfo->userName,
1602 volume_info.username,MAX_USERNAME_SIZE);
1603 if (volume_info.domainname)
1604 strncpy(pSesInfo->domainName,
1605 volume_info.domainname,MAX_USERNAME_SIZE);
1606 pSesInfo->linux_uid = volume_info.linux_uid;
1607 down(&pSesInfo->sesSem);
1608 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1609 up(&pSesInfo->sesSem);
1611 atomic_inc(&srvTcp->socketUseCount);
1613 if(volume_info.password)
1614 kfree(volume_info.password);
1617 /* search for existing tcon to this server share */
1619 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1620 cifs_sb->rsize = volume_info.rsize;
1622 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1623 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1624 cifs_sb->wsize = volume_info.wsize;
1626 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1627 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1628 cifs_sb->rsize = PAGE_CACHE_SIZE;
1629 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1631 cifs_sb->mnt_uid = volume_info.linux_uid;
1632 cifs_sb->mnt_gid = volume_info.linux_gid;
1633 cifs_sb->mnt_file_mode = volume_info.file_mode;
1634 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1635 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1637 if(volume_info.noperm)
1638 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1639 if(volume_info.setuids)
1640 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1641 if(volume_info.server_ino)
1642 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1643 if(volume_info.remap)
1644 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1645 if(volume_info.no_xattr)
1646 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1647 if(volume_info.direct_io) {
1648 cERROR(1,("mounting share using direct i/o"));
1649 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1653 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1654 volume_info.username);
1656 cFYI(1, ("Found match on UNC path "));
1657 /* we can have only one retry value for a connection
1658 to a share so for resources mounted more than once
1659 to the same server share the last value passed in
1660 for the retry flag is used */
1661 tcon->retry = volume_info.retry;
1663 tcon = tconInfoAlloc();
1667 /* check for null share name ie connect to dfs root */
1669 /* BB check if this works for exactly length three strings */
1670 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1671 && (strchr(volume_info.UNC + 3, '/') ==
1673 rc = connect_to_dfs_path(xid, pSesInfo,
1674 "", cifs_sb->local_nls,
1675 cifs_sb->mnt_cifs_flags &
1676 CIFS_MOUNT_MAP_SPECIAL_CHR);
1678 kfree(volume_info.UNC);
1682 rc = CIFSTCon(xid, pSesInfo,
1684 tcon, cifs_sb->local_nls);
1685 cFYI(1, ("CIFS Tcon rc = %d", rc));
1688 atomic_inc(&pSesInfo->inUse);
1689 tcon->retry = volume_info.retry;
1695 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1696 sb->s_maxbytes = (u64) 1 << 63;
1698 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1701 sb->s_time_gran = 100;
1703 /* on error free sesinfo and tcon struct if needed */
1705 /* if session setup failed, use count is zero but
1706 we still need to free cifsd thread */
1707 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1708 spin_lock(&GlobalMid_Lock);
1709 srvTcp->tcpStatus = CifsExiting;
1710 spin_unlock(&GlobalMid_Lock);
1712 send_sig(SIGKILL,srvTcp->tsk,1);
1714 /* If find_unc succeeded then rc == 0 so we can not end */
1715 if (tcon) /* up accidently freeing someone elses tcon struct */
1717 if (existingCifsSes == NULL) {
1719 if ((pSesInfo->server) &&
1720 (pSesInfo->status == CifsGood)) {
1722 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1723 /* if the socketUseCount is now zero */
1724 if((temp_rc == -ESHUTDOWN) &&
1725 (pSesInfo->server->tsk))
1726 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1728 cFYI(1, ("No session or bad tcon"));
1729 sesInfoFree(pSesInfo);
1730 /* pSesInfo = NULL; */
1734 atomic_inc(&tcon->useCount);
1735 cifs_sb->tcon = tcon;
1736 tcon->ses = pSesInfo;
1738 /* do not care if following two calls succeed - informational only */
1739 CIFSSMBQFSDeviceInfo(xid, tcon);
1740 CIFSSMBQFSAttributeInfo(xid, tcon);
1741 if (tcon->ses->capabilities & CAP_UNIX) {
1742 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1743 if(!volume_info.no_psx_acl) {
1744 if(CIFS_UNIX_POSIX_ACL_CAP &
1745 le64_to_cpu(tcon->fsUnixInfo.Capability))
1746 cFYI(1,("server negotiated posix acl support"));
1747 sb->s_flags |= MS_POSIXACL;
1753 /* volume_info.password is freed above when existing session found
1754 (in which case it is not needed anymore) but when new sesion is created
1755 the password ptr is put in the new session structure (in which case the
1756 password will be freed at unmount time) */
1758 kfree(volume_info.UNC);
1764 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1765 char session_key[CIFS_SESSION_KEY_SIZE],
1766 const struct nls_table *nls_codepage)
1768 struct smb_hdr *smb_buffer;
1769 struct smb_hdr *smb_buffer_response;
1770 SESSION_SETUP_ANDX *pSMB;
1771 SESSION_SETUP_ANDX *pSMBr;
1776 int remaining_words = 0;
1777 int bytes_returned = 0;
1782 cFYI(1, ("In sesssetup "));
1785 user = ses->userName;
1786 domain = ses->domainName;
1787 smb_buffer = cifs_buf_get();
1788 if (smb_buffer == NULL) {
1791 smb_buffer_response = smb_buffer;
1792 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1794 /* send SMBsessionSetup here */
1795 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1796 NULL /* no tCon exists yet */ , 13 /* wct */ );
1798 pSMB->req_no_secext.AndXCommand = 0xFF;
1799 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1800 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1802 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1803 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1805 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1806 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1807 if (ses->capabilities & CAP_UNICODE) {
1808 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1809 capabilities |= CAP_UNICODE;
1811 if (ses->capabilities & CAP_STATUS32) {
1812 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1813 capabilities |= CAP_STATUS32;
1815 if (ses->capabilities & CAP_DFS) {
1816 smb_buffer->Flags2 |= SMBFLG2_DFS;
1817 capabilities |= CAP_DFS;
1819 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1821 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1822 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1824 pSMB->req_no_secext.CaseSensitivePasswordLength =
1825 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1826 bcc_ptr = pByteArea(smb_buffer);
1827 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1828 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1829 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1830 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1832 if (ses->capabilities & CAP_UNICODE) {
1833 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1838 bytes_returned = 0; /* skill null user */
1841 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1843 /* convert number of 16 bit words to bytes */
1844 bcc_ptr += 2 * bytes_returned;
1845 bcc_ptr += 2; /* trailing null */
1848 cifs_strtoUCS((wchar_t *) bcc_ptr,
1849 "CIFS_LINUX_DOM", 32, nls_codepage);
1852 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1854 bcc_ptr += 2 * bytes_returned;
1857 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1859 bcc_ptr += 2 * bytes_returned;
1861 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1863 bcc_ptr += 2 * bytes_returned;
1866 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1868 bcc_ptr += 2 * bytes_returned;
1872 strncpy(bcc_ptr, user, 200);
1873 bcc_ptr += strnlen(user, 200);
1877 if (domain == NULL) {
1878 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1879 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1881 strncpy(bcc_ptr, domain, 64);
1882 bcc_ptr += strnlen(domain, 64);
1886 strcpy(bcc_ptr, "Linux version ");
1887 bcc_ptr += strlen("Linux version ");
1888 strcpy(bcc_ptr, system_utsname.release);
1889 bcc_ptr += strlen(system_utsname.release) + 1;
1890 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1891 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1893 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1894 smb_buffer->smb_buf_length += count;
1895 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1897 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1898 &bytes_returned, 1);
1900 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1901 } else if ((smb_buffer_response->WordCount == 3)
1902 || (smb_buffer_response->WordCount == 4)) {
1903 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1904 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1905 if (action & GUEST_LOGIN)
1906 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1907 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1908 cFYI(1, ("UID = %d ", ses->Suid));
1909 /* response can have either 3 or 4 word count - Samba sends 3 */
1910 bcc_ptr = pByteArea(smb_buffer_response);
1911 if ((pSMBr->resp.hdr.WordCount == 3)
1912 || ((pSMBr->resp.hdr.WordCount == 4)
1913 && (blob_len < pSMBr->resp.ByteCount))) {
1914 if (pSMBr->resp.hdr.WordCount == 4)
1915 bcc_ptr += blob_len;
1917 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1918 if ((long) (bcc_ptr) % 2) {
1920 (BCC(smb_buffer_response) - 1) /2;
1921 bcc_ptr++; /* Unicode strings must be word aligned */
1924 BCC(smb_buffer_response) / 2;
1927 UniStrnlen((wchar_t *) bcc_ptr,
1928 remaining_words - 1);
1929 /* We look for obvious messed up bcc or strings in response so we do not go off
1930 the end since (at least) WIN2K and Windows XP have a major bug in not null
1931 terminating last Unicode string in response */
1932 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1933 if(ses->serverOS == NULL)
1934 goto sesssetup_nomem;
1935 cifs_strfromUCS_le(ses->serverOS,
1936 (wchar_t *)bcc_ptr, len,nls_codepage);
1937 bcc_ptr += 2 * (len + 1);
1938 remaining_words -= len + 1;
1939 ses->serverOS[2 * len] = 0;
1940 ses->serverOS[1 + (2 * len)] = 0;
1941 if (remaining_words > 0) {
1942 len = UniStrnlen((wchar_t *)bcc_ptr,
1944 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
1945 if(ses->serverNOS == NULL)
1946 goto sesssetup_nomem;
1947 cifs_strfromUCS_le(ses->serverNOS,
1948 (wchar_t *)bcc_ptr,len,nls_codepage);
1949 bcc_ptr += 2 * (len + 1);
1950 ses->serverNOS[2 * len] = 0;
1951 ses->serverNOS[1 + (2 * len)] = 0;
1952 if(strncmp(ses->serverNOS,
1953 "NT LAN Manager 4",16) == 0) {
1954 cFYI(1,("NT4 server"));
1955 ses->flags |= CIFS_SES_NT4;
1957 remaining_words -= len + 1;
1958 if (remaining_words > 0) {
1959 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1960 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1962 kcalloc(1, 2*(len+1),GFP_KERNEL);
1963 if(ses->serverDomain == NULL)
1964 goto sesssetup_nomem;
1965 cifs_strfromUCS_le(ses->serverDomain,
1966 (wchar_t *)bcc_ptr,len,nls_codepage);
1967 bcc_ptr += 2 * (len + 1);
1968 ses->serverDomain[2*len] = 0;
1969 ses->serverDomain[1+(2*len)] = 0;
1970 } /* else no more room so create dummy domain string */
1973 kcalloc(1, 2, GFP_KERNEL);
1974 } else { /* no room so create dummy domain and NOS string */
1975 /* if these kcallocs fail not much we
1976 can do, but better to not fail the
1979 kcalloc(1, 2, GFP_KERNEL);
1981 kcalloc(1, 2, GFP_KERNEL);
1983 } else { /* ASCII */
1984 len = strnlen(bcc_ptr, 1024);
1985 if (((long) bcc_ptr + len) - (long)
1986 pByteArea(smb_buffer_response)
1987 <= BCC(smb_buffer_response)) {
1988 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
1989 if(ses->serverOS == NULL)
1990 goto sesssetup_nomem;
1991 strncpy(ses->serverOS,bcc_ptr, len);
1994 bcc_ptr[0] = 0; /* null terminate the string */
1997 len = strnlen(bcc_ptr, 1024);
1998 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
1999 if(ses->serverNOS == NULL)
2000 goto sesssetup_nomem;
2001 strncpy(ses->serverNOS, bcc_ptr, len);
2006 len = strnlen(bcc_ptr, 1024);
2007 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2008 if(ses->serverDomain == NULL)
2009 goto sesssetup_nomem;
2010 strncpy(ses->serverDomain, bcc_ptr, len);
2016 ("Variable field of length %d extends beyond end of smb ",
2021 (" Security Blob Length extends beyond end of SMB"));
2025 (" Invalid Word count %d: ",
2026 smb_buffer_response->WordCount));
2029 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2030 since that could make reconnection harder, and
2031 reconnection might be needed to free memory */
2033 cifs_buf_release(smb_buffer);
2039 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2040 char *SecurityBlob,int SecurityBlobLength,
2041 const struct nls_table *nls_codepage)
2043 struct smb_hdr *smb_buffer;
2044 struct smb_hdr *smb_buffer_response;
2045 SESSION_SETUP_ANDX *pSMB;
2046 SESSION_SETUP_ANDX *pSMBr;
2051 int remaining_words = 0;
2052 int bytes_returned = 0;
2057 cFYI(1, ("In spnego sesssetup "));
2060 user = ses->userName;
2061 domain = ses->domainName;
2063 smb_buffer = cifs_buf_get();
2064 if (smb_buffer == NULL) {
2067 smb_buffer_response = smb_buffer;
2068 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2070 /* send SMBsessionSetup here */
2071 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2072 NULL /* no tCon exists yet */ , 12 /* wct */ );
2073 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2074 pSMB->req.AndXCommand = 0xFF;
2075 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2076 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2078 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2079 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2081 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2082 CAP_EXTENDED_SECURITY;
2083 if (ses->capabilities & CAP_UNICODE) {
2084 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2085 capabilities |= CAP_UNICODE;
2087 if (ses->capabilities & CAP_STATUS32) {
2088 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2089 capabilities |= CAP_STATUS32;
2091 if (ses->capabilities & CAP_DFS) {
2092 smb_buffer->Flags2 |= SMBFLG2_DFS;
2093 capabilities |= CAP_DFS;
2095 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2097 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2098 bcc_ptr = pByteArea(smb_buffer);
2099 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2100 bcc_ptr += SecurityBlobLength;
2102 if (ses->capabilities & CAP_UNICODE) {
2103 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2108 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
2109 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2110 bcc_ptr += 2; /* trailing null */
2113 cifs_strtoUCS((wchar_t *) bcc_ptr,
2114 "CIFS_LINUX_DOM", 32, nls_codepage);
2117 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2119 bcc_ptr += 2 * bytes_returned;
2122 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2124 bcc_ptr += 2 * bytes_returned;
2126 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2128 bcc_ptr += 2 * bytes_returned;
2131 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2133 bcc_ptr += 2 * bytes_returned;
2136 strncpy(bcc_ptr, user, 200);
2137 bcc_ptr += strnlen(user, 200);
2140 if (domain == NULL) {
2141 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2142 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2144 strncpy(bcc_ptr, domain, 64);
2145 bcc_ptr += strnlen(domain, 64);
2149 strcpy(bcc_ptr, "Linux version ");
2150 bcc_ptr += strlen("Linux version ");
2151 strcpy(bcc_ptr, system_utsname.release);
2152 bcc_ptr += strlen(system_utsname.release) + 1;
2153 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2154 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2156 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2157 smb_buffer->smb_buf_length += count;
2158 pSMB->req.ByteCount = cpu_to_le16(count);
2160 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2161 &bytes_returned, 1);
2163 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2164 } else if ((smb_buffer_response->WordCount == 3)
2165 || (smb_buffer_response->WordCount == 4)) {
2166 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2168 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2169 if (action & GUEST_LOGIN)
2170 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2172 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2173 cFYI(1, ("UID = %d ", ses->Suid));
2174 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2176 /* BB Fix below to make endian neutral !! */
2178 if ((pSMBr->resp.hdr.WordCount == 3)
2179 || ((pSMBr->resp.hdr.WordCount == 4)
2181 pSMBr->resp.ByteCount))) {
2182 if (pSMBr->resp.hdr.WordCount == 4) {
2186 ("Security Blob Length %d ",
2190 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2191 if ((long) (bcc_ptr) % 2) {
2193 (BCC(smb_buffer_response)
2195 bcc_ptr++; /* Unicode strings must be word aligned */
2199 (smb_buffer_response) / 2;
2202 UniStrnlen((wchar_t *) bcc_ptr,
2203 remaining_words - 1);
2204 /* We look for obvious messed up bcc or strings in response so we do not go off
2205 the end since (at least) WIN2K and Windows XP have a major bug in not null
2206 terminating last Unicode string in response */
2208 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2209 cifs_strfromUCS_le(ses->serverOS,
2213 bcc_ptr += 2 * (len + 1);
2214 remaining_words -= len + 1;
2215 ses->serverOS[2 * len] = 0;
2216 ses->serverOS[1 + (2 * len)] = 0;
2217 if (remaining_words > 0) {
2218 len = UniStrnlen((wchar_t *)bcc_ptr,
2222 kcalloc(1, 2 * (len + 1),
2224 cifs_strfromUCS_le(ses->serverNOS,
2228 bcc_ptr += 2 * (len + 1);
2229 ses->serverNOS[2 * len] = 0;
2230 ses->serverNOS[1 + (2 * len)] = 0;
2231 remaining_words -= len + 1;
2232 if (remaining_words > 0) {
2233 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2234 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2235 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2236 cifs_strfromUCS_le(ses->serverDomain,
2240 bcc_ptr += 2*(len+1);
2241 ses->serverDomain[2*len] = 0;
2242 ses->serverDomain[1+(2*len)] = 0;
2243 } /* else no more room so create dummy domain string */
2246 kcalloc(1, 2,GFP_KERNEL);
2247 } else { /* no room so create dummy domain and NOS string */
2248 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2249 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2251 } else { /* ASCII */
2253 len = strnlen(bcc_ptr, 1024);
2254 if (((long) bcc_ptr + len) - (long)
2255 pByteArea(smb_buffer_response)
2256 <= BCC(smb_buffer_response)) {
2257 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2258 strncpy(ses->serverOS, bcc_ptr, len);
2261 bcc_ptr[0] = 0; /* null terminate the string */
2264 len = strnlen(bcc_ptr, 1024);
2265 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2266 strncpy(ses->serverNOS, bcc_ptr, len);
2271 len = strnlen(bcc_ptr, 1024);
2272 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2273 strncpy(ses->serverDomain, bcc_ptr, len);
2279 ("Variable field of length %d extends beyond end of smb ",
2284 (" Security Blob Length extends beyond end of SMB"));
2287 cERROR(1, ("No session structure passed in."));
2291 (" Invalid Word count %d: ",
2292 smb_buffer_response->WordCount));
2297 cifs_buf_release(smb_buffer);
2303 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2304 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2305 const struct nls_table *nls_codepage)
2307 struct smb_hdr *smb_buffer;
2308 struct smb_hdr *smb_buffer_response;
2309 SESSION_SETUP_ANDX *pSMB;
2310 SESSION_SETUP_ANDX *pSMBr;
2314 int remaining_words = 0;
2315 int bytes_returned = 0;
2317 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2318 PNEGOTIATE_MESSAGE SecurityBlob;
2319 PCHALLENGE_MESSAGE SecurityBlob2;
2320 __u32 negotiate_flags, capabilities;
2323 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2326 domain = ses->domainName;
2327 *pNTLMv2_flag = FALSE;
2328 smb_buffer = cifs_buf_get();
2329 if (smb_buffer == NULL) {
2332 smb_buffer_response = smb_buffer;
2333 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2334 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2336 /* send SMBsessionSetup here */
2337 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2338 NULL /* no tCon exists yet */ , 12 /* wct */ );
2339 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2340 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2342 pSMB->req.AndXCommand = 0xFF;
2343 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2344 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2346 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2347 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2349 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2350 CAP_EXTENDED_SECURITY;
2351 if (ses->capabilities & CAP_UNICODE) {
2352 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2353 capabilities |= CAP_UNICODE;
2355 if (ses->capabilities & CAP_STATUS32) {
2356 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2357 capabilities |= CAP_STATUS32;
2359 if (ses->capabilities & CAP_DFS) {
2360 smb_buffer->Flags2 |= SMBFLG2_DFS;
2361 capabilities |= CAP_DFS;
2363 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2365 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2366 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2367 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2368 SecurityBlob->MessageType = NtLmNegotiate;
2370 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2371 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2372 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2374 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2376 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2377 /* setup pointers to domain name and workstation name */
2378 bcc_ptr += SecurityBlobLength;
2380 SecurityBlob->WorkstationName.Buffer = 0;
2381 SecurityBlob->WorkstationName.Length = 0;
2382 SecurityBlob->WorkstationName.MaximumLength = 0;
2384 if (domain == NULL) {
2385 SecurityBlob->DomainName.Buffer = 0;
2386 SecurityBlob->DomainName.Length = 0;
2387 SecurityBlob->DomainName.MaximumLength = 0;
2390 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2391 strncpy(bcc_ptr, domain, 63);
2392 len = strnlen(domain, 64);
2393 SecurityBlob->DomainName.MaximumLength =
2395 SecurityBlob->DomainName.Buffer =
2396 cpu_to_le32((long) &SecurityBlob->
2398 (long) &SecurityBlob->Signature);
2400 SecurityBlobLength += len;
2401 SecurityBlob->DomainName.Length =
2404 if (ses->capabilities & CAP_UNICODE) {
2405 if ((long) bcc_ptr % 2) {
2411 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2413 bcc_ptr += 2 * bytes_returned;
2415 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2417 bcc_ptr += 2 * bytes_returned;
2418 bcc_ptr += 2; /* null terminate Linux version */
2420 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2422 bcc_ptr += 2 * bytes_returned;
2425 bcc_ptr += 2; /* null terminate network opsys string */
2428 bcc_ptr += 2; /* null domain */
2429 } else { /* ASCII */
2430 strcpy(bcc_ptr, "Linux version ");
2431 bcc_ptr += strlen("Linux version ");
2432 strcpy(bcc_ptr, system_utsname.release);
2433 bcc_ptr += strlen(system_utsname.release) + 1;
2434 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2435 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2436 bcc_ptr++; /* empty domain field */
2439 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2440 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2441 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2442 smb_buffer->smb_buf_length += count;
2443 pSMB->req.ByteCount = cpu_to_le16(count);
2445 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2446 &bytes_returned, 1);
2448 if (smb_buffer_response->Status.CifsError ==
2449 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2453 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2454 } else if ((smb_buffer_response->WordCount == 3)
2455 || (smb_buffer_response->WordCount == 4)) {
2456 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2457 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2459 if (action & GUEST_LOGIN)
2460 cFYI(1, (" Guest login"));
2461 /* Do we want to set anything in SesInfo struct when guest login? */
2463 bcc_ptr = pByteArea(smb_buffer_response);
2464 /* response can have either 3 or 4 word count - Samba sends 3 */
2466 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2467 if (SecurityBlob2->MessageType != NtLmChallenge) {
2469 ("Unexpected NTLMSSP message type received %d",
2470 SecurityBlob2->MessageType));
2472 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2473 cFYI(1, ("UID = %d ", ses->Suid));
2474 if ((pSMBr->resp.hdr.WordCount == 3)
2475 || ((pSMBr->resp.hdr.WordCount == 4)
2477 pSMBr->resp.ByteCount))) {
2479 if (pSMBr->resp.hdr.WordCount == 4) {
2480 bcc_ptr += blob_len;
2482 ("Security Blob Length %d ",
2486 cFYI(1, ("NTLMSSP Challenge rcvd "));
2488 memcpy(ses->server->cryptKey,
2489 SecurityBlob2->Challenge,
2490 CIFS_CRYPTO_KEY_SIZE);
2491 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2492 *pNTLMv2_flag = TRUE;
2494 if((SecurityBlob2->NegotiateFlags &
2495 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2496 || (sign_CIFS_PDUs > 1))
2497 ses->server->secMode |=
2498 SECMODE_SIGN_REQUIRED;
2499 if ((SecurityBlob2->NegotiateFlags &
2500 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2501 ses->server->secMode |=
2502 SECMODE_SIGN_ENABLED;
2504 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2505 if ((long) (bcc_ptr) % 2) {
2507 (BCC(smb_buffer_response)
2509 bcc_ptr++; /* Unicode strings must be word aligned */
2513 (smb_buffer_response) / 2;
2516 UniStrnlen((wchar_t *) bcc_ptr,
2517 remaining_words - 1);
2518 /* We look for obvious messed up bcc or strings in response so we do not go off
2519 the end since (at least) WIN2K and Windows XP have a major bug in not null
2520 terminating last Unicode string in response */
2522 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2523 cifs_strfromUCS_le(ses->serverOS,
2527 bcc_ptr += 2 * (len + 1);
2528 remaining_words -= len + 1;
2529 ses->serverOS[2 * len] = 0;
2530 ses->serverOS[1 + (2 * len)] = 0;
2531 if (remaining_words > 0) {
2532 len = UniStrnlen((wchar_t *)
2537 kcalloc(1, 2 * (len + 1),
2539 cifs_strfromUCS_le(ses->
2545 bcc_ptr += 2 * (len + 1);
2546 ses->serverNOS[2 * len] = 0;
2549 remaining_words -= len + 1;
2550 if (remaining_words > 0) {
2551 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2552 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2577 } /* else no more room so create dummy domain string */
2582 } else { /* no room so create dummy domain and NOS string */
2584 kcalloc(1, 2, GFP_KERNEL);
2586 kcalloc(1, 2, GFP_KERNEL);
2588 } else { /* ASCII */
2589 len = strnlen(bcc_ptr, 1024);
2590 if (((long) bcc_ptr + len) - (long)
2591 pByteArea(smb_buffer_response)
2592 <= BCC(smb_buffer_response)) {
2596 strncpy(ses->serverOS,
2600 bcc_ptr[0] = 0; /* null terminate string */
2603 len = strnlen(bcc_ptr, 1024);
2607 strncpy(ses->serverNOS, bcc_ptr, len);
2612 len = strnlen(bcc_ptr, 1024);
2616 strncpy(ses->serverDomain, bcc_ptr, len);
2622 ("Variable field of length %d extends beyond end of smb ",
2627 (" Security Blob Length extends beyond end of SMB"));
2630 cERROR(1, ("No session structure passed in."));
2634 (" Invalid Word count %d: ",
2635 smb_buffer_response->WordCount));
2640 cifs_buf_release(smb_buffer);
2645 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2646 char *ntlm_session_key, int ntlmv2_flag,
2647 const struct nls_table *nls_codepage)
2649 struct smb_hdr *smb_buffer;
2650 struct smb_hdr *smb_buffer_response;
2651 SESSION_SETUP_ANDX *pSMB;
2652 SESSION_SETUP_ANDX *pSMBr;
2657 int remaining_words = 0;
2658 int bytes_returned = 0;
2660 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2661 PAUTHENTICATE_MESSAGE SecurityBlob;
2662 __u32 negotiate_flags, capabilities;
2665 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2668 user = ses->userName;
2669 domain = ses->domainName;
2670 smb_buffer = cifs_buf_get();
2671 if (smb_buffer == NULL) {
2674 smb_buffer_response = smb_buffer;
2675 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2676 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2678 /* send SMBsessionSetup here */
2679 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2680 NULL /* no tCon exists yet */ , 12 /* wct */ );
2681 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2682 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2683 pSMB->req.AndXCommand = 0xFF;
2684 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2685 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2687 pSMB->req.hdr.Uid = ses->Suid;
2689 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2690 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2692 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2693 CAP_EXTENDED_SECURITY;
2694 if (ses->capabilities & CAP_UNICODE) {
2695 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2696 capabilities |= CAP_UNICODE;
2698 if (ses->capabilities & CAP_STATUS32) {
2699 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2700 capabilities |= CAP_STATUS32;
2702 if (ses->capabilities & CAP_DFS) {
2703 smb_buffer->Flags2 |= SMBFLG2_DFS;
2704 capabilities |= CAP_DFS;
2706 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2708 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2709 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2710 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2711 SecurityBlob->MessageType = NtLmAuthenticate;
2712 bcc_ptr += SecurityBlobLength;
2714 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2715 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2716 0x80000000 | NTLMSSP_NEGOTIATE_128;
2718 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2720 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2722 /* setup pointers to domain name and workstation name */
2724 SecurityBlob->WorkstationName.Buffer = 0;
2725 SecurityBlob->WorkstationName.Length = 0;
2726 SecurityBlob->WorkstationName.MaximumLength = 0;
2727 SecurityBlob->SessionKey.Length = 0;
2728 SecurityBlob->SessionKey.MaximumLength = 0;
2729 SecurityBlob->SessionKey.Buffer = 0;
2731 SecurityBlob->LmChallengeResponse.Length = 0;
2732 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2733 SecurityBlob->LmChallengeResponse.Buffer = 0;
2735 SecurityBlob->NtChallengeResponse.Length =
2736 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2737 SecurityBlob->NtChallengeResponse.MaximumLength =
2738 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2739 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2740 SecurityBlob->NtChallengeResponse.Buffer =
2741 cpu_to_le32(SecurityBlobLength);
2742 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2743 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2745 if (ses->capabilities & CAP_UNICODE) {
2746 if (domain == NULL) {
2747 SecurityBlob->DomainName.Buffer = 0;
2748 SecurityBlob->DomainName.Length = 0;
2749 SecurityBlob->DomainName.MaximumLength = 0;
2752 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2755 SecurityBlob->DomainName.MaximumLength =
2757 SecurityBlob->DomainName.Buffer =
2758 cpu_to_le32(SecurityBlobLength);
2760 SecurityBlobLength += len;
2761 SecurityBlob->DomainName.Length =
2765 SecurityBlob->UserName.Buffer = 0;
2766 SecurityBlob->UserName.Length = 0;
2767 SecurityBlob->UserName.MaximumLength = 0;
2770 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2773 SecurityBlob->UserName.MaximumLength =
2775 SecurityBlob->UserName.Buffer =
2776 cpu_to_le32(SecurityBlobLength);
2778 SecurityBlobLength += len;
2779 SecurityBlob->UserName.Length =
2783 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2784 SecurityBlob->WorkstationName.Length *= 2;
2785 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2786 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2787 bcc_ptr += SecurityBlob->WorkstationName.Length;
2788 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2789 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2791 if ((long) bcc_ptr % 2) {
2796 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2798 bcc_ptr += 2 * bytes_returned;
2800 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2802 bcc_ptr += 2 * bytes_returned;
2803 bcc_ptr += 2; /* null term version string */
2805 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2807 bcc_ptr += 2 * bytes_returned;
2810 bcc_ptr += 2; /* null terminate network opsys string */
2813 bcc_ptr += 2; /* null domain */
2814 } else { /* ASCII */
2815 if (domain == NULL) {
2816 SecurityBlob->DomainName.Buffer = 0;
2817 SecurityBlob->DomainName.Length = 0;
2818 SecurityBlob->DomainName.MaximumLength = 0;
2821 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2822 strncpy(bcc_ptr, domain, 63);
2823 len = strnlen(domain, 64);
2824 SecurityBlob->DomainName.MaximumLength =
2826 SecurityBlob->DomainName.Buffer =
2827 cpu_to_le32(SecurityBlobLength);
2829 SecurityBlobLength += len;
2830 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2833 SecurityBlob->UserName.Buffer = 0;
2834 SecurityBlob->UserName.Length = 0;
2835 SecurityBlob->UserName.MaximumLength = 0;
2838 strncpy(bcc_ptr, user, 63);
2839 len = strnlen(user, 64);
2840 SecurityBlob->UserName.MaximumLength =
2842 SecurityBlob->UserName.Buffer =
2843 cpu_to_le32(SecurityBlobLength);
2845 SecurityBlobLength += len;
2846 SecurityBlob->UserName.Length = cpu_to_le16(len);
2848 /* BB fill in our workstation name if known BB */
2850 strcpy(bcc_ptr, "Linux version ");
2851 bcc_ptr += strlen("Linux version ");
2852 strcpy(bcc_ptr, system_utsname.release);
2853 bcc_ptr += strlen(system_utsname.release) + 1;
2854 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2855 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2856 bcc_ptr++; /* null domain */
2859 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2860 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2861 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2862 smb_buffer->smb_buf_length += count;
2863 pSMB->req.ByteCount = cpu_to_le16(count);
2865 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2866 &bytes_returned, 1);
2868 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2869 } else if ((smb_buffer_response->WordCount == 3)
2870 || (smb_buffer_response->WordCount == 4)) {
2871 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2873 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2874 if (action & GUEST_LOGIN)
2875 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2876 /* if(SecurityBlob2->MessageType != NtLm??){
2877 cFYI("Unexpected message type on auth response is %d "));
2881 ("Does UID on challenge %d match auth response UID %d ",
2882 ses->Suid, smb_buffer_response->Uid));
2883 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2884 bcc_ptr = pByteArea(smb_buffer_response);
2885 /* response can have either 3 or 4 word count - Samba sends 3 */
2886 if ((pSMBr->resp.hdr.WordCount == 3)
2887 || ((pSMBr->resp.hdr.WordCount == 4)
2889 pSMBr->resp.ByteCount))) {
2890 if (pSMBr->resp.hdr.WordCount == 4) {
2894 ("Security Blob Length %d ",
2899 ("NTLMSSP response to Authenticate "));
2901 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2902 if ((long) (bcc_ptr) % 2) {
2904 (BCC(smb_buffer_response)
2906 bcc_ptr++; /* Unicode strings must be word aligned */
2908 remaining_words = BCC(smb_buffer_response) / 2;
2911 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2912 /* We look for obvious messed up bcc or strings in response so we do not go off
2913 the end since (at least) WIN2K and Windows XP have a major bug in not null
2914 terminating last Unicode string in response */
2916 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2917 cifs_strfromUCS_le(ses->serverOS,
2921 bcc_ptr += 2 * (len + 1);
2922 remaining_words -= len + 1;
2923 ses->serverOS[2 * len] = 0;
2924 ses->serverOS[1 + (2 * len)] = 0;
2925 if (remaining_words > 0) {
2926 len = UniStrnlen((wchar_t *)
2931 kcalloc(1, 2 * (len + 1),
2933 cifs_strfromUCS_le(ses->
2939 bcc_ptr += 2 * (len + 1);
2940 ses->serverNOS[2 * len] = 0;
2941 ses->serverNOS[1+(2*len)] = 0;
2942 remaining_words -= len + 1;
2943 if (remaining_words > 0) {
2944 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2945 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2970 } /* else no more room so create dummy domain string */
2972 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
2973 } else { /* no room so create dummy domain and NOS string */
2974 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2975 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2977 } else { /* ASCII */
2978 len = strnlen(bcc_ptr, 1024);
2979 if (((long) bcc_ptr + len) -
2980 (long) pByteArea(smb_buffer_response)
2981 <= BCC(smb_buffer_response)) {
2982 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2983 strncpy(ses->serverOS,bcc_ptr, len);
2986 bcc_ptr[0] = 0; /* null terminate the string */
2989 len = strnlen(bcc_ptr, 1024);
2990 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
2991 strncpy(ses->serverNOS, bcc_ptr, len);
2996 len = strnlen(bcc_ptr, 1024);
2997 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
2998 strncpy(ses->serverDomain, bcc_ptr, len);
3004 ("Variable field of length %d extends beyond end of smb ",
3009 (" Security Blob Length extends beyond end of SMB"));
3012 cERROR(1, ("No session structure passed in."));
3016 (" Invalid Word count %d: ",
3017 smb_buffer_response->WordCount));
3022 cifs_buf_release(smb_buffer);
3028 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3029 const char *tree, struct cifsTconInfo *tcon,
3030 const struct nls_table *nls_codepage)
3032 struct smb_hdr *smb_buffer;
3033 struct smb_hdr *smb_buffer_response;
3036 unsigned char *bcc_ptr;
3044 smb_buffer = cifs_buf_get();
3045 if (smb_buffer == NULL) {
3048 smb_buffer_response = smb_buffer;
3050 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3051 NULL /*no tid */ , 4 /*wct */ );
3052 smb_buffer->Uid = ses->Suid;
3053 pSMB = (TCONX_REQ *) smb_buffer;
3054 pSMBr = (TCONX_RSP *) smb_buffer_response;
3056 pSMB->AndXCommand = 0xFF;
3057 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3058 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3059 bcc_ptr = &pSMB->Password[0];
3060 bcc_ptr++; /* skip password */
3062 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3063 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3065 if (ses->capabilities & CAP_STATUS32) {
3066 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3068 if (ses->capabilities & CAP_DFS) {
3069 smb_buffer->Flags2 |= SMBFLG2_DFS;
3071 if (ses->capabilities & CAP_UNICODE) {
3072 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3074 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
3075 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3076 bcc_ptr += 2; /* skip trailing null */
3077 } else { /* ASCII */
3079 strcpy(bcc_ptr, tree);
3080 bcc_ptr += strlen(tree) + 1;
3082 strcpy(bcc_ptr, "?????");
3083 bcc_ptr += strlen("?????");
3085 count = bcc_ptr - &pSMB->Password[0];
3086 pSMB->hdr.smb_buf_length += count;
3087 pSMB->ByteCount = cpu_to_le16(count);
3089 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3091 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3092 /* above now done in SendReceive */
3093 if ((rc == 0) && (tcon != NULL)) {
3094 tcon->tidStatus = CifsGood;
3095 tcon->tid = smb_buffer_response->Tid;
3096 bcc_ptr = pByteArea(smb_buffer_response);
3097 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3098 /* skip service field (NB: this field is always ASCII) */
3099 bcc_ptr += length + 1;
3100 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3101 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3102 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3103 if ((bcc_ptr + (2 * length)) -
3104 pByteArea(smb_buffer_response) <=
3105 BCC(smb_buffer_response)) {
3106 if(tcon->nativeFileSystem)
3107 kfree(tcon->nativeFileSystem);
3108 tcon->nativeFileSystem =
3109 kcalloc(1, length + 2, GFP_KERNEL);
3110 cifs_strfromUCS_le(tcon->nativeFileSystem,
3111 (wchar_t *) bcc_ptr,
3112 length, nls_codepage);
3113 bcc_ptr += 2 * length;
3114 bcc_ptr[0] = 0; /* null terminate the string */
3118 /* else do not bother copying these informational fields */
3120 length = strnlen(bcc_ptr, 1024);
3121 if ((bcc_ptr + length) -
3122 pByteArea(smb_buffer_response) <=
3123 BCC(smb_buffer_response)) {
3124 if(tcon->nativeFileSystem)
3125 kfree(tcon->nativeFileSystem);
3126 tcon->nativeFileSystem =
3127 kcalloc(1, length + 1, GFP_KERNEL);
3128 strncpy(tcon->nativeFileSystem, bcc_ptr,
3131 /* else do not bother copying these informational fields */
3133 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3134 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3135 } else if ((rc == 0) && tcon == NULL) {
3136 /* all we need to save for IPC$ connection */
3137 ses->ipc_tid = smb_buffer_response->Tid;
3141 cifs_buf_release(smb_buffer);
3146 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3150 struct cifsSesInfo *ses = NULL;
3151 struct task_struct *cifsd_task;
3155 if (cifs_sb->tcon) {
3156 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3157 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3162 tconInfoFree(cifs_sb->tcon);
3163 if ((ses) && (ses->server)) {
3164 /* save off task so we do not refer to ses later */
3165 cifsd_task = ses->server->tsk;
3166 cFYI(1, ("About to do SMBLogoff "));
3167 rc = CIFSSMBLogoff(xid, ses);
3171 } else if (rc == -ESHUTDOWN) {
3172 cFYI(1,("Waking up socket by sending it signal"));
3174 send_sig(SIGKILL,cifsd_task,1);
3176 } /* else - we have an smb session
3177 left on this socket do not kill cifsd */
3179 cFYI(1, ("No session or bad tcon"));
3182 cifs_sb->tcon = NULL;
3184 set_current_state(TASK_INTERRUPTIBLE);
3185 schedule_timeout(HZ / 2);
3191 return rc; /* BB check if we should always return zero here */
3194 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3195 struct nls_table * nls_info)
3198 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3199 int ntlmv2_flag = FALSE;
3202 /* what if server changes its buffer size after dropping the session? */
3203 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3204 rc = CIFSSMBNegotiate(xid, pSesInfo);
3205 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3206 rc = CIFSSMBNegotiate(xid, pSesInfo);
3211 spin_lock(&GlobalMid_Lock);
3212 if(pSesInfo->server->tcpStatus != CifsExiting)
3213 pSesInfo->server->tcpStatus = CifsGood;
3216 spin_unlock(&GlobalMid_Lock);
3222 pSesInfo->capabilities = pSesInfo->server->capabilities;
3223 if(linuxExtEnabled == 0)
3224 pSesInfo->capabilities &= (~CAP_UNIX);
3225 /* pSesInfo->sequence_number = 0;*/
3226 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3227 pSesInfo->server->secMode,
3228 pSesInfo->server->capabilities,
3229 pSesInfo->server->timeZone));
3230 if (extended_security
3231 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3232 && (pSesInfo->server->secType == NTLMSSP)) {
3233 cFYI(1, ("New style sesssetup "));
3234 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3235 NULL /* security blob */,
3236 0 /* blob length */,
3238 } else if (extended_security
3239 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3240 && (pSesInfo->server->secType == RawNTLMSSP)) {
3241 cFYI(1, ("NTLMSSP sesssetup "));
3242 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3249 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3250 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3255 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3257 CalcNTLMv2_response(pSesInfo,v2_response);
3259 cifs_calculate_ntlmv2_mac_key(
3260 pSesInfo->server->mac_signing_key,
3261 response, ntlm_session_key, */
3263 /* BB Put dummy sig in SessSetup PDU? */
3270 SMBNTencrypt(pSesInfo->password,
3271 pSesInfo->server->cryptKey,
3275 cifs_calculate_mac_key(
3276 pSesInfo->server->mac_signing_key,
3278 pSesInfo->password);
3280 /* for better security the weaker lanman hash not sent
3281 in AuthSessSetup so we no longer calculate it */
3283 rc = CIFSNTLMSSPAuthSessSetup(xid,
3289 } else { /* old style NTLM 0.12 session setup */
3290 SMBNTencrypt(pSesInfo->password,
3291 pSesInfo->server->cryptKey,
3295 cifs_calculate_mac_key(
3296 pSesInfo->server->mac_signing_key,
3297 ntlm_session_key, pSesInfo->password);
3299 rc = CIFSSessSetup(xid, pSesInfo,
3300 ntlm_session_key, nls_info);
3303 cERROR(1,("Send error in SessSetup = %d",rc));
3305 cFYI(1,("CIFS Session Established successfully"));
3306 pSesInfo->status = CifsGood;