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,("Reconnect 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 abend 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,("Reconnect after unexpected peek error %d",
412 cifs_reconnect(server);
413 csocket = server->ssocket;
414 wake_up(&server->response_q);
416 } else if (length < 4) {
418 ("Frame under four bytes received (%d bytes long)",
420 cifs_reconnect(server);
421 csocket = server->ssocket;
422 wake_up(&server->response_q);
426 /* the right amount was read from socket - 4 bytes */
428 pdu_length = ntohl(smb_buffer->smb_buf_length);
429 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
431 temp = (char *) smb_buffer;
432 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
434 } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
435 cFYI(1,("Good RFC 1002 session rsp"));
437 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
438 /* we get this from Windows 98 instead of
439 an error on SMB negprot response */
440 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
442 if(server->tcpStatus == CifsNew) {
443 /* if nack on negprot (rather than
444 ret of smb negprot error) reconnecting
445 not going to help, ret error to mount */
448 /* give server a second to
449 clean up before reconnect attempt */
451 /* always try 445 first on reconnect
452 since we get NACK on some if we ever
453 connected to port 139 (the NACK is
454 since we do not begin with RFC1001
455 session initialize frame) */
456 server->addr.sockAddr.sin_port =
458 cifs_reconnect(server);
459 csocket = server->ssocket;
460 wake_up(&server->response_q);
463 } else if (temp[0] != (char) 0) {
464 cERROR(1,("Unknown RFC 1002 frame"));
465 cifs_dump_mem(" Received Data: ", temp, length);
466 cifs_reconnect(server);
467 csocket = server->ssocket;
471 /* else we have an SMB response */
472 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
473 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
474 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
475 length, pdu_length+4));
476 cifs_reconnect(server);
477 csocket = server->ssocket;
478 wake_up(&server->response_q);
485 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
487 memcpy(bigbuf, smallbuf, 4);
491 iov.iov_base = 4 + (char *)smb_buffer;
492 iov.iov_len = pdu_length;
493 for (total_read = 0; total_read < pdu_length;
494 total_read += length) {
495 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
496 pdu_length - total_read, 0);
497 if((server->tcpStatus == CifsExiting) ||
498 (length == -EINTR)) {
502 } else if (server->tcpStatus == CifsNeedReconnect) {
503 cifs_reconnect(server);
504 csocket = server->ssocket;
505 /* Reconnect wakes up rspns q */
506 /* Now we will reread sock */
509 } else if ((length == -ERESTARTSYS) ||
510 (length == -EAGAIN)) {
511 msleep(1); /* minimum sleep to prevent looping,
512 allowing socket to clear and app
513 threads to set tcpStatus
514 CifsNeedReconnect if server hung*/
516 } else if (length <= 0) {
517 cERROR(1,("Received no data, expecting %d",
518 pdu_length - total_read));
519 cifs_reconnect(server);
520 csocket = server->ssocket;
527 else if(reconnect == 1)
530 length += 4; /* account for rfc1002 hdr */
533 dump_smb(smb_buffer, length);
534 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
535 cERROR(1, ("Bad SMB Received "));
541 spin_lock(&GlobalMid_Lock);
542 list_for_each(tmp, &server->pending_mid_q) {
543 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
545 if ((mid_entry->mid == smb_buffer->Mid) &&
546 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
547 (mid_entry->command == smb_buffer->Command)) {
548 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
549 /* 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)) {
557 /* all parts received */
562 cERROR(1,("1st trans2 resp needs bigbuf"));
563 /* BB maybe we can fix this up, switch
564 to already allocated large buffer? */
566 /* Have first buffer */
567 mid_entry->resp_buf =
569 mid_entry->largeBuf = 1;
575 mid_entry->resp_buf = smb_buffer;
577 mid_entry->largeBuf = 1;
579 mid_entry->largeBuf = 0;
581 task_to_wake = mid_entry->tsk;
582 mid_entry->midState = MID_RESPONSE_RECEIVED;
586 spin_unlock(&GlobalMid_Lock);
588 /* Was previous buf put in mpx struct for multi-rsp? */
590 /* smb buffer will be freed by user thread */
596 wake_up_process(task_to_wake);
597 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
598 && (isMultiRsp == FALSE)) {
599 cERROR(1, ("No task to wake, unknown frame rcvd!"));
600 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
602 } /* end while !EXITING */
604 spin_lock(&GlobalMid_Lock);
605 server->tcpStatus = CifsExiting;
607 atomic_set(&server->inFlight, 0);
608 spin_unlock(&GlobalMid_Lock);
609 /* Although there should not be any requests blocked on
610 this queue it can not hurt to be paranoid and try to wake up requests
611 that may haven been blocked when more than 50 at time were on the wire
612 to the same server - they now will see the session is in exit state
613 and get out of SendReceive. */
614 wake_up_all(&server->request_q);
615 /* give those requests time to exit */
618 if(server->ssocket) {
619 sock_release(csocket);
620 server->ssocket = NULL;
622 /* buffer usuallly freed in free_mid - need to free it here on exit */
624 cifs_buf_release(bigbuf);
625 if (smallbuf != NULL)
626 cifs_small_buf_release(smallbuf);
628 read_lock(&GlobalSMBSeslock);
629 if (list_empty(&server->pending_mid_q)) {
630 /* loop through server session structures attached to this and
632 list_for_each(tmp, &GlobalSMBSessionList) {
634 list_entry(tmp, struct cifsSesInfo,
636 if (ses->server == server) {
637 ses->status = CifsExiting;
641 read_unlock(&GlobalSMBSeslock);
643 spin_lock(&GlobalMid_Lock);
644 list_for_each(tmp, &server->pending_mid_q) {
645 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
646 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
648 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
649 task_to_wake = mid_entry->tsk;
651 wake_up_process(task_to_wake);
655 spin_unlock(&GlobalMid_Lock);
656 read_unlock(&GlobalSMBSeslock);
657 /* 1/8th of sec is more than enough time for them to exit */
661 if (list_empty(&server->pending_mid_q)) {
662 /* mpx threads have not exited yet give them
663 at least the smb send timeout time for long ops */
664 cFYI(1, ("Wait for exit from demultiplex thread"));
666 /* if threads still have not exited they are probably never
667 coming home not much else we can do but free the memory */
671 write_lock(&GlobalSMBSeslock);
672 atomic_dec(&tcpSesAllocCount);
673 length = tcpSesAllocCount.counter;
674 write_unlock(&GlobalSMBSeslock);
676 mempool_resize(cifs_req_poolp,
677 length + cifs_min_rcv,
686 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
690 unsigned int temp_len, i, j;
696 memset(vol->source_rfc1001_name,0x20,15);
697 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
698 /* does not have to be a perfect mapping since the field is
699 informational, only used for servers that do not support
700 port 445 and it can be overridden at mount time */
701 vol->source_rfc1001_name[i] =
702 toupper(system_utsname.nodename[i]);
704 vol->source_rfc1001_name[15] = 0;
706 vol->linux_uid = current->uid; /* current->euid instead? */
707 vol->linux_gid = current->gid;
708 vol->dir_mode = S_IRWXUGO;
709 /* 2767 perms indicate mandatory locking support */
710 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
712 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
718 if(strncmp(options,"sep=",4) == 0) {
719 if(options[4] != 0) {
720 separator[0] = options[4];
723 cFYI(1,("Null separator not allowed"));
727 while ((data = strsep(&options, separator)) != NULL) {
730 if ((value = strchr(data, '=')) != NULL)
733 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
735 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
737 } else if (strnicmp(data, "user", 4) == 0) {
738 if (!value || !*value) {
740 "CIFS: invalid or missing username\n");
741 return 1; /* needs_arg; */
743 if (strnlen(value, 200) < 200) {
744 vol->username = value;
746 printk(KERN_WARNING "CIFS: username too long\n");
749 } else if (strnicmp(data, "pass", 4) == 0) {
751 vol->password = NULL;
753 } else if(value[0] == 0) {
754 /* check if string begins with double comma
755 since that would mean the password really
756 does start with a comma, and would not
757 indicate an empty string */
758 if(value[1] != separator[0]) {
759 vol->password = NULL;
763 temp_len = strlen(value);
764 /* removed password length check, NTLM passwords
765 can be arbitrarily long */
767 /* if comma in password, the string will be
768 prematurely null terminated. Commas in password are
769 specified across the cifs mount interface by a double
770 comma ie ,, and a comma used as in other cases ie ','
771 as a parameter delimiter/separator is single and due
772 to the strsep above is temporarily zeroed. */
774 /* NB: password legally can have multiple commas and
775 the only illegal character in a password is null */
777 if ((value[temp_len] == 0) &&
778 (value[temp_len+1] == separator[0])) {
780 value[temp_len] = separator[0];
781 temp_len+=2; /* move after the second comma */
782 while(value[temp_len] != 0) {
783 if (value[temp_len] == separator[0]) {
784 if (value[temp_len+1] ==
786 /* skip second comma */
789 /* single comma indicating start
796 if(value[temp_len] == 0) {
800 /* point option to start of next parm */
801 options = value + temp_len + 1;
803 /* go from value to value + temp_len condensing
804 double commas to singles. Note that this ends up
805 allocating a few bytes too many, which is ok */
806 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
807 if(vol->password == NULL) {
808 printk("CIFS: no memory for pass\n");
811 for(i=0,j=0;i<temp_len;i++,j++) {
812 vol->password[j] = value[i];
813 if(value[i] == separator[0]
814 && value[i+1] == separator[0]) {
815 /* skip second comma */
819 vol->password[j] = 0;
821 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
822 if(vol->password == NULL) {
823 printk("CIFS: no memory for pass\n");
826 strcpy(vol->password, value);
828 } else if (strnicmp(data, "ip", 2) == 0) {
829 if (!value || !*value) {
831 } else if (strnlen(value, 35) < 35) {
834 printk(KERN_WARNING "CIFS: ip address too long\n");
837 } else if ((strnicmp(data, "unc", 3) == 0)
838 || (strnicmp(data, "target", 6) == 0)
839 || (strnicmp(data, "path", 4) == 0)) {
840 if (!value || !*value) {
842 "CIFS: invalid path to network resource\n");
843 return 1; /* needs_arg; */
845 if ((temp_len = strnlen(value, 300)) < 300) {
846 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
849 strcpy(vol->UNC,value);
850 if (strncmp(vol->UNC, "//", 2) == 0) {
853 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
855 "CIFS: UNC Path does not begin with // or \\\\ \n");
859 printk(KERN_WARNING "CIFS: UNC name too long\n");
862 } else if ((strnicmp(data, "domain", 3) == 0)
863 || (strnicmp(data, "workgroup", 5) == 0)) {
864 if (!value || !*value) {
865 printk(KERN_WARNING "CIFS: invalid domain name\n");
866 return 1; /* needs_arg; */
868 /* BB are there cases in which a comma can be valid in
869 a domain name and need special handling? */
870 if (strnlen(value, 65) < 65) {
871 vol->domainname = value;
872 cFYI(1, ("Domain name set"));
874 printk(KERN_WARNING "CIFS: domain name too long\n");
877 } else if (strnicmp(data, "iocharset", 9) == 0) {
878 if (!value || !*value) {
879 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
880 return 1; /* needs_arg; */
882 if (strnlen(value, 65) < 65) {
883 if(strnicmp(value,"default",7))
884 vol->iocharset = value;
885 /* if iocharset not set load_nls_default used by caller */
886 cFYI(1, ("iocharset set to %s",value));
888 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
891 } else if (strnicmp(data, "uid", 3) == 0) {
892 if (value && *value) {
894 simple_strtoul(value, &value, 0);
896 } else if (strnicmp(data, "gid", 3) == 0) {
897 if (value && *value) {
899 simple_strtoul(value, &value, 0);
901 } else if (strnicmp(data, "file_mode", 4) == 0) {
902 if (value && *value) {
904 simple_strtoul(value, &value, 0);
906 } else if (strnicmp(data, "dir_mode", 4) == 0) {
907 if (value && *value) {
909 simple_strtoul(value, &value, 0);
911 } else if (strnicmp(data, "dirmode", 4) == 0) {
912 if (value && *value) {
914 simple_strtoul(value, &value, 0);
916 } else if (strnicmp(data, "port", 4) == 0) {
917 if (value && *value) {
919 simple_strtoul(value, &value, 0);
921 } else if (strnicmp(data, "rsize", 5) == 0) {
922 if (value && *value) {
924 simple_strtoul(value, &value, 0);
926 } else if (strnicmp(data, "wsize", 5) == 0) {
927 if (value && *value) {
929 simple_strtoul(value, &value, 0);
931 } else if (strnicmp(data, "sockopt", 5) == 0) {
932 if (value && *value) {
934 simple_strtoul(value, &value, 0);
936 } else if (strnicmp(data, "netbiosname", 4) == 0) {
937 if (!value || !*value || (*value == ' ')) {
938 cFYI(1,("invalid (empty) netbiosname specified"));
940 memset(vol->source_rfc1001_name,0x20,15);
942 /* BB are there cases in which a comma can be
943 valid in this workstation netbios name (and need
944 special handling)? */
946 /* We do not uppercase netbiosname for user */
950 vol->source_rfc1001_name[i] = value[i];
952 /* The string has 16th byte zero still from
953 set at top of the function */
954 if((i==15) && (value[i] != 0))
955 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
957 } else if (strnicmp(data, "credentials", 4) == 0) {
959 } else if (strnicmp(data, "version", 3) == 0) {
961 } else if (strnicmp(data, "guest",5) == 0) {
963 } else if (strnicmp(data, "rw", 2) == 0) {
965 } else if ((strnicmp(data, "suid", 4) == 0) ||
966 (strnicmp(data, "nosuid", 6) == 0) ||
967 (strnicmp(data, "exec", 4) == 0) ||
968 (strnicmp(data, "noexec", 6) == 0) ||
969 (strnicmp(data, "nodev", 5) == 0) ||
970 (strnicmp(data, "noauto", 6) == 0) ||
971 (strnicmp(data, "dev", 3) == 0)) {
972 /* The mount tool or mount.cifs helper (if present)
973 uses these opts to set flags, and the flags are read
974 by the kernel vfs layer before we get here (ie
975 before read super) so there is no point trying to
976 parse these options again and set anything and it
977 is ok to just ignore them */
979 } else if (strnicmp(data, "ro", 2) == 0) {
981 } else if (strnicmp(data, "hard", 4) == 0) {
983 } else if (strnicmp(data, "soft", 4) == 0) {
985 } else if (strnicmp(data, "perm", 4) == 0) {
987 } else if (strnicmp(data, "noperm", 6) == 0) {
989 } else if (strnicmp(data, "mapchars", 8) == 0) {
991 } else if (strnicmp(data, "nomapchars", 10) == 0) {
993 } else if (strnicmp(data, "setuids", 7) == 0) {
995 } else if (strnicmp(data, "nosetuids", 9) == 0) {
997 } else if (strnicmp(data, "nohard", 6) == 0) {
999 } else if (strnicmp(data, "nosoft", 6) == 0) {
1001 } else if (strnicmp(data, "nointr", 6) == 0) {
1003 } else if (strnicmp(data, "intr", 4) == 0) {
1005 } else if (strnicmp(data, "serverino",7) == 0) {
1006 vol->server_ino = 1;
1007 } else if (strnicmp(data, "noserverino",9) == 0) {
1008 vol->server_ino = 0;
1009 } else if (strnicmp(data, "acl",3) == 0) {
1010 vol->no_psx_acl = 0;
1011 } else if (strnicmp(data, "noacl",5) == 0) {
1012 vol->no_psx_acl = 1;
1013 } else if (strnicmp(data, "direct",6) == 0) {
1015 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1017 } else if (strnicmp(data, "in6_addr",8) == 0) {
1018 if (!value || !*value) {
1019 vol->in6_addr = NULL;
1020 } else if (strnlen(value, 49) == 48) {
1021 vol->in6_addr = value;
1023 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1026 } else if (strnicmp(data, "noac", 4) == 0) {
1027 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1029 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1031 if (vol->UNC == NULL) {
1032 if(devname == NULL) {
1033 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1036 if ((temp_len = strnlen(devname, 300)) < 300) {
1037 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1038 if(vol->UNC == NULL)
1040 strcpy(vol->UNC,devname);
1041 if (strncmp(vol->UNC, "//", 2) == 0) {
1044 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1045 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1049 printk(KERN_WARNING "CIFS: UNC name too long\n");
1053 if(vol->UNCip == NULL)
1054 vol->UNCip = &vol->UNC[2];
1059 static struct cifsSesInfo *
1060 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1061 struct in6_addr *target_ip6_addr,
1062 char *userName, struct TCP_Server_Info **psrvTcp)
1064 struct list_head *tmp;
1065 struct cifsSesInfo *ses;
1067 read_lock(&GlobalSMBSeslock);
1069 list_for_each(tmp, &GlobalSMBSessionList) {
1070 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1072 if((target_ip_addr &&
1073 (ses->server->addr.sockAddr.sin_addr.s_addr
1074 == target_ip_addr->s_addr)) || (target_ip6_addr
1075 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1076 target_ip6_addr,sizeof(*target_ip6_addr)))){
1077 /* BB lock server and tcp session and increment use count here?? */
1078 *psrvTcp = ses->server; /* found a match on the TCP session */
1079 /* BB check if reconnection needed */
1081 (ses->userName, userName,
1082 MAX_USERNAME_SIZE) == 0){
1083 read_unlock(&GlobalSMBSeslock);
1084 return ses; /* found exact match on both tcp and SMB sessions */
1088 /* else tcp and smb sessions need reconnection */
1090 read_unlock(&GlobalSMBSeslock);
1094 static struct cifsTconInfo *
1095 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1097 struct list_head *tmp;
1098 struct cifsTconInfo *tcon;
1100 read_lock(&GlobalSMBSeslock);
1101 list_for_each(tmp, &GlobalTreeConnectionList) {
1102 cFYI(1, ("Next tcon - "));
1103 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1105 if (tcon->ses->server) {
1107 (" old ip addr: %x == new ip %x ?",
1108 tcon->ses->server->addr.sockAddr.sin_addr.
1109 s_addr, new_target_ip_addr));
1110 if (tcon->ses->server->addr.sockAddr.sin_addr.
1111 s_addr == new_target_ip_addr) {
1112 /* BB lock tcon and server and tcp session and increment use count here? */
1113 /* found a match on the TCP session */
1114 /* BB check if reconnection needed */
1115 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1116 tcon->treeName, uncName));
1118 (tcon->treeName, uncName,
1119 MAX_TREE_SIZE) == 0) {
1121 ("Matched UNC, old user: %s == new: %s ?",
1122 tcon->treeName, uncName));
1124 (tcon->ses->userName,
1126 MAX_USERNAME_SIZE) == 0) {
1127 read_unlock(&GlobalSMBSeslock);
1128 return tcon;/* also matched user (smb session)*/
1135 read_unlock(&GlobalSMBSeslock);
1140 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1141 const char *old_path, const struct nls_table *nls_codepage,
1144 unsigned char *referrals = NULL;
1145 unsigned int num_referrals;
1148 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1149 &num_referrals, &referrals, remap);
1151 /* BB Add in code to: if valid refrl, if not ip address contact
1152 the helper that resolves tcp names, mount to it, try to
1153 tcon to it unmount it if fail */
1162 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1163 const char *old_path, const struct nls_table *nls_codepage,
1164 unsigned int *pnum_referrals,
1165 unsigned char ** preferrals, int remap)
1170 *pnum_referrals = 0;
1172 if (pSesInfo->ipc_tid == 0) {
1173 temp_unc = kmalloc(2 /* for slashes */ +
1174 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1175 + 1 + 4 /* slash IPC$ */ + 2,
1177 if (temp_unc == NULL)
1181 strcpy(temp_unc + 2, pSesInfo->serverName);
1182 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1183 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1185 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1189 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1190 pnum_referrals, nls_codepage, remap);
1195 /* See RFC1001 section 14 on representation of Netbios names */
1196 static void rfc1002mangle(char * target,char * source, unsigned int length)
1200 for(i=0,j=0;i<(length);i++) {
1201 /* mask a nibble at a time and encode */
1202 target[j] = 'A' + (0x0F & (source[i] >> 4));
1203 target[j+1] = 'A' + (0x0F & source[i]);
1211 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1212 char * netbios_name)
1216 __be16 orig_port = 0;
1218 if(*csocket == NULL) {
1219 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1221 cERROR(1, ("Error %d creating socket",rc));
1225 /* BB other socket options to set KEEPALIVE, NODELAY? */
1226 cFYI(1,("Socket created"));
1227 (*csocket)->sk->sk_allocation = GFP_NOFS;
1231 psin_server->sin_family = AF_INET;
1232 if(psin_server->sin_port) { /* user overrode default port */
1233 rc = (*csocket)->ops->connect(*csocket,
1234 (struct sockaddr *) psin_server,
1235 sizeof (struct sockaddr_in),0);
1241 /* save original port so we can retry user specified port
1242 later if fall back ports fail this time */
1243 orig_port = psin_server->sin_port;
1245 /* do not retry on the same port we just failed on */
1246 if(psin_server->sin_port != htons(CIFS_PORT)) {
1247 psin_server->sin_port = htons(CIFS_PORT);
1249 rc = (*csocket)->ops->connect(*csocket,
1250 (struct sockaddr *) psin_server,
1251 sizeof (struct sockaddr_in),0);
1257 psin_server->sin_port = htons(RFC1001_PORT);
1258 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1259 psin_server, sizeof (struct sockaddr_in),0);
1264 /* give up here - unless we want to retry on different
1265 protocol families some day */
1268 psin_server->sin_port = orig_port;
1269 cFYI(1,("Error %d connecting to server via ipv4",rc));
1270 sock_release(*csocket);
1274 /* Eventually check for other socket options to change from
1275 the default. sock_setsockopt not used because it expects
1276 user space buffer */
1277 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1279 /* send RFC1001 sessinit */
1281 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1282 /* some servers require RFC1001 sessinit before sending
1283 negprot - BB check reconnection in case where second
1284 sessinit is sent but no second negprot */
1285 struct rfc1002_session_packet * ses_init_buf;
1286 struct smb_hdr * smb_buf;
1287 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1289 ses_init_buf->trailer.session_req.called_len = 32;
1290 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1291 DEFAULT_CIFS_CALLED_NAME,16);
1292 ses_init_buf->trailer.session_req.calling_len = 32;
1293 /* calling name ends in null (byte 16) from old smb
1295 if(netbios_name && (netbios_name[0] !=0)) {
1296 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1299 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1300 "LINUX_CIFS_CLNT",16);
1302 ses_init_buf->trailer.session_req.scope1 = 0;
1303 ses_init_buf->trailer.session_req.scope2 = 0;
1304 smb_buf = (struct smb_hdr *)ses_init_buf;
1305 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1306 smb_buf->smb_buf_length = 0x81000044;
1307 rc = smb_send(*csocket, smb_buf, 0x44,
1308 (struct sockaddr *)psin_server);
1309 kfree(ses_init_buf);
1311 /* else the negprot may still work without this
1312 even though malloc failed */
1320 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1324 __be16 orig_port = 0;
1326 if(*csocket == NULL) {
1327 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1329 cERROR(1, ("Error %d creating ipv6 socket",rc));
1333 /* BB other socket options to set KEEPALIVE, NODELAY? */
1334 cFYI(1,("ipv6 Socket created"));
1335 (*csocket)->sk->sk_allocation = GFP_NOFS;
1339 psin_server->sin6_family = AF_INET6;
1341 if(psin_server->sin6_port) { /* user overrode default port */
1342 rc = (*csocket)->ops->connect(*csocket,
1343 (struct sockaddr *) psin_server,
1344 sizeof (struct sockaddr_in6),0);
1350 /* save original port so we can retry user specified port
1351 later if fall back ports fail this time */
1353 orig_port = psin_server->sin6_port;
1354 /* do not retry on the same port we just failed on */
1355 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1356 psin_server->sin6_port = htons(CIFS_PORT);
1358 rc = (*csocket)->ops->connect(*csocket,
1359 (struct sockaddr *) psin_server,
1360 sizeof (struct sockaddr_in6),0);
1366 psin_server->sin6_port = htons(RFC1001_PORT);
1367 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1368 psin_server, sizeof (struct sockaddr_in6),0);
1373 /* give up here - unless we want to retry on different
1374 protocol families some day */
1377 psin_server->sin6_port = orig_port;
1378 cFYI(1,("Error %d connecting to server via ipv6",rc));
1379 sock_release(*csocket);
1383 /* Eventually check for other socket options to change from
1384 the default. sock_setsockopt not used because it expects
1385 user space buffer */
1386 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1392 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1393 char *mount_data, const char *devname)
1397 int address_type = AF_INET;
1398 struct socket *csocket = NULL;
1399 struct sockaddr_in sin_server;
1400 struct sockaddr_in6 sin_server6;
1401 struct smb_vol volume_info;
1402 struct cifsSesInfo *pSesInfo = NULL;
1403 struct cifsSesInfo *existingCifsSes = NULL;
1404 struct cifsTconInfo *tcon = NULL;
1405 struct TCP_Server_Info *srvTcp = NULL;
1409 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1411 memset(&volume_info,0,sizeof(struct smb_vol));
1412 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1414 kfree(volume_info.UNC);
1415 if(volume_info.password)
1416 kfree(volume_info.password);
1421 if (volume_info.username) {
1422 /* BB fixme parse for domain name here */
1423 cFYI(1, ("Username: %s ", volume_info.username));
1426 cifserror("No username specified ");
1427 /* In userspace mount helper we can get user name from alternate
1428 locations such as env variables and files on disk */
1430 kfree(volume_info.UNC);
1431 if(volume_info.password)
1432 kfree(volume_info.password);
1437 if (volume_info.UNCip && volume_info.UNC) {
1438 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1441 /* not ipv4 address, try ipv6 */
1442 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1444 address_type = AF_INET6;
1446 address_type = AF_INET;
1450 /* we failed translating address */
1452 kfree(volume_info.UNC);
1453 if(volume_info.password)
1454 kfree(volume_info.password);
1459 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1462 } else if (volume_info.UNCip){
1463 /* BB using ip addr as server name connect to the DFS root below */
1464 cERROR(1,("Connecting to DFS root not implemented yet"));
1466 kfree(volume_info.UNC);
1467 if(volume_info.password)
1468 kfree(volume_info.password);
1471 } else /* which servers DFS root would we conect to */ {
1473 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1475 kfree(volume_info.UNC);
1476 if(volume_info.password)
1477 kfree(volume_info.password);
1482 /* this is needed for ASCII cp to Unicode converts */
1483 if(volume_info.iocharset == NULL) {
1484 cifs_sb->local_nls = load_nls_default();
1485 /* load_nls_default can not return null */
1487 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1488 if(cifs_sb->local_nls == NULL) {
1489 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1491 kfree(volume_info.UNC);
1492 if(volume_info.password)
1493 kfree(volume_info.password);
1499 if(address_type == AF_INET)
1500 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1501 NULL /* no ipv6 addr */,
1502 volume_info.username, &srvTcp);
1503 else if(address_type == AF_INET6)
1504 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1505 &sin_server6.sin6_addr,
1506 volume_info.username, &srvTcp);
1509 kfree(volume_info.UNC);
1510 if(volume_info.password)
1511 kfree(volume_info.password);
1518 cFYI(1, ("Existing tcp session with server found "));
1519 } else { /* create socket */
1520 if(volume_info.port)
1521 sin_server.sin_port = htons(volume_info.port);
1523 sin_server.sin_port = 0;
1524 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1527 ("Error connecting to IPv4 socket. Aborting operation"));
1529 sock_release(csocket);
1531 kfree(volume_info.UNC);
1532 if(volume_info.password)
1533 kfree(volume_info.password);
1538 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1539 if (srvTcp == NULL) {
1541 sock_release(csocket);
1543 kfree(volume_info.UNC);
1544 if(volume_info.password)
1545 kfree(volume_info.password);
1549 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1550 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1551 atomic_set(&srvTcp->inFlight,0);
1552 /* BB Add code for ipv6 case too */
1553 srvTcp->ssocket = csocket;
1554 srvTcp->protocolType = IPV4;
1555 init_waitqueue_head(&srvTcp->response_q);
1556 init_waitqueue_head(&srvTcp->request_q);
1557 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1558 /* at this point we are the only ones with the pointer
1559 to the struct since the kernel thread not created yet
1560 so no need to spinlock this init of tcpStatus */
1561 srvTcp->tcpStatus = CifsNew;
1562 init_MUTEX(&srvTcp->tcpSem);
1563 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1564 CLONE_FS | CLONE_FILES | CLONE_VM);
1567 sock_release(csocket);
1569 kfree(volume_info.UNC);
1570 if(volume_info.password)
1571 kfree(volume_info.password);
1576 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1577 srvTcp->sequence_number = 0;
1581 if (existingCifsSes) {
1582 pSesInfo = existingCifsSes;
1583 cFYI(1, ("Existing smb sess found "));
1584 if(volume_info.password)
1585 kfree(volume_info.password);
1586 /* volume_info.UNC freed at end of function */
1588 cFYI(1, ("Existing smb sess not found "));
1589 pSesInfo = sesInfoAlloc();
1590 if (pSesInfo == NULL)
1593 pSesInfo->server = srvTcp;
1594 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1595 NIPQUAD(sin_server.sin_addr.s_addr));
1599 /* volume_info.password freed at unmount */
1600 if (volume_info.password)
1601 pSesInfo->password = volume_info.password;
1602 if (volume_info.username)
1603 strncpy(pSesInfo->userName,
1604 volume_info.username,MAX_USERNAME_SIZE);
1605 if (volume_info.domainname)
1606 strncpy(pSesInfo->domainName,
1607 volume_info.domainname,MAX_USERNAME_SIZE);
1608 pSesInfo->linux_uid = volume_info.linux_uid;
1609 down(&pSesInfo->sesSem);
1610 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1611 up(&pSesInfo->sesSem);
1613 atomic_inc(&srvTcp->socketUseCount);
1615 if(volume_info.password)
1616 kfree(volume_info.password);
1619 /* search for existing tcon to this server share */
1621 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1622 cifs_sb->rsize = volume_info.rsize;
1624 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1625 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1626 cifs_sb->wsize = volume_info.wsize;
1628 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1629 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1630 cifs_sb->rsize = PAGE_CACHE_SIZE;
1631 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1633 cifs_sb->mnt_uid = volume_info.linux_uid;
1634 cifs_sb->mnt_gid = volume_info.linux_gid;
1635 cifs_sb->mnt_file_mode = volume_info.file_mode;
1636 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1637 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1639 if(volume_info.noperm)
1640 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1641 if(volume_info.setuids)
1642 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1643 if(volume_info.server_ino)
1644 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1645 if(volume_info.remap)
1646 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1647 if(volume_info.no_xattr)
1648 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1649 if(volume_info.direct_io) {
1650 cERROR(1,("mounting share using direct i/o"));
1651 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1655 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1656 volume_info.username);
1658 cFYI(1, ("Found match on UNC path "));
1659 /* we can have only one retry value for a connection
1660 to a share so for resources mounted more than once
1661 to the same server share the last value passed in
1662 for the retry flag is used */
1663 tcon->retry = volume_info.retry;
1665 tcon = tconInfoAlloc();
1669 /* check for null share name ie connect to dfs root */
1671 /* BB check if this works for exactly length three strings */
1672 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1673 && (strchr(volume_info.UNC + 3, '/') ==
1675 rc = connect_to_dfs_path(xid, pSesInfo,
1676 "", cifs_sb->local_nls,
1677 cifs_sb->mnt_cifs_flags &
1678 CIFS_MOUNT_MAP_SPECIAL_CHR);
1680 kfree(volume_info.UNC);
1684 rc = CIFSTCon(xid, pSesInfo,
1686 tcon, cifs_sb->local_nls);
1687 cFYI(1, ("CIFS Tcon rc = %d", rc));
1690 atomic_inc(&pSesInfo->inUse);
1691 tcon->retry = volume_info.retry;
1697 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1698 sb->s_maxbytes = (u64) 1 << 63;
1700 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1703 sb->s_time_gran = 100;
1705 /* on error free sesinfo and tcon struct if needed */
1707 /* if session setup failed, use count is zero but
1708 we still need to free cifsd thread */
1709 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1710 spin_lock(&GlobalMid_Lock);
1711 srvTcp->tcpStatus = CifsExiting;
1712 spin_unlock(&GlobalMid_Lock);
1714 send_sig(SIGKILL,srvTcp->tsk,1);
1716 /* If find_unc succeeded then rc == 0 so we can not end */
1717 if (tcon) /* up accidently freeing someone elses tcon struct */
1719 if (existingCifsSes == NULL) {
1721 if ((pSesInfo->server) &&
1722 (pSesInfo->status == CifsGood)) {
1724 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1725 /* if the socketUseCount is now zero */
1726 if((temp_rc == -ESHUTDOWN) &&
1727 (pSesInfo->server->tsk))
1728 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1730 cFYI(1, ("No session or bad tcon"));
1731 sesInfoFree(pSesInfo);
1732 /* pSesInfo = NULL; */
1736 atomic_inc(&tcon->useCount);
1737 cifs_sb->tcon = tcon;
1738 tcon->ses = pSesInfo;
1740 /* do not care if following two calls succeed - informational only */
1741 CIFSSMBQFSDeviceInfo(xid, tcon);
1742 CIFSSMBQFSAttributeInfo(xid, tcon);
1743 if (tcon->ses->capabilities & CAP_UNIX) {
1744 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1745 if(!volume_info.no_psx_acl) {
1746 if(CIFS_UNIX_POSIX_ACL_CAP &
1747 le64_to_cpu(tcon->fsUnixInfo.Capability))
1748 cFYI(1,("server negotiated posix acl support"));
1749 sb->s_flags |= MS_POSIXACL;
1755 /* volume_info.password is freed above when existing session found
1756 (in which case it is not needed anymore) but when new sesion is created
1757 the password ptr is put in the new session structure (in which case the
1758 password will be freed at unmount time) */
1760 kfree(volume_info.UNC);
1766 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1767 char session_key[CIFS_SESSION_KEY_SIZE],
1768 const struct nls_table *nls_codepage)
1770 struct smb_hdr *smb_buffer;
1771 struct smb_hdr *smb_buffer_response;
1772 SESSION_SETUP_ANDX *pSMB;
1773 SESSION_SETUP_ANDX *pSMBr;
1778 int remaining_words = 0;
1779 int bytes_returned = 0;
1784 cFYI(1, ("In sesssetup "));
1787 user = ses->userName;
1788 domain = ses->domainName;
1789 smb_buffer = cifs_buf_get();
1790 if (smb_buffer == NULL) {
1793 smb_buffer_response = smb_buffer;
1794 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1796 /* send SMBsessionSetup here */
1797 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1798 NULL /* no tCon exists yet */ , 13 /* wct */ );
1800 pSMB->req_no_secext.AndXCommand = 0xFF;
1801 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1802 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1804 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1805 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1807 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1808 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1809 if (ses->capabilities & CAP_UNICODE) {
1810 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1811 capabilities |= CAP_UNICODE;
1813 if (ses->capabilities & CAP_STATUS32) {
1814 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1815 capabilities |= CAP_STATUS32;
1817 if (ses->capabilities & CAP_DFS) {
1818 smb_buffer->Flags2 |= SMBFLG2_DFS;
1819 capabilities |= CAP_DFS;
1821 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1823 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1824 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1826 pSMB->req_no_secext.CaseSensitivePasswordLength =
1827 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1828 bcc_ptr = pByteArea(smb_buffer);
1829 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1830 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1831 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1832 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1834 if (ses->capabilities & CAP_UNICODE) {
1835 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1840 bytes_returned = 0; /* skill null user */
1843 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1845 /* convert number of 16 bit words to bytes */
1846 bcc_ptr += 2 * bytes_returned;
1847 bcc_ptr += 2; /* trailing null */
1850 cifs_strtoUCS((wchar_t *) bcc_ptr,
1851 "CIFS_LINUX_DOM", 32, nls_codepage);
1854 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1856 bcc_ptr += 2 * bytes_returned;
1859 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1861 bcc_ptr += 2 * bytes_returned;
1863 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1865 bcc_ptr += 2 * bytes_returned;
1868 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1870 bcc_ptr += 2 * bytes_returned;
1874 strncpy(bcc_ptr, user, 200);
1875 bcc_ptr += strnlen(user, 200);
1879 if (domain == NULL) {
1880 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1881 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1883 strncpy(bcc_ptr, domain, 64);
1884 bcc_ptr += strnlen(domain, 64);
1888 strcpy(bcc_ptr, "Linux version ");
1889 bcc_ptr += strlen("Linux version ");
1890 strcpy(bcc_ptr, system_utsname.release);
1891 bcc_ptr += strlen(system_utsname.release) + 1;
1892 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1893 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1895 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1896 smb_buffer->smb_buf_length += count;
1897 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1899 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1900 &bytes_returned, 1);
1902 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1903 } else if ((smb_buffer_response->WordCount == 3)
1904 || (smb_buffer_response->WordCount == 4)) {
1905 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1906 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1907 if (action & GUEST_LOGIN)
1908 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1909 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1910 cFYI(1, ("UID = %d ", ses->Suid));
1911 /* response can have either 3 or 4 word count - Samba sends 3 */
1912 bcc_ptr = pByteArea(smb_buffer_response);
1913 if ((pSMBr->resp.hdr.WordCount == 3)
1914 || ((pSMBr->resp.hdr.WordCount == 4)
1915 && (blob_len < pSMBr->resp.ByteCount))) {
1916 if (pSMBr->resp.hdr.WordCount == 4)
1917 bcc_ptr += blob_len;
1919 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1920 if ((long) (bcc_ptr) % 2) {
1922 (BCC(smb_buffer_response) - 1) /2;
1923 bcc_ptr++; /* Unicode strings must be word aligned */
1926 BCC(smb_buffer_response) / 2;
1929 UniStrnlen((wchar_t *) bcc_ptr,
1930 remaining_words - 1);
1931 /* We look for obvious messed up bcc or strings in response so we do not go off
1932 the end since (at least) WIN2K and Windows XP have a major bug in not null
1933 terminating last Unicode string in response */
1934 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1935 if(ses->serverOS == NULL)
1936 goto sesssetup_nomem;
1937 cifs_strfromUCS_le(ses->serverOS,
1938 (wchar_t *)bcc_ptr, len,nls_codepage);
1939 bcc_ptr += 2 * (len + 1);
1940 remaining_words -= len + 1;
1941 ses->serverOS[2 * len] = 0;
1942 ses->serverOS[1 + (2 * len)] = 0;
1943 if (remaining_words > 0) {
1944 len = UniStrnlen((wchar_t *)bcc_ptr,
1946 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
1947 if(ses->serverNOS == NULL)
1948 goto sesssetup_nomem;
1949 cifs_strfromUCS_le(ses->serverNOS,
1950 (wchar_t *)bcc_ptr,len,nls_codepage);
1951 bcc_ptr += 2 * (len + 1);
1952 ses->serverNOS[2 * len] = 0;
1953 ses->serverNOS[1 + (2 * len)] = 0;
1954 if(strncmp(ses->serverNOS,
1955 "NT LAN Manager 4",16) == 0) {
1956 cFYI(1,("NT4 server"));
1957 ses->flags |= CIFS_SES_NT4;
1959 remaining_words -= len + 1;
1960 if (remaining_words > 0) {
1961 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1962 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1964 kcalloc(1, 2*(len+1),GFP_KERNEL);
1965 if(ses->serverDomain == NULL)
1966 goto sesssetup_nomem;
1967 cifs_strfromUCS_le(ses->serverDomain,
1968 (wchar_t *)bcc_ptr,len,nls_codepage);
1969 bcc_ptr += 2 * (len + 1);
1970 ses->serverDomain[2*len] = 0;
1971 ses->serverDomain[1+(2*len)] = 0;
1972 } /* else no more room so create dummy domain string */
1975 kcalloc(1, 2, GFP_KERNEL);
1976 } else { /* no room so create dummy domain and NOS string */
1977 /* if these kcallocs fail not much we
1978 can do, but better to not fail the
1981 kcalloc(1, 2, GFP_KERNEL);
1983 kcalloc(1, 2, GFP_KERNEL);
1985 } else { /* ASCII */
1986 len = strnlen(bcc_ptr, 1024);
1987 if (((long) bcc_ptr + len) - (long)
1988 pByteArea(smb_buffer_response)
1989 <= BCC(smb_buffer_response)) {
1990 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
1991 if(ses->serverOS == NULL)
1992 goto sesssetup_nomem;
1993 strncpy(ses->serverOS,bcc_ptr, len);
1996 bcc_ptr[0] = 0; /* null terminate the string */
1999 len = strnlen(bcc_ptr, 1024);
2000 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2001 if(ses->serverNOS == NULL)
2002 goto sesssetup_nomem;
2003 strncpy(ses->serverNOS, bcc_ptr, len);
2008 len = strnlen(bcc_ptr, 1024);
2009 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2010 if(ses->serverDomain == NULL)
2011 goto sesssetup_nomem;
2012 strncpy(ses->serverDomain, bcc_ptr, len);
2018 ("Variable field of length %d extends beyond end of smb ",
2023 (" Security Blob Length extends beyond end of SMB"));
2027 (" Invalid Word count %d: ",
2028 smb_buffer_response->WordCount));
2031 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2032 since that could make reconnection harder, and
2033 reconnection might be needed to free memory */
2035 cifs_buf_release(smb_buffer);
2041 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2042 char *SecurityBlob,int SecurityBlobLength,
2043 const struct nls_table *nls_codepage)
2045 struct smb_hdr *smb_buffer;
2046 struct smb_hdr *smb_buffer_response;
2047 SESSION_SETUP_ANDX *pSMB;
2048 SESSION_SETUP_ANDX *pSMBr;
2053 int remaining_words = 0;
2054 int bytes_returned = 0;
2059 cFYI(1, ("In spnego sesssetup "));
2062 user = ses->userName;
2063 domain = ses->domainName;
2065 smb_buffer = cifs_buf_get();
2066 if (smb_buffer == NULL) {
2069 smb_buffer_response = smb_buffer;
2070 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2072 /* send SMBsessionSetup here */
2073 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2074 NULL /* no tCon exists yet */ , 12 /* wct */ );
2075 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2076 pSMB->req.AndXCommand = 0xFF;
2077 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2078 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2080 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2081 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2083 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2084 CAP_EXTENDED_SECURITY;
2085 if (ses->capabilities & CAP_UNICODE) {
2086 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2087 capabilities |= CAP_UNICODE;
2089 if (ses->capabilities & CAP_STATUS32) {
2090 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2091 capabilities |= CAP_STATUS32;
2093 if (ses->capabilities & CAP_DFS) {
2094 smb_buffer->Flags2 |= SMBFLG2_DFS;
2095 capabilities |= CAP_DFS;
2097 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2099 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2100 bcc_ptr = pByteArea(smb_buffer);
2101 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2102 bcc_ptr += SecurityBlobLength;
2104 if (ses->capabilities & CAP_UNICODE) {
2105 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2110 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
2111 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2112 bcc_ptr += 2; /* trailing null */
2115 cifs_strtoUCS((wchar_t *) bcc_ptr,
2116 "CIFS_LINUX_DOM", 32, nls_codepage);
2119 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2121 bcc_ptr += 2 * bytes_returned;
2124 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2126 bcc_ptr += 2 * bytes_returned;
2128 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2130 bcc_ptr += 2 * bytes_returned;
2133 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2135 bcc_ptr += 2 * bytes_returned;
2138 strncpy(bcc_ptr, user, 200);
2139 bcc_ptr += strnlen(user, 200);
2142 if (domain == NULL) {
2143 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2144 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2146 strncpy(bcc_ptr, domain, 64);
2147 bcc_ptr += strnlen(domain, 64);
2151 strcpy(bcc_ptr, "Linux version ");
2152 bcc_ptr += strlen("Linux version ");
2153 strcpy(bcc_ptr, system_utsname.release);
2154 bcc_ptr += strlen(system_utsname.release) + 1;
2155 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2156 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2158 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2159 smb_buffer->smb_buf_length += count;
2160 pSMB->req.ByteCount = cpu_to_le16(count);
2162 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2163 &bytes_returned, 1);
2165 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2166 } else if ((smb_buffer_response->WordCount == 3)
2167 || (smb_buffer_response->WordCount == 4)) {
2168 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2170 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2171 if (action & GUEST_LOGIN)
2172 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2174 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2175 cFYI(1, ("UID = %d ", ses->Suid));
2176 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2178 /* BB Fix below to make endian neutral !! */
2180 if ((pSMBr->resp.hdr.WordCount == 3)
2181 || ((pSMBr->resp.hdr.WordCount == 4)
2183 pSMBr->resp.ByteCount))) {
2184 if (pSMBr->resp.hdr.WordCount == 4) {
2188 ("Security Blob Length %d ",
2192 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2193 if ((long) (bcc_ptr) % 2) {
2195 (BCC(smb_buffer_response)
2197 bcc_ptr++; /* Unicode strings must be word aligned */
2201 (smb_buffer_response) / 2;
2204 UniStrnlen((wchar_t *) bcc_ptr,
2205 remaining_words - 1);
2206 /* We look for obvious messed up bcc or strings in response so we do not go off
2207 the end since (at least) WIN2K and Windows XP have a major bug in not null
2208 terminating last Unicode string in response */
2210 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2211 cifs_strfromUCS_le(ses->serverOS,
2215 bcc_ptr += 2 * (len + 1);
2216 remaining_words -= len + 1;
2217 ses->serverOS[2 * len] = 0;
2218 ses->serverOS[1 + (2 * len)] = 0;
2219 if (remaining_words > 0) {
2220 len = UniStrnlen((wchar_t *)bcc_ptr,
2224 kcalloc(1, 2 * (len + 1),
2226 cifs_strfromUCS_le(ses->serverNOS,
2230 bcc_ptr += 2 * (len + 1);
2231 ses->serverNOS[2 * len] = 0;
2232 ses->serverNOS[1 + (2 * len)] = 0;
2233 remaining_words -= len + 1;
2234 if (remaining_words > 0) {
2235 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2236 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2237 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2238 cifs_strfromUCS_le(ses->serverDomain,
2242 bcc_ptr += 2*(len+1);
2243 ses->serverDomain[2*len] = 0;
2244 ses->serverDomain[1+(2*len)] = 0;
2245 } /* else no more room so create dummy domain string */
2248 kcalloc(1, 2,GFP_KERNEL);
2249 } else { /* no room so create dummy domain and NOS string */
2250 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2251 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2253 } else { /* ASCII */
2255 len = strnlen(bcc_ptr, 1024);
2256 if (((long) bcc_ptr + len) - (long)
2257 pByteArea(smb_buffer_response)
2258 <= BCC(smb_buffer_response)) {
2259 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2260 strncpy(ses->serverOS, bcc_ptr, len);
2263 bcc_ptr[0] = 0; /* null terminate the string */
2266 len = strnlen(bcc_ptr, 1024);
2267 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2268 strncpy(ses->serverNOS, bcc_ptr, len);
2273 len = strnlen(bcc_ptr, 1024);
2274 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2275 strncpy(ses->serverDomain, bcc_ptr, len);
2281 ("Variable field of length %d extends beyond end of smb ",
2286 (" Security Blob Length extends beyond end of SMB"));
2289 cERROR(1, ("No session structure passed in."));
2293 (" Invalid Word count %d: ",
2294 smb_buffer_response->WordCount));
2299 cifs_buf_release(smb_buffer);
2305 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2306 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2307 const struct nls_table *nls_codepage)
2309 struct smb_hdr *smb_buffer;
2310 struct smb_hdr *smb_buffer_response;
2311 SESSION_SETUP_ANDX *pSMB;
2312 SESSION_SETUP_ANDX *pSMBr;
2316 int remaining_words = 0;
2317 int bytes_returned = 0;
2319 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2320 PNEGOTIATE_MESSAGE SecurityBlob;
2321 PCHALLENGE_MESSAGE SecurityBlob2;
2322 __u32 negotiate_flags, capabilities;
2325 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2328 domain = ses->domainName;
2329 *pNTLMv2_flag = FALSE;
2330 smb_buffer = cifs_buf_get();
2331 if (smb_buffer == NULL) {
2334 smb_buffer_response = smb_buffer;
2335 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2336 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2338 /* send SMBsessionSetup here */
2339 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2340 NULL /* no tCon exists yet */ , 12 /* wct */ );
2341 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2342 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2344 pSMB->req.AndXCommand = 0xFF;
2345 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2346 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2348 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2349 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2351 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2352 CAP_EXTENDED_SECURITY;
2353 if (ses->capabilities & CAP_UNICODE) {
2354 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2355 capabilities |= CAP_UNICODE;
2357 if (ses->capabilities & CAP_STATUS32) {
2358 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2359 capabilities |= CAP_STATUS32;
2361 if (ses->capabilities & CAP_DFS) {
2362 smb_buffer->Flags2 |= SMBFLG2_DFS;
2363 capabilities |= CAP_DFS;
2365 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2367 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2368 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2369 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2370 SecurityBlob->MessageType = NtLmNegotiate;
2372 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2373 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2374 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2376 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2378 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2379 /* setup pointers to domain name and workstation name */
2380 bcc_ptr += SecurityBlobLength;
2382 SecurityBlob->WorkstationName.Buffer = 0;
2383 SecurityBlob->WorkstationName.Length = 0;
2384 SecurityBlob->WorkstationName.MaximumLength = 0;
2386 if (domain == NULL) {
2387 SecurityBlob->DomainName.Buffer = 0;
2388 SecurityBlob->DomainName.Length = 0;
2389 SecurityBlob->DomainName.MaximumLength = 0;
2392 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2393 strncpy(bcc_ptr, domain, 63);
2394 len = strnlen(domain, 64);
2395 SecurityBlob->DomainName.MaximumLength =
2397 SecurityBlob->DomainName.Buffer =
2398 cpu_to_le32((long) &SecurityBlob->
2400 (long) &SecurityBlob->Signature);
2402 SecurityBlobLength += len;
2403 SecurityBlob->DomainName.Length =
2406 if (ses->capabilities & CAP_UNICODE) {
2407 if ((long) bcc_ptr % 2) {
2413 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2415 bcc_ptr += 2 * bytes_returned;
2417 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2419 bcc_ptr += 2 * bytes_returned;
2420 bcc_ptr += 2; /* null terminate Linux version */
2422 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2424 bcc_ptr += 2 * bytes_returned;
2427 bcc_ptr += 2; /* null terminate network opsys string */
2430 bcc_ptr += 2; /* null domain */
2431 } else { /* ASCII */
2432 strcpy(bcc_ptr, "Linux version ");
2433 bcc_ptr += strlen("Linux version ");
2434 strcpy(bcc_ptr, system_utsname.release);
2435 bcc_ptr += strlen(system_utsname.release) + 1;
2436 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2437 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2438 bcc_ptr++; /* empty domain field */
2441 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2442 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2443 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2444 smb_buffer->smb_buf_length += count;
2445 pSMB->req.ByteCount = cpu_to_le16(count);
2447 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2448 &bytes_returned, 1);
2450 if (smb_buffer_response->Status.CifsError ==
2451 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2455 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2456 } else if ((smb_buffer_response->WordCount == 3)
2457 || (smb_buffer_response->WordCount == 4)) {
2458 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2459 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2461 if (action & GUEST_LOGIN)
2462 cFYI(1, (" Guest login"));
2463 /* Do we want to set anything in SesInfo struct when guest login? */
2465 bcc_ptr = pByteArea(smb_buffer_response);
2466 /* response can have either 3 or 4 word count - Samba sends 3 */
2468 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2469 if (SecurityBlob2->MessageType != NtLmChallenge) {
2471 ("Unexpected NTLMSSP message type received %d",
2472 SecurityBlob2->MessageType));
2474 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2475 cFYI(1, ("UID = %d ", ses->Suid));
2476 if ((pSMBr->resp.hdr.WordCount == 3)
2477 || ((pSMBr->resp.hdr.WordCount == 4)
2479 pSMBr->resp.ByteCount))) {
2481 if (pSMBr->resp.hdr.WordCount == 4) {
2482 bcc_ptr += blob_len;
2484 ("Security Blob Length %d ",
2488 cFYI(1, ("NTLMSSP Challenge rcvd "));
2490 memcpy(ses->server->cryptKey,
2491 SecurityBlob2->Challenge,
2492 CIFS_CRYPTO_KEY_SIZE);
2493 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2494 *pNTLMv2_flag = TRUE;
2496 if((SecurityBlob2->NegotiateFlags &
2497 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2498 || (sign_CIFS_PDUs > 1))
2499 ses->server->secMode |=
2500 SECMODE_SIGN_REQUIRED;
2501 if ((SecurityBlob2->NegotiateFlags &
2502 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2503 ses->server->secMode |=
2504 SECMODE_SIGN_ENABLED;
2506 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2507 if ((long) (bcc_ptr) % 2) {
2509 (BCC(smb_buffer_response)
2511 bcc_ptr++; /* Unicode strings must be word aligned */
2515 (smb_buffer_response) / 2;
2518 UniStrnlen((wchar_t *) bcc_ptr,
2519 remaining_words - 1);
2520 /* We look for obvious messed up bcc or strings in response so we do not go off
2521 the end since (at least) WIN2K and Windows XP have a major bug in not null
2522 terminating last Unicode string in response */
2524 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2525 cifs_strfromUCS_le(ses->serverOS,
2529 bcc_ptr += 2 * (len + 1);
2530 remaining_words -= len + 1;
2531 ses->serverOS[2 * len] = 0;
2532 ses->serverOS[1 + (2 * len)] = 0;
2533 if (remaining_words > 0) {
2534 len = UniStrnlen((wchar_t *)
2539 kcalloc(1, 2 * (len + 1),
2541 cifs_strfromUCS_le(ses->
2547 bcc_ptr += 2 * (len + 1);
2548 ses->serverNOS[2 * len] = 0;
2551 remaining_words -= len + 1;
2552 if (remaining_words > 0) {
2553 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2554 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2579 } /* else no more room so create dummy domain string */
2584 } else { /* no room so create dummy domain and NOS string */
2586 kcalloc(1, 2, GFP_KERNEL);
2588 kcalloc(1, 2, GFP_KERNEL);
2590 } else { /* ASCII */
2591 len = strnlen(bcc_ptr, 1024);
2592 if (((long) bcc_ptr + len) - (long)
2593 pByteArea(smb_buffer_response)
2594 <= BCC(smb_buffer_response)) {
2598 strncpy(ses->serverOS,
2602 bcc_ptr[0] = 0; /* null terminate string */
2605 len = strnlen(bcc_ptr, 1024);
2609 strncpy(ses->serverNOS, bcc_ptr, len);
2614 len = strnlen(bcc_ptr, 1024);
2618 strncpy(ses->serverDomain, bcc_ptr, len);
2624 ("Variable field of length %d extends beyond end of smb ",
2629 (" Security Blob Length extends beyond end of SMB"));
2632 cERROR(1, ("No session structure passed in."));
2636 (" Invalid Word count %d: ",
2637 smb_buffer_response->WordCount));
2642 cifs_buf_release(smb_buffer);
2647 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2648 char *ntlm_session_key, int ntlmv2_flag,
2649 const struct nls_table *nls_codepage)
2651 struct smb_hdr *smb_buffer;
2652 struct smb_hdr *smb_buffer_response;
2653 SESSION_SETUP_ANDX *pSMB;
2654 SESSION_SETUP_ANDX *pSMBr;
2659 int remaining_words = 0;
2660 int bytes_returned = 0;
2662 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2663 PAUTHENTICATE_MESSAGE SecurityBlob;
2664 __u32 negotiate_flags, capabilities;
2667 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2670 user = ses->userName;
2671 domain = ses->domainName;
2672 smb_buffer = cifs_buf_get();
2673 if (smb_buffer == NULL) {
2676 smb_buffer_response = smb_buffer;
2677 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2678 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2680 /* send SMBsessionSetup here */
2681 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2682 NULL /* no tCon exists yet */ , 12 /* wct */ );
2683 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2684 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2685 pSMB->req.AndXCommand = 0xFF;
2686 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2687 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2689 pSMB->req.hdr.Uid = ses->Suid;
2691 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2692 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2694 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2695 CAP_EXTENDED_SECURITY;
2696 if (ses->capabilities & CAP_UNICODE) {
2697 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2698 capabilities |= CAP_UNICODE;
2700 if (ses->capabilities & CAP_STATUS32) {
2701 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2702 capabilities |= CAP_STATUS32;
2704 if (ses->capabilities & CAP_DFS) {
2705 smb_buffer->Flags2 |= SMBFLG2_DFS;
2706 capabilities |= CAP_DFS;
2708 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2710 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2711 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2712 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2713 SecurityBlob->MessageType = NtLmAuthenticate;
2714 bcc_ptr += SecurityBlobLength;
2716 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2717 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2718 0x80000000 | NTLMSSP_NEGOTIATE_128;
2720 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2722 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2724 /* setup pointers to domain name and workstation name */
2726 SecurityBlob->WorkstationName.Buffer = 0;
2727 SecurityBlob->WorkstationName.Length = 0;
2728 SecurityBlob->WorkstationName.MaximumLength = 0;
2729 SecurityBlob->SessionKey.Length = 0;
2730 SecurityBlob->SessionKey.MaximumLength = 0;
2731 SecurityBlob->SessionKey.Buffer = 0;
2733 SecurityBlob->LmChallengeResponse.Length = 0;
2734 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2735 SecurityBlob->LmChallengeResponse.Buffer = 0;
2737 SecurityBlob->NtChallengeResponse.Length =
2738 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2739 SecurityBlob->NtChallengeResponse.MaximumLength =
2740 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2741 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2742 SecurityBlob->NtChallengeResponse.Buffer =
2743 cpu_to_le32(SecurityBlobLength);
2744 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2745 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2747 if (ses->capabilities & CAP_UNICODE) {
2748 if (domain == NULL) {
2749 SecurityBlob->DomainName.Buffer = 0;
2750 SecurityBlob->DomainName.Length = 0;
2751 SecurityBlob->DomainName.MaximumLength = 0;
2754 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2757 SecurityBlob->DomainName.MaximumLength =
2759 SecurityBlob->DomainName.Buffer =
2760 cpu_to_le32(SecurityBlobLength);
2762 SecurityBlobLength += len;
2763 SecurityBlob->DomainName.Length =
2767 SecurityBlob->UserName.Buffer = 0;
2768 SecurityBlob->UserName.Length = 0;
2769 SecurityBlob->UserName.MaximumLength = 0;
2772 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2775 SecurityBlob->UserName.MaximumLength =
2777 SecurityBlob->UserName.Buffer =
2778 cpu_to_le32(SecurityBlobLength);
2780 SecurityBlobLength += len;
2781 SecurityBlob->UserName.Length =
2785 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2786 SecurityBlob->WorkstationName.Length *= 2;
2787 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2788 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2789 bcc_ptr += SecurityBlob->WorkstationName.Length;
2790 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2791 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2793 if ((long) bcc_ptr % 2) {
2798 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2800 bcc_ptr += 2 * bytes_returned;
2802 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2804 bcc_ptr += 2 * bytes_returned;
2805 bcc_ptr += 2; /* null term version string */
2807 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2809 bcc_ptr += 2 * bytes_returned;
2812 bcc_ptr += 2; /* null terminate network opsys string */
2815 bcc_ptr += 2; /* null domain */
2816 } else { /* ASCII */
2817 if (domain == NULL) {
2818 SecurityBlob->DomainName.Buffer = 0;
2819 SecurityBlob->DomainName.Length = 0;
2820 SecurityBlob->DomainName.MaximumLength = 0;
2823 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2824 strncpy(bcc_ptr, domain, 63);
2825 len = strnlen(domain, 64);
2826 SecurityBlob->DomainName.MaximumLength =
2828 SecurityBlob->DomainName.Buffer =
2829 cpu_to_le32(SecurityBlobLength);
2831 SecurityBlobLength += len;
2832 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2835 SecurityBlob->UserName.Buffer = 0;
2836 SecurityBlob->UserName.Length = 0;
2837 SecurityBlob->UserName.MaximumLength = 0;
2840 strncpy(bcc_ptr, user, 63);
2841 len = strnlen(user, 64);
2842 SecurityBlob->UserName.MaximumLength =
2844 SecurityBlob->UserName.Buffer =
2845 cpu_to_le32(SecurityBlobLength);
2847 SecurityBlobLength += len;
2848 SecurityBlob->UserName.Length = cpu_to_le16(len);
2850 /* BB fill in our workstation name if known BB */
2852 strcpy(bcc_ptr, "Linux version ");
2853 bcc_ptr += strlen("Linux version ");
2854 strcpy(bcc_ptr, system_utsname.release);
2855 bcc_ptr += strlen(system_utsname.release) + 1;
2856 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2857 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2858 bcc_ptr++; /* null domain */
2861 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2862 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2863 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2864 smb_buffer->smb_buf_length += count;
2865 pSMB->req.ByteCount = cpu_to_le16(count);
2867 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2868 &bytes_returned, 1);
2870 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2871 } else if ((smb_buffer_response->WordCount == 3)
2872 || (smb_buffer_response->WordCount == 4)) {
2873 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2875 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2876 if (action & GUEST_LOGIN)
2877 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2878 /* if(SecurityBlob2->MessageType != NtLm??){
2879 cFYI("Unexpected message type on auth response is %d "));
2883 ("Does UID on challenge %d match auth response UID %d ",
2884 ses->Suid, smb_buffer_response->Uid));
2885 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2886 bcc_ptr = pByteArea(smb_buffer_response);
2887 /* response can have either 3 or 4 word count - Samba sends 3 */
2888 if ((pSMBr->resp.hdr.WordCount == 3)
2889 || ((pSMBr->resp.hdr.WordCount == 4)
2891 pSMBr->resp.ByteCount))) {
2892 if (pSMBr->resp.hdr.WordCount == 4) {
2896 ("Security Blob Length %d ",
2901 ("NTLMSSP response to Authenticate "));
2903 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2904 if ((long) (bcc_ptr) % 2) {
2906 (BCC(smb_buffer_response)
2908 bcc_ptr++; /* Unicode strings must be word aligned */
2910 remaining_words = BCC(smb_buffer_response) / 2;
2913 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2914 /* We look for obvious messed up bcc or strings in response so we do not go off
2915 the end since (at least) WIN2K and Windows XP have a major bug in not null
2916 terminating last Unicode string in response */
2918 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2919 cifs_strfromUCS_le(ses->serverOS,
2923 bcc_ptr += 2 * (len + 1);
2924 remaining_words -= len + 1;
2925 ses->serverOS[2 * len] = 0;
2926 ses->serverOS[1 + (2 * len)] = 0;
2927 if (remaining_words > 0) {
2928 len = UniStrnlen((wchar_t *)
2933 kcalloc(1, 2 * (len + 1),
2935 cifs_strfromUCS_le(ses->
2941 bcc_ptr += 2 * (len + 1);
2942 ses->serverNOS[2 * len] = 0;
2943 ses->serverNOS[1+(2*len)] = 0;
2944 remaining_words -= len + 1;
2945 if (remaining_words > 0) {
2946 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2947 /* last string not always null terminated (e.g. for Windows XP & 2000) */
2972 } /* else no more room so create dummy domain string */
2974 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
2975 } else { /* no room so create dummy domain and NOS string */
2976 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2977 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2979 } else { /* ASCII */
2980 len = strnlen(bcc_ptr, 1024);
2981 if (((long) bcc_ptr + len) -
2982 (long) pByteArea(smb_buffer_response)
2983 <= BCC(smb_buffer_response)) {
2984 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2985 strncpy(ses->serverOS,bcc_ptr, len);
2988 bcc_ptr[0] = 0; /* null terminate the string */
2991 len = strnlen(bcc_ptr, 1024);
2992 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
2993 strncpy(ses->serverNOS, bcc_ptr, len);
2998 len = strnlen(bcc_ptr, 1024);
2999 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
3000 strncpy(ses->serverDomain, bcc_ptr, len);
3006 ("Variable field of length %d extends beyond end of smb ",
3011 (" Security Blob Length extends beyond end of SMB"));
3014 cERROR(1, ("No session structure passed in."));
3018 (" Invalid Word count %d: ",
3019 smb_buffer_response->WordCount));
3024 cifs_buf_release(smb_buffer);
3030 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3031 const char *tree, struct cifsTconInfo *tcon,
3032 const struct nls_table *nls_codepage)
3034 struct smb_hdr *smb_buffer;
3035 struct smb_hdr *smb_buffer_response;
3038 unsigned char *bcc_ptr;
3046 smb_buffer = cifs_buf_get();
3047 if (smb_buffer == NULL) {
3050 smb_buffer_response = smb_buffer;
3052 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3053 NULL /*no tid */ , 4 /*wct */ );
3054 smb_buffer->Uid = ses->Suid;
3055 pSMB = (TCONX_REQ *) smb_buffer;
3056 pSMBr = (TCONX_RSP *) smb_buffer_response;
3058 pSMB->AndXCommand = 0xFF;
3059 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3060 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3061 bcc_ptr = &pSMB->Password[0];
3062 bcc_ptr++; /* skip password */
3064 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3065 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3067 if (ses->capabilities & CAP_STATUS32) {
3068 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3070 if (ses->capabilities & CAP_DFS) {
3071 smb_buffer->Flags2 |= SMBFLG2_DFS;
3073 if (ses->capabilities & CAP_UNICODE) {
3074 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3076 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
3077 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3078 bcc_ptr += 2; /* skip trailing null */
3079 } else { /* ASCII */
3081 strcpy(bcc_ptr, tree);
3082 bcc_ptr += strlen(tree) + 1;
3084 strcpy(bcc_ptr, "?????");
3085 bcc_ptr += strlen("?????");
3087 count = bcc_ptr - &pSMB->Password[0];
3088 pSMB->hdr.smb_buf_length += count;
3089 pSMB->ByteCount = cpu_to_le16(count);
3091 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3093 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3094 /* above now done in SendReceive */
3095 if ((rc == 0) && (tcon != NULL)) {
3096 tcon->tidStatus = CifsGood;
3097 tcon->tid = smb_buffer_response->Tid;
3098 bcc_ptr = pByteArea(smb_buffer_response);
3099 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3100 /* skip service field (NB: this field is always ASCII) */
3101 bcc_ptr += length + 1;
3102 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3103 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3104 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3105 if ((bcc_ptr + (2 * length)) -
3106 pByteArea(smb_buffer_response) <=
3107 BCC(smb_buffer_response)) {
3108 if(tcon->nativeFileSystem)
3109 kfree(tcon->nativeFileSystem);
3110 tcon->nativeFileSystem =
3111 kcalloc(1, length + 2, GFP_KERNEL);
3112 cifs_strfromUCS_le(tcon->nativeFileSystem,
3113 (wchar_t *) bcc_ptr,
3114 length, nls_codepage);
3115 bcc_ptr += 2 * length;
3116 bcc_ptr[0] = 0; /* null terminate the string */
3120 /* else do not bother copying these informational fields */
3122 length = strnlen(bcc_ptr, 1024);
3123 if ((bcc_ptr + length) -
3124 pByteArea(smb_buffer_response) <=
3125 BCC(smb_buffer_response)) {
3126 if(tcon->nativeFileSystem)
3127 kfree(tcon->nativeFileSystem);
3128 tcon->nativeFileSystem =
3129 kcalloc(1, length + 1, GFP_KERNEL);
3130 strncpy(tcon->nativeFileSystem, bcc_ptr,
3133 /* else do not bother copying these informational fields */
3135 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3136 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3137 } else if ((rc == 0) && tcon == NULL) {
3138 /* all we need to save for IPC$ connection */
3139 ses->ipc_tid = smb_buffer_response->Tid;
3143 cifs_buf_release(smb_buffer);
3148 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3152 struct cifsSesInfo *ses = NULL;
3153 struct task_struct *cifsd_task;
3157 if (cifs_sb->tcon) {
3158 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3159 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3164 tconInfoFree(cifs_sb->tcon);
3165 if ((ses) && (ses->server)) {
3166 /* save off task so we do not refer to ses later */
3167 cifsd_task = ses->server->tsk;
3168 cFYI(1, ("About to do SMBLogoff "));
3169 rc = CIFSSMBLogoff(xid, ses);
3173 } else if (rc == -ESHUTDOWN) {
3174 cFYI(1,("Waking up socket by sending it signal"));
3176 send_sig(SIGKILL,cifsd_task,1);
3178 } /* else - we have an smb session
3179 left on this socket do not kill cifsd */
3181 cFYI(1, ("No session or bad tcon"));
3184 cifs_sb->tcon = NULL;
3186 set_current_state(TASK_INTERRUPTIBLE);
3187 schedule_timeout(HZ / 2);
3193 return rc; /* BB check if we should always return zero here */
3196 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3197 struct nls_table * nls_info)
3200 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3201 int ntlmv2_flag = FALSE;
3204 /* what if server changes its buffer size after dropping the session? */
3205 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3206 rc = CIFSSMBNegotiate(xid, pSesInfo);
3207 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3208 rc = CIFSSMBNegotiate(xid, pSesInfo);
3213 spin_lock(&GlobalMid_Lock);
3214 if(pSesInfo->server->tcpStatus != CifsExiting)
3215 pSesInfo->server->tcpStatus = CifsGood;
3218 spin_unlock(&GlobalMid_Lock);
3224 pSesInfo->capabilities = pSesInfo->server->capabilities;
3225 if(linuxExtEnabled == 0)
3226 pSesInfo->capabilities &= (~CAP_UNIX);
3227 /* pSesInfo->sequence_number = 0;*/
3228 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3229 pSesInfo->server->secMode,
3230 pSesInfo->server->capabilities,
3231 pSesInfo->server->timeZone));
3232 if (extended_security
3233 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3234 && (pSesInfo->server->secType == NTLMSSP)) {
3235 cFYI(1, ("New style sesssetup "));
3236 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3237 NULL /* security blob */,
3238 0 /* blob length */,
3240 } else if (extended_security
3241 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3242 && (pSesInfo->server->secType == RawNTLMSSP)) {
3243 cFYI(1, ("NTLMSSP sesssetup "));
3244 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3251 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3252 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3257 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3259 CalcNTLMv2_response(pSesInfo,v2_response);
3261 cifs_calculate_ntlmv2_mac_key(
3262 pSesInfo->server->mac_signing_key,
3263 response, ntlm_session_key, */
3265 /* BB Put dummy sig in SessSetup PDU? */
3272 SMBNTencrypt(pSesInfo->password,
3273 pSesInfo->server->cryptKey,
3277 cifs_calculate_mac_key(
3278 pSesInfo->server->mac_signing_key,
3280 pSesInfo->password);
3282 /* for better security the weaker lanman hash not sent
3283 in AuthSessSetup so we no longer calculate it */
3285 rc = CIFSNTLMSSPAuthSessSetup(xid,
3291 } else { /* old style NTLM 0.12 session setup */
3292 SMBNTencrypt(pSesInfo->password,
3293 pSesInfo->server->cryptKey,
3297 cifs_calculate_mac_key(
3298 pSesInfo->server->mac_signing_key,
3299 ntlm_session_key, pSesInfo->password);
3301 rc = CIFSSessSetup(xid, pSesInfo,
3302 ntlm_session_key, nls_info);
3305 cERROR(1,("Send error in SessSetup = %d",rc));
3307 cFYI(1,("CIFS Session Established successfully"));
3308 pSesInfo->status = CifsGood;