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 <linux/completion.h>
33 #include <asm/uaccess.h>
34 #include <asm/processor.h>
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
40 #include "cifs_fs_sb.h"
43 #include "rfc1002pdu.h"
46 #define RFC1001_PORT 139
48 static DECLARE_COMPLETION(cifsd_complete);
50 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
52 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
55 extern mempool_t *cifs_req_poolp;
63 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
64 char *iocharset; /* local code page for mapping to and from Unicode */
65 char source_rfc1001_name[16]; /* netbios name of client */
66 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
76 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
77 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
78 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
80 unsigned remap:1; /* set to remap seven reserved chars in filenames */
81 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
83 unsigned nocase; /* request case insensitive filenames */
84 unsigned nobrl; /* disable sending byte range locks to srv */
88 unsigned short int port;
91 static int ipv4_connect(struct sockaddr_in *psin_server,
92 struct socket **csocket,
94 char * server_netb_name);
95 static int ipv6_connect(struct sockaddr_in6 *psin_server,
96 struct socket **csocket);
100 * cifs tcp session reconnection
102 * mark tcp session as reconnecting so temporarily locked
103 * mark all smb sessions as reconnecting for tcp session
104 * reconnect tcp session
105 * wake up waiters on reconnection? - (not needed currently)
109 cifs_reconnect(struct TCP_Server_Info *server)
112 struct list_head *tmp;
113 struct cifsSesInfo *ses;
114 struct cifsTconInfo *tcon;
115 struct mid_q_entry * mid_entry;
117 spin_lock(&GlobalMid_Lock);
118 if(server->tcpStatus == CifsExiting) {
119 /* the demux thread will exit normally
120 next time through the loop */
121 spin_unlock(&GlobalMid_Lock);
124 server->tcpStatus = CifsNeedReconnect;
125 spin_unlock(&GlobalMid_Lock);
128 cFYI(1, ("Reconnecting tcp session"));
130 /* before reconnecting the tcp session, mark the smb session (uid)
131 and the tid bad so they are not used until reconnected */
132 read_lock(&GlobalSMBSeslock);
133 list_for_each(tmp, &GlobalSMBSessionList) {
134 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
136 if (ses->server == server) {
137 ses->status = CifsNeedReconnect;
141 /* else tcp and smb sessions need reconnection */
143 list_for_each(tmp, &GlobalTreeConnectionList) {
144 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
145 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
146 tcon->tidStatus = CifsNeedReconnect;
149 read_unlock(&GlobalSMBSeslock);
150 /* do not want to be sending data on a socket we are freeing */
151 down(&server->tcpSem);
152 if(server->ssocket) {
153 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
154 server->ssocket->flags));
155 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
156 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
157 server->ssocket->flags));
158 sock_release(server->ssocket);
159 server->ssocket = NULL;
162 spin_lock(&GlobalMid_Lock);
163 list_for_each(tmp, &server->pending_mid_q) {
164 mid_entry = list_entry(tmp, struct
168 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
169 /* Mark other intransit requests as needing
170 retry so we do not immediately mark the
171 session bad again (ie after we reconnect
172 below) as they timeout too */
173 mid_entry->midState = MID_RETRY_NEEDED;
177 spin_unlock(&GlobalMid_Lock);
180 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
182 if(server->protocolType == IPV6) {
183 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
185 rc = ipv4_connect(&server->addr.sockAddr,
187 server->workstation_RFC1001_name,
188 server->server_RFC1001_name);
193 atomic_inc(&tcpSesReconnectCount);
194 spin_lock(&GlobalMid_Lock);
195 if(server->tcpStatus != CifsExiting)
196 server->tcpStatus = CifsGood;
197 server->sequence_number = 0;
198 spin_unlock(&GlobalMid_Lock);
199 /* atomic_set(&server->inFlight,0);*/
200 wake_up(&server->response_q);
208 0 not a transact2, or all data present
209 >0 transact2 with that much data missing
210 -EINVAL = invalid transact2
213 static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
215 struct smb_t2_rsp * pSMBt;
217 int data_in_this_rsp;
220 if(pSMB->Command != SMB_COM_TRANSACTION2)
223 /* check for plausible wct, bcc and t2 data and parm sizes */
224 /* check for parm and data offset going beyond end of smb */
225 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
226 cFYI(1,("invalid transact2 word count"));
230 pSMBt = (struct smb_t2_rsp *)pSMB;
232 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
233 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
235 remaining = total_data_size - data_in_this_rsp;
239 else if(remaining < 0) {
240 cFYI(1,("total data %d smaller than data in frame %d",
241 total_data_size, data_in_this_rsp));
244 cFYI(1,("missing %d bytes from transact2, check next response",
246 if(total_data_size > maxBufSize) {
247 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
248 total_data_size,maxBufSize));
255 static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
257 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
258 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
263 char * data_area_of_target;
264 char * data_area_of_buf2;
267 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
269 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
270 cFYI(1,("total data sizes of primary and secondary t2 differ"));
273 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
275 remaining = total_data_size - total_in_buf;
280 if(remaining == 0) /* nothing to do, ignore */
283 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
284 if(remaining < total_in_buf2) {
285 cFYI(1,("transact2 2nd response contains too much data"));
288 /* find end of first SMB data area */
289 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
290 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
291 /* validate target area */
293 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
294 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
296 data_area_of_target += total_in_buf;
298 /* copy second buffer into end of first buffer */
299 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
300 total_in_buf += total_in_buf2;
301 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
302 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
303 byte_count += total_in_buf2;
304 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
306 byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
307 byte_count += total_in_buf2;
309 /* BB also add check that we are not beyond maximum buffer size */
311 pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
313 if(remaining == total_in_buf2) {
314 cFYI(1,("found the last secondary response"));
315 return 0; /* we are done */
316 } else /* more responses to go */
322 cifs_demultiplex_thread(struct TCP_Server_Info *server)
325 unsigned int pdu_length, total_read;
326 struct smb_hdr *smb_buffer = NULL;
327 struct smb_hdr *bigbuf = NULL;
328 struct smb_hdr *smallbuf = NULL;
329 struct msghdr smb_msg;
331 struct socket *csocket = server->ssocket;
332 struct list_head *tmp;
333 struct cifsSesInfo *ses;
334 struct task_struct *task_to_wake = NULL;
335 struct mid_q_entry *mid_entry;
337 int isLargeBuf = FALSE;
342 allow_signal(SIGKILL);
343 current->flags |= PF_MEMALLOC;
344 server->tsk = current; /* save process info to wake at shutdown */
345 cFYI(1, ("Demultiplex PID: %d", current->pid));
346 write_lock(&GlobalSMBSeslock);
347 atomic_inc(&tcpSesAllocCount);
348 length = tcpSesAllocCount.counter;
349 write_unlock(&GlobalSMBSeslock);
350 complete(&cifsd_complete);
352 mempool_resize(cifs_req_poolp,
353 length + cifs_min_rcv,
357 while (server->tcpStatus != CifsExiting) {
358 if (bigbuf == NULL) {
359 bigbuf = cifs_buf_get();
361 cERROR(1,("No memory for large SMB response"));
363 /* retry will check if exiting */
366 } else if(isLargeBuf) {
367 /* we are reusing a dirtry large buf, clear its start */
368 memset(bigbuf, 0, sizeof (struct smb_hdr));
371 if (smallbuf == NULL) {
372 smallbuf = cifs_small_buf_get();
373 if(smallbuf == NULL) {
374 cERROR(1,("No memory for SMB response"));
376 /* retry will check if exiting */
379 /* beginning of smb buffer is cleared in our buf_get */
380 } else /* if existing small buf clear beginning */
381 memset(smallbuf, 0, sizeof (struct smb_hdr));
385 smb_buffer = smallbuf;
386 iov.iov_base = smb_buffer;
388 smb_msg.msg_control = NULL;
389 smb_msg.msg_controllen = 0;
391 kernel_recvmsg(csocket, &smb_msg,
392 &iov, 1, 4, 0 /* BB see socket.h flags */);
394 if(server->tcpStatus == CifsExiting) {
396 } else if (server->tcpStatus == CifsNeedReconnect) {
397 cFYI(1,("Reconnect after server stopped responding"));
398 cifs_reconnect(server);
399 cFYI(1,("call to reconnect done"));
400 csocket = server->ssocket;
402 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
403 msleep(1); /* minimum sleep to prevent looping
404 allowing socket to clear and app threads to set
405 tcpStatus CifsNeedReconnect if server hung */
407 } else if (length <= 0) {
408 if(server->tcpStatus == CifsNew) {
409 cFYI(1,("tcp session abend after SMBnegprot"));
410 /* some servers kill the TCP session rather than
411 returning an SMB negprot error, in which
412 case reconnecting here is not going to help,
413 and so simply return error to mount */
416 if(length == -EINTR) {
417 cFYI(1,("cifsd thread killed"));
420 cFYI(1,("Reconnect after unexpected peek error %d",
422 cifs_reconnect(server);
423 csocket = server->ssocket;
424 wake_up(&server->response_q);
426 } else if (length < 4) {
428 ("Frame under four bytes received (%d bytes long)",
430 cifs_reconnect(server);
431 csocket = server->ssocket;
432 wake_up(&server->response_q);
436 /* the right amount was read from socket - 4 bytes */
438 pdu_length = ntohl(smb_buffer->smb_buf_length);
439 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
441 temp = (char *) smb_buffer;
442 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
444 } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
445 cFYI(1,("Good RFC 1002 session rsp"));
447 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
448 /* we get this from Windows 98 instead of
449 an error on SMB negprot response */
450 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
452 if(server->tcpStatus == CifsNew) {
453 /* if nack on negprot (rather than
454 ret of smb negprot error) reconnecting
455 not going to help, ret error to mount */
458 /* give server a second to
459 clean up before reconnect attempt */
461 /* always try 445 first on reconnect
462 since we get NACK on some if we ever
463 connected to port 139 (the NACK is
464 since we do not begin with RFC1001
465 session initialize frame) */
466 server->addr.sockAddr.sin_port =
468 cifs_reconnect(server);
469 csocket = server->ssocket;
470 wake_up(&server->response_q);
473 } else if (temp[0] != (char) 0) {
474 cERROR(1,("Unknown RFC 1002 frame"));
475 cifs_dump_mem(" Received Data: ", temp, length);
476 cifs_reconnect(server);
477 csocket = server->ssocket;
481 /* else we have an SMB response */
482 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
483 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
484 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
485 length, pdu_length+4));
486 cifs_reconnect(server);
487 csocket = server->ssocket;
488 wake_up(&server->response_q);
495 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
497 memcpy(bigbuf, smallbuf, 4);
501 iov.iov_base = 4 + (char *)smb_buffer;
502 iov.iov_len = pdu_length;
503 for (total_read = 0; total_read < pdu_length;
504 total_read += length) {
505 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
506 pdu_length - total_read, 0);
507 if((server->tcpStatus == CifsExiting) ||
508 (length == -EINTR)) {
512 } else if (server->tcpStatus == CifsNeedReconnect) {
513 cifs_reconnect(server);
514 csocket = server->ssocket;
515 /* Reconnect wakes up rspns q */
516 /* Now we will reread sock */
519 } else if ((length == -ERESTARTSYS) ||
520 (length == -EAGAIN)) {
521 msleep(1); /* minimum sleep to prevent looping,
522 allowing socket to clear and app
523 threads to set tcpStatus
524 CifsNeedReconnect if server hung*/
526 } else if (length <= 0) {
527 cERROR(1,("Received no data, expecting %d",
528 pdu_length - total_read));
529 cifs_reconnect(server);
530 csocket = server->ssocket;
537 else if(reconnect == 1)
540 length += 4; /* account for rfc1002 hdr */
543 dump_smb(smb_buffer, length);
544 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
545 cERROR(1, ("Bad SMB Received "));
551 spin_lock(&GlobalMid_Lock);
552 list_for_each(tmp, &server->pending_mid_q) {
553 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
555 if ((mid_entry->mid == smb_buffer->Mid) &&
556 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
557 (mid_entry->command == smb_buffer->Command)) {
558 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
559 /* We have a multipart transact2 resp */
561 if(mid_entry->resp_buf) {
562 /* merge response - fix up 1st*/
563 if(coalesce_t2(smb_buffer,
564 mid_entry->resp_buf)) {
567 /* all parts received */
572 cERROR(1,("1st trans2 resp needs bigbuf"));
573 /* BB maybe we can fix this up, switch
574 to already allocated large buffer? */
576 /* Have first buffer */
577 mid_entry->resp_buf =
579 mid_entry->largeBuf = 1;
585 mid_entry->resp_buf = smb_buffer;
587 mid_entry->largeBuf = 1;
589 mid_entry->largeBuf = 0;
591 task_to_wake = mid_entry->tsk;
592 mid_entry->midState = MID_RESPONSE_RECEIVED;
596 spin_unlock(&GlobalMid_Lock);
598 /* Was previous buf put in mpx struct for multi-rsp? */
600 /* smb buffer will be freed by user thread */
606 wake_up_process(task_to_wake);
607 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
608 && (isMultiRsp == FALSE)) {
609 cERROR(1, ("No task to wake, unknown frame rcvd!"));
610 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
612 } /* end while !EXITING */
614 spin_lock(&GlobalMid_Lock);
615 server->tcpStatus = CifsExiting;
617 /* check if we have blocked requests that need to free */
618 /* Note that cifs_max_pending is normally 50, but
619 can be set at module install time to as little as two */
620 if(atomic_read(&server->inFlight) >= cifs_max_pending)
621 atomic_set(&server->inFlight, cifs_max_pending - 1);
622 /* We do not want to set the max_pending too low or we
623 could end up with the counter going negative */
624 spin_unlock(&GlobalMid_Lock);
625 /* Although there should not be any requests blocked on
626 this queue it can not hurt to be paranoid and try to wake up requests
627 that may haven been blocked when more than 50 at time were on the wire
628 to the same server - they now will see the session is in exit state
629 and get out of SendReceive. */
630 wake_up_all(&server->request_q);
631 /* give those requests time to exit */
634 if(server->ssocket) {
635 sock_release(csocket);
636 server->ssocket = NULL;
638 /* buffer usuallly freed in free_mid - need to free it here on exit */
640 cifs_buf_release(bigbuf);
641 if (smallbuf != NULL)
642 cifs_small_buf_release(smallbuf);
644 read_lock(&GlobalSMBSeslock);
645 if (list_empty(&server->pending_mid_q)) {
646 /* loop through server session structures attached to this and
648 list_for_each(tmp, &GlobalSMBSessionList) {
650 list_entry(tmp, struct cifsSesInfo,
652 if (ses->server == server) {
653 ses->status = CifsExiting;
657 read_unlock(&GlobalSMBSeslock);
659 /* although we can not zero the server struct pointer yet,
660 since there are active requests which may depnd on them,
661 mark the corresponding SMB sessions as exiting too */
662 list_for_each(tmp, &GlobalSMBSessionList) {
663 ses = list_entry(tmp, struct cifsSesInfo,
665 if (ses->server == server) {
666 ses->status = CifsExiting;
670 spin_lock(&GlobalMid_Lock);
671 list_for_each(tmp, &server->pending_mid_q) {
672 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
673 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
675 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
676 task_to_wake = mid_entry->tsk;
678 wake_up_process(task_to_wake);
682 spin_unlock(&GlobalMid_Lock);
683 read_unlock(&GlobalSMBSeslock);
684 /* 1/8th of sec is more than enough time for them to exit */
688 if (!list_empty(&server->pending_mid_q)) {
689 /* mpx threads have not exited yet give them
690 at least the smb send timeout time for long ops */
691 /* due to delays on oplock break requests, we need
692 to wait at least 45 seconds before giving up
693 on a request getting a response and going ahead
695 cFYI(1, ("Wait for exit from demultiplex thread"));
697 /* if threads still have not exited they are probably never
698 coming home not much else we can do but free the memory */
701 write_lock(&GlobalSMBSeslock);
702 atomic_dec(&tcpSesAllocCount);
703 length = tcpSesAllocCount.counter;
705 /* last chance to mark ses pointers invalid
706 if there are any pointing to this (e.g
707 if a crazy root user tried to kill cifsd
708 kernel thread explicitly this might happen) */
709 list_for_each(tmp, &GlobalSMBSessionList) {
710 ses = list_entry(tmp, struct cifsSesInfo,
712 if (ses->server == server) {
716 write_unlock(&GlobalSMBSeslock);
720 mempool_resize(cifs_req_poolp,
721 length + cifs_min_rcv,
725 complete_and_exit(&cifsd_complete, 0);
730 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
734 unsigned int temp_len, i, j;
740 memset(vol->source_rfc1001_name,0x20,15);
741 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
742 /* does not have to be a perfect mapping since the field is
743 informational, only used for servers that do not support
744 port 445 and it can be overridden at mount time */
745 vol->source_rfc1001_name[i] =
746 toupper(system_utsname.nodename[i]);
748 vol->source_rfc1001_name[15] = 0;
749 /* null target name indicates to use *SMBSERVR default called name
750 if we end up sending RFC1001 session initialize */
751 vol->target_rfc1001_name[0] = 0;
752 vol->linux_uid = current->uid; /* current->euid instead? */
753 vol->linux_gid = current->gid;
754 vol->dir_mode = S_IRWXUGO;
755 /* 2767 perms indicate mandatory locking support */
756 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
758 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
761 /* default is always to request posix paths. */
762 vol->posix_paths = 1;
767 if(strncmp(options,"sep=",4) == 0) {
768 if(options[4] != 0) {
769 separator[0] = options[4];
772 cFYI(1,("Null separator not allowed"));
776 while ((data = strsep(&options, separator)) != NULL) {
779 if ((value = strchr(data, '=')) != NULL)
782 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
784 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
786 } else if (strnicmp(data, "user", 4) == 0) {
787 if (!value || !*value) {
789 "CIFS: invalid or missing username\n");
790 return 1; /* needs_arg; */
792 if (strnlen(value, 200) < 200) {
793 vol->username = value;
795 printk(KERN_WARNING "CIFS: username too long\n");
798 } else if (strnicmp(data, "pass", 4) == 0) {
800 vol->password = NULL;
802 } else if(value[0] == 0) {
803 /* check if string begins with double comma
804 since that would mean the password really
805 does start with a comma, and would not
806 indicate an empty string */
807 if(value[1] != separator[0]) {
808 vol->password = NULL;
812 temp_len = strlen(value);
813 /* removed password length check, NTLM passwords
814 can be arbitrarily long */
816 /* if comma in password, the string will be
817 prematurely null terminated. Commas in password are
818 specified across the cifs mount interface by a double
819 comma ie ,, and a comma used as in other cases ie ','
820 as a parameter delimiter/separator is single and due
821 to the strsep above is temporarily zeroed. */
823 /* NB: password legally can have multiple commas and
824 the only illegal character in a password is null */
826 if ((value[temp_len] == 0) &&
827 (value[temp_len+1] == separator[0])) {
829 value[temp_len] = separator[0];
830 temp_len+=2; /* move after the second comma */
831 while(value[temp_len] != 0) {
832 if (value[temp_len] == separator[0]) {
833 if (value[temp_len+1] ==
835 /* skip second comma */
838 /* single comma indicating start
845 if(value[temp_len] == 0) {
849 /* point option to start of next parm */
850 options = value + temp_len + 1;
852 /* go from value to value + temp_len condensing
853 double commas to singles. Note that this ends up
854 allocating a few bytes too many, which is ok */
855 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
856 if(vol->password == NULL) {
857 printk("CIFS: no memory for pass\n");
860 for(i=0,j=0;i<temp_len;i++,j++) {
861 vol->password[j] = value[i];
862 if(value[i] == separator[0]
863 && value[i+1] == separator[0]) {
864 /* skip second comma */
868 vol->password[j] = 0;
870 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
871 if(vol->password == NULL) {
872 printk("CIFS: no memory for pass\n");
875 strcpy(vol->password, value);
877 } else if (strnicmp(data, "ip", 2) == 0) {
878 if (!value || !*value) {
880 } else if (strnlen(value, 35) < 35) {
883 printk(KERN_WARNING "CIFS: ip address too long\n");
886 } else if ((strnicmp(data, "unc", 3) == 0)
887 || (strnicmp(data, "target", 6) == 0)
888 || (strnicmp(data, "path", 4) == 0)) {
889 if (!value || !*value) {
891 "CIFS: invalid path to network resource\n");
892 return 1; /* needs_arg; */
894 if ((temp_len = strnlen(value, 300)) < 300) {
895 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
898 strcpy(vol->UNC,value);
899 if (strncmp(vol->UNC, "//", 2) == 0) {
902 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
904 "CIFS: UNC Path does not begin with // or \\\\ \n");
908 printk(KERN_WARNING "CIFS: UNC name too long\n");
911 } else if ((strnicmp(data, "domain", 3) == 0)
912 || (strnicmp(data, "workgroup", 5) == 0)) {
913 if (!value || !*value) {
914 printk(KERN_WARNING "CIFS: invalid domain name\n");
915 return 1; /* needs_arg; */
917 /* BB are there cases in which a comma can be valid in
918 a domain name and need special handling? */
919 if (strnlen(value, 65) < 65) {
920 vol->domainname = value;
921 cFYI(1, ("Domain name set"));
923 printk(KERN_WARNING "CIFS: domain name too long\n");
926 } else if (strnicmp(data, "iocharset", 9) == 0) {
927 if (!value || !*value) {
928 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
929 return 1; /* needs_arg; */
931 if (strnlen(value, 65) < 65) {
932 if(strnicmp(value,"default",7))
933 vol->iocharset = value;
934 /* if iocharset not set load_nls_default used by caller */
935 cFYI(1, ("iocharset set to %s",value));
937 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
940 } else if (strnicmp(data, "uid", 3) == 0) {
941 if (value && *value) {
943 simple_strtoul(value, &value, 0);
945 } else if (strnicmp(data, "gid", 3) == 0) {
946 if (value && *value) {
948 simple_strtoul(value, &value, 0);
950 } else if (strnicmp(data, "file_mode", 4) == 0) {
951 if (value && *value) {
953 simple_strtoul(value, &value, 0);
955 } else if (strnicmp(data, "dir_mode", 4) == 0) {
956 if (value && *value) {
958 simple_strtoul(value, &value, 0);
960 } else if (strnicmp(data, "dirmode", 4) == 0) {
961 if (value && *value) {
963 simple_strtoul(value, &value, 0);
965 } else if (strnicmp(data, "port", 4) == 0) {
966 if (value && *value) {
968 simple_strtoul(value, &value, 0);
970 } else if (strnicmp(data, "rsize", 5) == 0) {
971 if (value && *value) {
973 simple_strtoul(value, &value, 0);
975 } else if (strnicmp(data, "wsize", 5) == 0) {
976 if (value && *value) {
978 simple_strtoul(value, &value, 0);
980 } else if (strnicmp(data, "sockopt", 5) == 0) {
981 if (value && *value) {
983 simple_strtoul(value, &value, 0);
985 } else if (strnicmp(data, "netbiosname", 4) == 0) {
986 if (!value || !*value || (*value == ' ')) {
987 cFYI(1,("invalid (empty) netbiosname specified"));
989 memset(vol->source_rfc1001_name,0x20,15);
991 /* BB are there cases in which a comma can be
992 valid in this workstation netbios name (and need
993 special handling)? */
995 /* We do not uppercase netbiosname for user */
999 vol->source_rfc1001_name[i] = value[i];
1001 /* The string has 16th byte zero still from
1002 set at top of the function */
1003 if((i==15) && (value[i] != 0))
1004 printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
1006 } else if (strnicmp(data, "servern", 7) == 0) {
1007 /* servernetbiosname specified override *SMBSERVER */
1008 if (!value || !*value || (*value == ' ')) {
1009 cFYI(1,("empty server netbiosname specified"));
1011 /* last byte, type, is 0x20 for servr type */
1012 memset(vol->target_rfc1001_name,0x20,16);
1015 /* BB are there cases in which a comma can be
1016 valid in this workstation netbios name (and need
1017 special handling)? */
1019 /* user or mount helper must uppercase netbiosname */
1023 vol->target_rfc1001_name[i] = value[i];
1025 /* The string has 16th byte zero still from
1026 set at top of the function */
1027 if((i==15) && (value[i] != 0))
1028 printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
1030 } else if (strnicmp(data, "credentials", 4) == 0) {
1032 } else if (strnicmp(data, "version", 3) == 0) {
1034 } else if (strnicmp(data, "guest",5) == 0) {
1036 } else if (strnicmp(data, "rw", 2) == 0) {
1038 } else if ((strnicmp(data, "suid", 4) == 0) ||
1039 (strnicmp(data, "nosuid", 6) == 0) ||
1040 (strnicmp(data, "exec", 4) == 0) ||
1041 (strnicmp(data, "noexec", 6) == 0) ||
1042 (strnicmp(data, "nodev", 5) == 0) ||
1043 (strnicmp(data, "noauto", 6) == 0) ||
1044 (strnicmp(data, "dev", 3) == 0)) {
1045 /* The mount tool or mount.cifs helper (if present)
1046 uses these opts to set flags, and the flags are read
1047 by the kernel vfs layer before we get here (ie
1048 before read super) so there is no point trying to
1049 parse these options again and set anything and it
1050 is ok to just ignore them */
1052 } else if (strnicmp(data, "ro", 2) == 0) {
1054 } else if (strnicmp(data, "hard", 4) == 0) {
1056 } else if (strnicmp(data, "soft", 4) == 0) {
1058 } else if (strnicmp(data, "perm", 4) == 0) {
1060 } else if (strnicmp(data, "noperm", 6) == 0) {
1062 } else if (strnicmp(data, "mapchars", 8) == 0) {
1064 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1066 } else if (strnicmp(data, "sfu", 3) == 0) {
1068 } else if (strnicmp(data, "nosfu", 5) == 0) {
1070 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1071 vol->posix_paths = 1;
1072 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1073 vol->posix_paths = 0;
1074 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1075 (strnicmp(data, "ignorecase", 10) == 0)) {
1077 } else if (strnicmp(data, "brl", 3) == 0) {
1079 } else if (strnicmp(data, "nobrl", 5) == 0) {
1081 /* turn off mandatory locking in mode
1082 if remote locking is turned off since the
1083 local vfs will do advisory */
1084 if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1085 vol->file_mode = S_IALLUGO;
1086 } else if (strnicmp(data, "setuids", 7) == 0) {
1088 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1090 } else if (strnicmp(data, "nohard", 6) == 0) {
1092 } else if (strnicmp(data, "nosoft", 6) == 0) {
1094 } else if (strnicmp(data, "nointr", 6) == 0) {
1096 } else if (strnicmp(data, "intr", 4) == 0) {
1098 } else if (strnicmp(data, "serverino",7) == 0) {
1099 vol->server_ino = 1;
1100 } else if (strnicmp(data, "noserverino",9) == 0) {
1101 vol->server_ino = 0;
1102 } else if (strnicmp(data, "acl",3) == 0) {
1103 vol->no_psx_acl = 0;
1104 } else if (strnicmp(data, "noacl",5) == 0) {
1105 vol->no_psx_acl = 1;
1106 } else if (strnicmp(data, "direct",6) == 0) {
1108 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1110 } else if (strnicmp(data, "in6_addr",8) == 0) {
1111 if (!value || !*value) {
1112 vol->in6_addr = NULL;
1113 } else if (strnlen(value, 49) == 48) {
1114 vol->in6_addr = value;
1116 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1119 } else if (strnicmp(data, "noac", 4) == 0) {
1120 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1122 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1124 if (vol->UNC == NULL) {
1125 if(devname == NULL) {
1126 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1129 if ((temp_len = strnlen(devname, 300)) < 300) {
1130 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1131 if(vol->UNC == NULL)
1133 strcpy(vol->UNC,devname);
1134 if (strncmp(vol->UNC, "//", 2) == 0) {
1137 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1138 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1142 printk(KERN_WARNING "CIFS: UNC name too long\n");
1146 if(vol->UNCip == NULL)
1147 vol->UNCip = &vol->UNC[2];
1152 static struct cifsSesInfo *
1153 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1154 struct in6_addr *target_ip6_addr,
1155 char *userName, struct TCP_Server_Info **psrvTcp)
1157 struct list_head *tmp;
1158 struct cifsSesInfo *ses;
1160 read_lock(&GlobalSMBSeslock);
1162 list_for_each(tmp, &GlobalSMBSessionList) {
1163 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1165 if((target_ip_addr &&
1166 (ses->server->addr.sockAddr.sin_addr.s_addr
1167 == target_ip_addr->s_addr)) || (target_ip6_addr
1168 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1169 target_ip6_addr,sizeof(*target_ip6_addr)))){
1170 /* BB lock server and tcp session and increment use count here?? */
1171 *psrvTcp = ses->server; /* found a match on the TCP session */
1172 /* BB check if reconnection needed */
1174 (ses->userName, userName,
1175 MAX_USERNAME_SIZE) == 0){
1176 read_unlock(&GlobalSMBSeslock);
1177 return ses; /* found exact match on both tcp and SMB sessions */
1181 /* else tcp and smb sessions need reconnection */
1183 read_unlock(&GlobalSMBSeslock);
1187 static struct cifsTconInfo *
1188 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1190 struct list_head *tmp;
1191 struct cifsTconInfo *tcon;
1193 read_lock(&GlobalSMBSeslock);
1194 list_for_each(tmp, &GlobalTreeConnectionList) {
1195 cFYI(1, ("Next tcon - "));
1196 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1198 if (tcon->ses->server) {
1200 (" old ip addr: %x == new ip %x ?",
1201 tcon->ses->server->addr.sockAddr.sin_addr.
1202 s_addr, new_target_ip_addr));
1203 if (tcon->ses->server->addr.sockAddr.sin_addr.
1204 s_addr == new_target_ip_addr) {
1205 /* BB lock tcon and server and tcp session and increment use count here? */
1206 /* found a match on the TCP session */
1207 /* BB check if reconnection needed */
1208 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1209 tcon->treeName, uncName));
1211 (tcon->treeName, uncName,
1212 MAX_TREE_SIZE) == 0) {
1214 ("Matched UNC, old user: %s == new: %s ?",
1215 tcon->treeName, uncName));
1217 (tcon->ses->userName,
1219 MAX_USERNAME_SIZE) == 0) {
1220 read_unlock(&GlobalSMBSeslock);
1221 return tcon;/* also matched user (smb session)*/
1228 read_unlock(&GlobalSMBSeslock);
1233 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1234 const char *old_path, const struct nls_table *nls_codepage,
1237 unsigned char *referrals = NULL;
1238 unsigned int num_referrals;
1241 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1242 &num_referrals, &referrals, remap);
1244 /* BB Add in code to: if valid refrl, if not ip address contact
1245 the helper that resolves tcp names, mount to it, try to
1246 tcon to it unmount it if fail */
1255 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1256 const char *old_path, const struct nls_table *nls_codepage,
1257 unsigned int *pnum_referrals,
1258 unsigned char ** preferrals, int remap)
1263 *pnum_referrals = 0;
1265 if (pSesInfo->ipc_tid == 0) {
1266 temp_unc = kmalloc(2 /* for slashes */ +
1267 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1268 + 1 + 4 /* slash IPC$ */ + 2,
1270 if (temp_unc == NULL)
1274 strcpy(temp_unc + 2, pSesInfo->serverName);
1275 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1276 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1278 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1282 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1283 pnum_referrals, nls_codepage, remap);
1288 /* See RFC1001 section 14 on representation of Netbios names */
1289 static void rfc1002mangle(char * target,char * source, unsigned int length)
1293 for(i=0,j=0;i<(length);i++) {
1294 /* mask a nibble at a time and encode */
1295 target[j] = 'A' + (0x0F & (source[i] >> 4));
1296 target[j+1] = 'A' + (0x0F & source[i]);
1304 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1305 char * netbios_name, char * target_name)
1309 __be16 orig_port = 0;
1311 if(*csocket == NULL) {
1312 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1314 cERROR(1, ("Error %d creating socket",rc));
1318 /* BB other socket options to set KEEPALIVE, NODELAY? */
1319 cFYI(1,("Socket created"));
1320 (*csocket)->sk->sk_allocation = GFP_NOFS;
1324 psin_server->sin_family = AF_INET;
1325 if(psin_server->sin_port) { /* user overrode default port */
1326 rc = (*csocket)->ops->connect(*csocket,
1327 (struct sockaddr *) psin_server,
1328 sizeof (struct sockaddr_in),0);
1334 /* save original port so we can retry user specified port
1335 later if fall back ports fail this time */
1336 orig_port = psin_server->sin_port;
1338 /* do not retry on the same port we just failed on */
1339 if(psin_server->sin_port != htons(CIFS_PORT)) {
1340 psin_server->sin_port = htons(CIFS_PORT);
1342 rc = (*csocket)->ops->connect(*csocket,
1343 (struct sockaddr *) psin_server,
1344 sizeof (struct sockaddr_in),0);
1350 psin_server->sin_port = htons(RFC1001_PORT);
1351 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1352 psin_server, sizeof (struct sockaddr_in),0);
1357 /* give up here - unless we want to retry on different
1358 protocol families some day */
1361 psin_server->sin_port = orig_port;
1362 cFYI(1,("Error %d connecting to server via ipv4",rc));
1363 sock_release(*csocket);
1367 /* Eventually check for other socket options to change from
1368 the default. sock_setsockopt not used because it expects
1369 user space buffer */
1370 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1372 /* send RFC1001 sessinit */
1374 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1375 /* some servers require RFC1001 sessinit before sending
1376 negprot - BB check reconnection in case where second
1377 sessinit is sent but no second negprot */
1378 struct rfc1002_session_packet * ses_init_buf;
1379 struct smb_hdr * smb_buf;
1380 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1382 ses_init_buf->trailer.session_req.called_len = 32;
1383 if(target_name && (target_name[0] != 0)) {
1384 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1387 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1388 DEFAULT_CIFS_CALLED_NAME,16);
1391 ses_init_buf->trailer.session_req.calling_len = 32;
1392 /* calling name ends in null (byte 16) from old smb
1394 if(netbios_name && (netbios_name[0] !=0)) {
1395 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1398 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1399 "LINUX_CIFS_CLNT",16);
1401 ses_init_buf->trailer.session_req.scope1 = 0;
1402 ses_init_buf->trailer.session_req.scope2 = 0;
1403 smb_buf = (struct smb_hdr *)ses_init_buf;
1404 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1405 smb_buf->smb_buf_length = 0x81000044;
1406 rc = smb_send(*csocket, smb_buf, 0x44,
1407 (struct sockaddr *)psin_server);
1408 kfree(ses_init_buf);
1410 /* else the negprot may still work without this
1411 even though malloc failed */
1419 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1423 __be16 orig_port = 0;
1425 if(*csocket == NULL) {
1426 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1428 cERROR(1, ("Error %d creating ipv6 socket",rc));
1432 /* BB other socket options to set KEEPALIVE, NODELAY? */
1433 cFYI(1,("ipv6 Socket created"));
1434 (*csocket)->sk->sk_allocation = GFP_NOFS;
1438 psin_server->sin6_family = AF_INET6;
1440 if(psin_server->sin6_port) { /* user overrode default port */
1441 rc = (*csocket)->ops->connect(*csocket,
1442 (struct sockaddr *) psin_server,
1443 sizeof (struct sockaddr_in6),0);
1449 /* save original port so we can retry user specified port
1450 later if fall back ports fail this time */
1452 orig_port = psin_server->sin6_port;
1453 /* do not retry on the same port we just failed on */
1454 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1455 psin_server->sin6_port = htons(CIFS_PORT);
1457 rc = (*csocket)->ops->connect(*csocket,
1458 (struct sockaddr *) psin_server,
1459 sizeof (struct sockaddr_in6),0);
1465 psin_server->sin6_port = htons(RFC1001_PORT);
1466 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1467 psin_server, sizeof (struct sockaddr_in6),0);
1472 /* give up here - unless we want to retry on different
1473 protocol families some day */
1476 psin_server->sin6_port = orig_port;
1477 cFYI(1,("Error %d connecting to server via ipv6",rc));
1478 sock_release(*csocket);
1482 /* Eventually check for other socket options to change from
1483 the default. sock_setsockopt not used because it expects
1484 user space buffer */
1485 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1491 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1492 char *mount_data, const char *devname)
1496 int address_type = AF_INET;
1497 struct socket *csocket = NULL;
1498 struct sockaddr_in sin_server;
1499 struct sockaddr_in6 sin_server6;
1500 struct smb_vol volume_info;
1501 struct cifsSesInfo *pSesInfo = NULL;
1502 struct cifsSesInfo *existingCifsSes = NULL;
1503 struct cifsTconInfo *tcon = NULL;
1504 struct TCP_Server_Info *srvTcp = NULL;
1508 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1510 memset(&volume_info,0,sizeof(struct smb_vol));
1511 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1513 kfree(volume_info.UNC);
1514 if(volume_info.password)
1515 kfree(volume_info.password);
1520 if (volume_info.username) {
1521 /* BB fixme parse for domain name here */
1522 cFYI(1, ("Username: %s ", volume_info.username));
1525 cifserror("No username specified ");
1526 /* In userspace mount helper we can get user name from alternate
1527 locations such as env variables and files on disk */
1529 kfree(volume_info.UNC);
1530 if(volume_info.password)
1531 kfree(volume_info.password);
1536 if (volume_info.UNCip && volume_info.UNC) {
1537 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1540 /* not ipv4 address, try ipv6 */
1541 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1543 address_type = AF_INET6;
1545 address_type = AF_INET;
1549 /* we failed translating address */
1551 kfree(volume_info.UNC);
1552 if(volume_info.password)
1553 kfree(volume_info.password);
1558 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1561 } else if (volume_info.UNCip){
1562 /* BB using ip addr as server name connect to the DFS root below */
1563 cERROR(1,("Connecting to DFS root not implemented yet"));
1565 kfree(volume_info.UNC);
1566 if(volume_info.password)
1567 kfree(volume_info.password);
1570 } else /* which servers DFS root would we conect to */ {
1572 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1574 kfree(volume_info.UNC);
1575 if(volume_info.password)
1576 kfree(volume_info.password);
1581 /* this is needed for ASCII cp to Unicode converts */
1582 if(volume_info.iocharset == NULL) {
1583 cifs_sb->local_nls = load_nls_default();
1584 /* load_nls_default can not return null */
1586 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1587 if(cifs_sb->local_nls == NULL) {
1588 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1590 kfree(volume_info.UNC);
1591 if(volume_info.password)
1592 kfree(volume_info.password);
1598 if(address_type == AF_INET)
1599 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1600 NULL /* no ipv6 addr */,
1601 volume_info.username, &srvTcp);
1602 else if(address_type == AF_INET6)
1603 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1604 &sin_server6.sin6_addr,
1605 volume_info.username, &srvTcp);
1608 kfree(volume_info.UNC);
1609 if(volume_info.password)
1610 kfree(volume_info.password);
1617 cFYI(1, ("Existing tcp session with server found "));
1618 } else { /* create socket */
1619 if(volume_info.port)
1620 sin_server.sin_port = htons(volume_info.port);
1622 sin_server.sin_port = 0;
1623 rc = ipv4_connect(&sin_server,&csocket,
1624 volume_info.source_rfc1001_name,
1625 volume_info.target_rfc1001_name);
1628 ("Error connecting to IPv4 socket. Aborting operation"));
1630 sock_release(csocket);
1632 kfree(volume_info.UNC);
1633 if(volume_info.password)
1634 kfree(volume_info.password);
1639 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1640 if (srvTcp == NULL) {
1642 sock_release(csocket);
1644 kfree(volume_info.UNC);
1645 if(volume_info.password)
1646 kfree(volume_info.password);
1650 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1651 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1652 atomic_set(&srvTcp->inFlight,0);
1653 /* BB Add code for ipv6 case too */
1654 srvTcp->ssocket = csocket;
1655 srvTcp->protocolType = IPV4;
1656 init_waitqueue_head(&srvTcp->response_q);
1657 init_waitqueue_head(&srvTcp->request_q);
1658 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1659 /* at this point we are the only ones with the pointer
1660 to the struct since the kernel thread not created yet
1661 so no need to spinlock this init of tcpStatus */
1662 srvTcp->tcpStatus = CifsNew;
1663 init_MUTEX(&srvTcp->tcpSem);
1664 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1665 CLONE_FS | CLONE_FILES | CLONE_VM);
1668 sock_release(csocket);
1670 kfree(volume_info.UNC);
1671 if(volume_info.password)
1672 kfree(volume_info.password);
1676 wait_for_completion(&cifsd_complete);
1678 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1679 memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
1680 srvTcp->sequence_number = 0;
1684 if (existingCifsSes) {
1685 pSesInfo = existingCifsSes;
1686 cFYI(1, ("Existing smb sess found "));
1687 if(volume_info.password)
1688 kfree(volume_info.password);
1689 /* volume_info.UNC freed at end of function */
1691 cFYI(1, ("Existing smb sess not found "));
1692 pSesInfo = sesInfoAlloc();
1693 if (pSesInfo == NULL)
1696 pSesInfo->server = srvTcp;
1697 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1698 NIPQUAD(sin_server.sin_addr.s_addr));
1702 /* volume_info.password freed at unmount */
1703 if (volume_info.password)
1704 pSesInfo->password = volume_info.password;
1705 if (volume_info.username)
1706 strncpy(pSesInfo->userName,
1707 volume_info.username,MAX_USERNAME_SIZE);
1708 if (volume_info.domainname)
1709 strncpy(pSesInfo->domainName,
1710 volume_info.domainname,MAX_USERNAME_SIZE);
1711 pSesInfo->linux_uid = volume_info.linux_uid;
1712 down(&pSesInfo->sesSem);
1713 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1714 up(&pSesInfo->sesSem);
1716 atomic_inc(&srvTcp->socketUseCount);
1718 if(volume_info.password)
1719 kfree(volume_info.password);
1722 /* search for existing tcon to this server share */
1724 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1725 cifs_sb->rsize = volume_info.rsize;
1727 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1728 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1729 cifs_sb->wsize = volume_info.wsize;
1731 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1732 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1733 cifs_sb->rsize = PAGE_CACHE_SIZE;
1734 /* Windows ME does this */
1735 cFYI(1,("Attempt to set readsize for mount to less than one page (4096)"));
1737 cifs_sb->mnt_uid = volume_info.linux_uid;
1738 cifs_sb->mnt_gid = volume_info.linux_gid;
1739 cifs_sb->mnt_file_mode = volume_info.file_mode;
1740 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1741 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1743 if(volume_info.noperm)
1744 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1745 if(volume_info.setuids)
1746 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1747 if(volume_info.server_ino)
1748 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1749 if(volume_info.remap)
1750 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1751 if(volume_info.no_xattr)
1752 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1753 if(volume_info.sfu_emul)
1754 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1755 if(volume_info.nobrl)
1756 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1758 if(volume_info.direct_io) {
1759 cFYI(1,("mounting share using direct i/o"));
1760 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1764 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1765 volume_info.username);
1767 cFYI(1, ("Found match on UNC path "));
1768 /* we can have only one retry value for a connection
1769 to a share so for resources mounted more than once
1770 to the same server share the last value passed in
1771 for the retry flag is used */
1772 tcon->retry = volume_info.retry;
1773 tcon->nocase = volume_info.nocase;
1775 tcon = tconInfoAlloc();
1779 /* check for null share name ie connect to dfs root */
1781 /* BB check if this works for exactly length three strings */
1782 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1783 && (strchr(volume_info.UNC + 3, '/') ==
1785 rc = connect_to_dfs_path(xid, pSesInfo,
1786 "", cifs_sb->local_nls,
1787 cifs_sb->mnt_cifs_flags &
1788 CIFS_MOUNT_MAP_SPECIAL_CHR);
1790 kfree(volume_info.UNC);
1794 rc = CIFSTCon(xid, pSesInfo,
1796 tcon, cifs_sb->local_nls);
1797 cFYI(1, ("CIFS Tcon rc = %d", rc));
1800 atomic_inc(&pSesInfo->inUse);
1801 tcon->retry = volume_info.retry;
1802 tcon->nocase = volume_info.nocase;
1808 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1809 sb->s_maxbytes = (u64) 1 << 63;
1811 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1814 sb->s_time_gran = 100;
1816 /* on error free sesinfo and tcon struct if needed */
1818 /* if session setup failed, use count is zero but
1819 we still need to free cifsd thread */
1820 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1821 spin_lock(&GlobalMid_Lock);
1822 srvTcp->tcpStatus = CifsExiting;
1823 spin_unlock(&GlobalMid_Lock);
1825 send_sig(SIGKILL,srvTcp->tsk,1);
1826 wait_for_completion(&cifsd_complete);
1829 /* If find_unc succeeded then rc == 0 so we can not end */
1830 if (tcon) /* up accidently freeing someone elses tcon struct */
1832 if (existingCifsSes == NULL) {
1834 if ((pSesInfo->server) &&
1835 (pSesInfo->status == CifsGood)) {
1837 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1838 /* if the socketUseCount is now zero */
1839 if((temp_rc == -ESHUTDOWN) &&
1840 (pSesInfo->server->tsk)) {
1841 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1842 wait_for_completion(&cifsd_complete);
1845 cFYI(1, ("No session or bad tcon"));
1846 sesInfoFree(pSesInfo);
1847 /* pSesInfo = NULL; */
1851 atomic_inc(&tcon->useCount);
1852 cifs_sb->tcon = tcon;
1853 tcon->ses = pSesInfo;
1855 /* do not care if following two calls succeed - informational only */
1856 CIFSSMBQFSDeviceInfo(xid, tcon);
1857 CIFSSMBQFSAttributeInfo(xid, tcon);
1858 if (tcon->ses->capabilities & CAP_UNIX) {
1859 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1860 if(!volume_info.no_psx_acl) {
1861 if(CIFS_UNIX_POSIX_ACL_CAP &
1862 le64_to_cpu(tcon->fsUnixInfo.Capability))
1863 cFYI(1,("server negotiated posix acl support"));
1864 sb->s_flags |= MS_POSIXACL;
1867 /* Try and negotiate POSIX pathnames if we can. */
1868 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
1869 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1870 if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
1871 cFYI(1,("negotiated posix pathnames support"));
1872 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
1874 cFYI(1,("posix pathnames support requested but not supported"));
1881 /* volume_info.password is freed above when existing session found
1882 (in which case it is not needed anymore) but when new sesion is created
1883 the password ptr is put in the new session structure (in which case the
1884 password will be freed at unmount time) */
1886 kfree(volume_info.UNC);
1892 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1893 char session_key[CIFS_SESSION_KEY_SIZE],
1894 const struct nls_table *nls_codepage)
1896 struct smb_hdr *smb_buffer;
1897 struct smb_hdr *smb_buffer_response;
1898 SESSION_SETUP_ANDX *pSMB;
1899 SESSION_SETUP_ANDX *pSMBr;
1904 int remaining_words = 0;
1905 int bytes_returned = 0;
1910 cFYI(1, ("In sesssetup "));
1913 user = ses->userName;
1914 domain = ses->domainName;
1915 smb_buffer = cifs_buf_get();
1916 if (smb_buffer == NULL) {
1919 smb_buffer_response = smb_buffer;
1920 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1922 /* send SMBsessionSetup here */
1923 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1924 NULL /* no tCon exists yet */ , 13 /* wct */ );
1926 smb_buffer->Mid = GetNextMid(ses->server);
1927 pSMB->req_no_secext.AndXCommand = 0xFF;
1928 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1929 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1931 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1932 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1934 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1935 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1936 if (ses->capabilities & CAP_UNICODE) {
1937 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1938 capabilities |= CAP_UNICODE;
1940 if (ses->capabilities & CAP_STATUS32) {
1941 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1942 capabilities |= CAP_STATUS32;
1944 if (ses->capabilities & CAP_DFS) {
1945 smb_buffer->Flags2 |= SMBFLG2_DFS;
1946 capabilities |= CAP_DFS;
1948 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1950 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1951 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1953 pSMB->req_no_secext.CaseSensitivePasswordLength =
1954 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1955 bcc_ptr = pByteArea(smb_buffer);
1956 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1957 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1958 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1959 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1961 if (ses->capabilities & CAP_UNICODE) {
1962 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1967 bytes_returned = 0; /* skill null user */
1970 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1972 /* convert number of 16 bit words to bytes */
1973 bcc_ptr += 2 * bytes_returned;
1974 bcc_ptr += 2; /* trailing null */
1977 cifs_strtoUCS((wchar_t *) bcc_ptr,
1978 "CIFS_LINUX_DOM", 32, nls_codepage);
1981 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1983 bcc_ptr += 2 * bytes_returned;
1986 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1988 bcc_ptr += 2 * bytes_returned;
1990 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1992 bcc_ptr += 2 * bytes_returned;
1995 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1997 bcc_ptr += 2 * bytes_returned;
2001 strncpy(bcc_ptr, user, 200);
2002 bcc_ptr += strnlen(user, 200);
2006 if (domain == NULL) {
2007 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2008 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2010 strncpy(bcc_ptr, domain, 64);
2011 bcc_ptr += strnlen(domain, 64);
2015 strcpy(bcc_ptr, "Linux version ");
2016 bcc_ptr += strlen("Linux version ");
2017 strcpy(bcc_ptr, system_utsname.release);
2018 bcc_ptr += strlen(system_utsname.release) + 1;
2019 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2020 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2022 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2023 smb_buffer->smb_buf_length += count;
2024 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2026 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2027 &bytes_returned, 1);
2029 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2030 } else if ((smb_buffer_response->WordCount == 3)
2031 || (smb_buffer_response->WordCount == 4)) {
2032 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2033 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2034 if (action & GUEST_LOGIN)
2035 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
2036 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2037 cFYI(1, ("UID = %d ", ses->Suid));
2038 /* response can have either 3 or 4 word count - Samba sends 3 */
2039 bcc_ptr = pByteArea(smb_buffer_response);
2040 if ((pSMBr->resp.hdr.WordCount == 3)
2041 || ((pSMBr->resp.hdr.WordCount == 4)
2042 && (blob_len < pSMBr->resp.ByteCount))) {
2043 if (pSMBr->resp.hdr.WordCount == 4)
2044 bcc_ptr += blob_len;
2046 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2047 if ((long) (bcc_ptr) % 2) {
2049 (BCC(smb_buffer_response) - 1) /2;
2050 bcc_ptr++; /* Unicode strings must be word aligned */
2053 BCC(smb_buffer_response) / 2;
2056 UniStrnlen((wchar_t *) bcc_ptr,
2057 remaining_words - 1);
2058 /* We look for obvious messed up bcc or strings in response so we do not go off
2059 the end since (at least) WIN2K and Windows XP have a major bug in not null
2060 terminating last Unicode string in response */
2061 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2062 if(ses->serverOS == NULL)
2063 goto sesssetup_nomem;
2064 cifs_strfromUCS_le(ses->serverOS,
2065 (wchar_t *)bcc_ptr, len,nls_codepage);
2066 bcc_ptr += 2 * (len + 1);
2067 remaining_words -= len + 1;
2068 ses->serverOS[2 * len] = 0;
2069 ses->serverOS[1 + (2 * len)] = 0;
2070 if (remaining_words > 0) {
2071 len = UniStrnlen((wchar_t *)bcc_ptr,
2073 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
2074 if(ses->serverNOS == NULL)
2075 goto sesssetup_nomem;
2076 cifs_strfromUCS_le(ses->serverNOS,
2077 (wchar_t *)bcc_ptr,len,nls_codepage);
2078 bcc_ptr += 2 * (len + 1);
2079 ses->serverNOS[2 * len] = 0;
2080 ses->serverNOS[1 + (2 * len)] = 0;
2081 if(strncmp(ses->serverNOS,
2082 "NT LAN Manager 4",16) == 0) {
2083 cFYI(1,("NT4 server"));
2084 ses->flags |= CIFS_SES_NT4;
2086 remaining_words -= len + 1;
2087 if (remaining_words > 0) {
2088 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2089 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2091 kcalloc(1, 2*(len+1),GFP_KERNEL);
2092 if(ses->serverDomain == NULL)
2093 goto sesssetup_nomem;
2094 cifs_strfromUCS_le(ses->serverDomain,
2095 (wchar_t *)bcc_ptr,len,nls_codepage);
2096 bcc_ptr += 2 * (len + 1);
2097 ses->serverDomain[2*len] = 0;
2098 ses->serverDomain[1+(2*len)] = 0;
2099 } /* else no more room so create dummy domain string */
2102 kcalloc(1, 2, GFP_KERNEL);
2103 } else { /* no room so create dummy domain and NOS string */
2104 /* if these kcallocs fail not much we
2105 can do, but better to not fail the
2108 kcalloc(1, 2, GFP_KERNEL);
2110 kcalloc(1, 2, GFP_KERNEL);
2112 } else { /* ASCII */
2113 len = strnlen(bcc_ptr, 1024);
2114 if (((long) bcc_ptr + len) - (long)
2115 pByteArea(smb_buffer_response)
2116 <= BCC(smb_buffer_response)) {
2117 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2118 if(ses->serverOS == NULL)
2119 goto sesssetup_nomem;
2120 strncpy(ses->serverOS,bcc_ptr, len);
2123 bcc_ptr[0] = 0; /* null terminate the string */
2126 len = strnlen(bcc_ptr, 1024);
2127 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2128 if(ses->serverNOS == NULL)
2129 goto sesssetup_nomem;
2130 strncpy(ses->serverNOS, bcc_ptr, len);
2135 len = strnlen(bcc_ptr, 1024);
2136 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2137 if(ses->serverDomain == NULL)
2138 goto sesssetup_nomem;
2139 strncpy(ses->serverDomain, bcc_ptr, len);
2145 ("Variable field of length %d extends beyond end of smb ",
2150 (" Security Blob Length extends beyond end of SMB"));
2154 (" Invalid Word count %d: ",
2155 smb_buffer_response->WordCount));
2158 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2159 since that could make reconnection harder, and
2160 reconnection might be needed to free memory */
2162 cifs_buf_release(smb_buffer);
2168 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2169 char *SecurityBlob,int SecurityBlobLength,
2170 const struct nls_table *nls_codepage)
2172 struct smb_hdr *smb_buffer;
2173 struct smb_hdr *smb_buffer_response;
2174 SESSION_SETUP_ANDX *pSMB;
2175 SESSION_SETUP_ANDX *pSMBr;
2180 int remaining_words = 0;
2181 int bytes_returned = 0;
2186 cFYI(1, ("In spnego sesssetup "));
2189 user = ses->userName;
2190 domain = ses->domainName;
2192 smb_buffer = cifs_buf_get();
2193 if (smb_buffer == NULL) {
2196 smb_buffer_response = smb_buffer;
2197 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2199 /* send SMBsessionSetup here */
2200 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2201 NULL /* no tCon exists yet */ , 12 /* wct */ );
2203 smb_buffer->Mid = GetNextMid(ses->server);
2204 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2205 pSMB->req.AndXCommand = 0xFF;
2206 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2207 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2209 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2210 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2212 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2213 CAP_EXTENDED_SECURITY;
2214 if (ses->capabilities & CAP_UNICODE) {
2215 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2216 capabilities |= CAP_UNICODE;
2218 if (ses->capabilities & CAP_STATUS32) {
2219 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2220 capabilities |= CAP_STATUS32;
2222 if (ses->capabilities & CAP_DFS) {
2223 smb_buffer->Flags2 |= SMBFLG2_DFS;
2224 capabilities |= CAP_DFS;
2226 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2228 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2229 bcc_ptr = pByteArea(smb_buffer);
2230 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2231 bcc_ptr += SecurityBlobLength;
2233 if (ses->capabilities & CAP_UNICODE) {
2234 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2239 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
2240 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2241 bcc_ptr += 2; /* trailing null */
2244 cifs_strtoUCS((wchar_t *) bcc_ptr,
2245 "CIFS_LINUX_DOM", 32, nls_codepage);
2248 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2250 bcc_ptr += 2 * bytes_returned;
2253 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2255 bcc_ptr += 2 * bytes_returned;
2257 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2259 bcc_ptr += 2 * bytes_returned;
2262 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2264 bcc_ptr += 2 * bytes_returned;
2267 strncpy(bcc_ptr, user, 200);
2268 bcc_ptr += strnlen(user, 200);
2271 if (domain == NULL) {
2272 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2273 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2275 strncpy(bcc_ptr, domain, 64);
2276 bcc_ptr += strnlen(domain, 64);
2280 strcpy(bcc_ptr, "Linux version ");
2281 bcc_ptr += strlen("Linux version ");
2282 strcpy(bcc_ptr, system_utsname.release);
2283 bcc_ptr += strlen(system_utsname.release) + 1;
2284 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2285 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2287 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2288 smb_buffer->smb_buf_length += count;
2289 pSMB->req.ByteCount = cpu_to_le16(count);
2291 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2292 &bytes_returned, 1);
2294 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2295 } else if ((smb_buffer_response->WordCount == 3)
2296 || (smb_buffer_response->WordCount == 4)) {
2297 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2299 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2300 if (action & GUEST_LOGIN)
2301 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2303 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2304 cFYI(1, ("UID = %d ", ses->Suid));
2305 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2307 /* BB Fix below to make endian neutral !! */
2309 if ((pSMBr->resp.hdr.WordCount == 3)
2310 || ((pSMBr->resp.hdr.WordCount == 4)
2312 pSMBr->resp.ByteCount))) {
2313 if (pSMBr->resp.hdr.WordCount == 4) {
2317 ("Security Blob Length %d ",
2321 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2322 if ((long) (bcc_ptr) % 2) {
2324 (BCC(smb_buffer_response)
2326 bcc_ptr++; /* Unicode strings must be word aligned */
2330 (smb_buffer_response) / 2;
2333 UniStrnlen((wchar_t *) bcc_ptr,
2334 remaining_words - 1);
2335 /* We look for obvious messed up bcc or strings in response so we do not go off
2336 the end since (at least) WIN2K and Windows XP have a major bug in not null
2337 terminating last Unicode string in response */
2339 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2340 cifs_strfromUCS_le(ses->serverOS,
2344 bcc_ptr += 2 * (len + 1);
2345 remaining_words -= len + 1;
2346 ses->serverOS[2 * len] = 0;
2347 ses->serverOS[1 + (2 * len)] = 0;
2348 if (remaining_words > 0) {
2349 len = UniStrnlen((wchar_t *)bcc_ptr,
2353 kcalloc(1, 2 * (len + 1),
2355 cifs_strfromUCS_le(ses->serverNOS,
2359 bcc_ptr += 2 * (len + 1);
2360 ses->serverNOS[2 * len] = 0;
2361 ses->serverNOS[1 + (2 * len)] = 0;
2362 remaining_words -= len + 1;
2363 if (remaining_words > 0) {
2364 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2365 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2366 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2367 cifs_strfromUCS_le(ses->serverDomain,
2371 bcc_ptr += 2*(len+1);
2372 ses->serverDomain[2*len] = 0;
2373 ses->serverDomain[1+(2*len)] = 0;
2374 } /* else no more room so create dummy domain string */
2377 kcalloc(1, 2,GFP_KERNEL);
2378 } else { /* no room so create dummy domain and NOS string */
2379 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2380 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2382 } else { /* ASCII */
2384 len = strnlen(bcc_ptr, 1024);
2385 if (((long) bcc_ptr + len) - (long)
2386 pByteArea(smb_buffer_response)
2387 <= BCC(smb_buffer_response)) {
2388 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2389 strncpy(ses->serverOS, bcc_ptr, len);
2392 bcc_ptr[0] = 0; /* null terminate the string */
2395 len = strnlen(bcc_ptr, 1024);
2396 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2397 strncpy(ses->serverNOS, bcc_ptr, len);
2402 len = strnlen(bcc_ptr, 1024);
2403 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2404 strncpy(ses->serverDomain, bcc_ptr, len);
2410 ("Variable field of length %d extends beyond end of smb ",
2415 (" Security Blob Length extends beyond end of SMB"));
2418 cERROR(1, ("No session structure passed in."));
2422 (" Invalid Word count %d: ",
2423 smb_buffer_response->WordCount));
2428 cifs_buf_release(smb_buffer);
2434 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2435 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2436 const struct nls_table *nls_codepage)
2438 struct smb_hdr *smb_buffer;
2439 struct smb_hdr *smb_buffer_response;
2440 SESSION_SETUP_ANDX *pSMB;
2441 SESSION_SETUP_ANDX *pSMBr;
2445 int remaining_words = 0;
2446 int bytes_returned = 0;
2448 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2449 PNEGOTIATE_MESSAGE SecurityBlob;
2450 PCHALLENGE_MESSAGE SecurityBlob2;
2451 __u32 negotiate_flags, capabilities;
2454 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2457 domain = ses->domainName;
2458 *pNTLMv2_flag = FALSE;
2459 smb_buffer = cifs_buf_get();
2460 if (smb_buffer == NULL) {
2463 smb_buffer_response = smb_buffer;
2464 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2465 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2467 /* send SMBsessionSetup here */
2468 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2469 NULL /* no tCon exists yet */ , 12 /* wct */ );
2471 smb_buffer->Mid = GetNextMid(ses->server);
2472 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2473 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2475 pSMB->req.AndXCommand = 0xFF;
2476 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2477 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2479 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2480 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2482 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2483 CAP_EXTENDED_SECURITY;
2484 if (ses->capabilities & CAP_UNICODE) {
2485 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2486 capabilities |= CAP_UNICODE;
2488 if (ses->capabilities & CAP_STATUS32) {
2489 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2490 capabilities |= CAP_STATUS32;
2492 if (ses->capabilities & CAP_DFS) {
2493 smb_buffer->Flags2 |= SMBFLG2_DFS;
2494 capabilities |= CAP_DFS;
2496 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2498 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2499 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2500 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2501 SecurityBlob->MessageType = NtLmNegotiate;
2503 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2504 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2505 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2507 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2509 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2510 /* setup pointers to domain name and workstation name */
2511 bcc_ptr += SecurityBlobLength;
2513 SecurityBlob->WorkstationName.Buffer = 0;
2514 SecurityBlob->WorkstationName.Length = 0;
2515 SecurityBlob->WorkstationName.MaximumLength = 0;
2517 if (domain == NULL) {
2518 SecurityBlob->DomainName.Buffer = 0;
2519 SecurityBlob->DomainName.Length = 0;
2520 SecurityBlob->DomainName.MaximumLength = 0;
2523 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2524 strncpy(bcc_ptr, domain, 63);
2525 len = strnlen(domain, 64);
2526 SecurityBlob->DomainName.MaximumLength =
2528 SecurityBlob->DomainName.Buffer =
2529 cpu_to_le32((long) &SecurityBlob->
2531 (long) &SecurityBlob->Signature);
2533 SecurityBlobLength += len;
2534 SecurityBlob->DomainName.Length =
2537 if (ses->capabilities & CAP_UNICODE) {
2538 if ((long) bcc_ptr % 2) {
2544 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2546 bcc_ptr += 2 * bytes_returned;
2548 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2550 bcc_ptr += 2 * bytes_returned;
2551 bcc_ptr += 2; /* null terminate Linux version */
2553 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2555 bcc_ptr += 2 * bytes_returned;
2558 bcc_ptr += 2; /* null terminate network opsys string */
2561 bcc_ptr += 2; /* null domain */
2562 } else { /* ASCII */
2563 strcpy(bcc_ptr, "Linux version ");
2564 bcc_ptr += strlen("Linux version ");
2565 strcpy(bcc_ptr, system_utsname.release);
2566 bcc_ptr += strlen(system_utsname.release) + 1;
2567 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2568 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2569 bcc_ptr++; /* empty domain field */
2572 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2573 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2574 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2575 smb_buffer->smb_buf_length += count;
2576 pSMB->req.ByteCount = cpu_to_le16(count);
2578 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2579 &bytes_returned, 1);
2581 if (smb_buffer_response->Status.CifsError ==
2582 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2586 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2587 } else if ((smb_buffer_response->WordCount == 3)
2588 || (smb_buffer_response->WordCount == 4)) {
2589 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2590 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2592 if (action & GUEST_LOGIN)
2593 cFYI(1, (" Guest login"));
2594 /* Do we want to set anything in SesInfo struct when guest login? */
2596 bcc_ptr = pByteArea(smb_buffer_response);
2597 /* response can have either 3 or 4 word count - Samba sends 3 */
2599 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2600 if (SecurityBlob2->MessageType != NtLmChallenge) {
2602 ("Unexpected NTLMSSP message type received %d",
2603 SecurityBlob2->MessageType));
2605 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2606 cFYI(1, ("UID = %d ", ses->Suid));
2607 if ((pSMBr->resp.hdr.WordCount == 3)
2608 || ((pSMBr->resp.hdr.WordCount == 4)
2610 pSMBr->resp.ByteCount))) {
2612 if (pSMBr->resp.hdr.WordCount == 4) {
2613 bcc_ptr += blob_len;
2615 ("Security Blob Length %d ",
2619 cFYI(1, ("NTLMSSP Challenge rcvd "));
2621 memcpy(ses->server->cryptKey,
2622 SecurityBlob2->Challenge,
2623 CIFS_CRYPTO_KEY_SIZE);
2624 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2625 *pNTLMv2_flag = TRUE;
2627 if((SecurityBlob2->NegotiateFlags &
2628 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2629 || (sign_CIFS_PDUs > 1))
2630 ses->server->secMode |=
2631 SECMODE_SIGN_REQUIRED;
2632 if ((SecurityBlob2->NegotiateFlags &
2633 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2634 ses->server->secMode |=
2635 SECMODE_SIGN_ENABLED;
2637 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2638 if ((long) (bcc_ptr) % 2) {
2640 (BCC(smb_buffer_response)
2642 bcc_ptr++; /* Unicode strings must be word aligned */
2646 (smb_buffer_response) / 2;
2649 UniStrnlen((wchar_t *) bcc_ptr,
2650 remaining_words - 1);
2651 /* We look for obvious messed up bcc or strings in response so we do not go off
2652 the end since (at least) WIN2K and Windows XP have a major bug in not null
2653 terminating last Unicode string in response */
2655 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2656 cifs_strfromUCS_le(ses->serverOS,
2660 bcc_ptr += 2 * (len + 1);
2661 remaining_words -= len + 1;
2662 ses->serverOS[2 * len] = 0;
2663 ses->serverOS[1 + (2 * len)] = 0;
2664 if (remaining_words > 0) {
2665 len = UniStrnlen((wchar_t *)
2670 kcalloc(1, 2 * (len + 1),
2672 cifs_strfromUCS_le(ses->
2678 bcc_ptr += 2 * (len + 1);
2679 ses->serverNOS[2 * len] = 0;
2682 remaining_words -= len + 1;
2683 if (remaining_words > 0) {
2684 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2685 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2710 } /* else no more room so create dummy domain string */
2715 } else { /* no room so create dummy domain and NOS string */
2717 kcalloc(1, 2, GFP_KERNEL);
2719 kcalloc(1, 2, GFP_KERNEL);
2721 } else { /* ASCII */
2722 len = strnlen(bcc_ptr, 1024);
2723 if (((long) bcc_ptr + len) - (long)
2724 pByteArea(smb_buffer_response)
2725 <= BCC(smb_buffer_response)) {
2729 strncpy(ses->serverOS,
2733 bcc_ptr[0] = 0; /* null terminate string */
2736 len = strnlen(bcc_ptr, 1024);
2740 strncpy(ses->serverNOS, bcc_ptr, len);
2745 len = strnlen(bcc_ptr, 1024);
2749 strncpy(ses->serverDomain, bcc_ptr, len);
2755 ("Variable field of length %d extends beyond end of smb ",
2760 (" Security Blob Length extends beyond end of SMB"));
2763 cERROR(1, ("No session structure passed in."));
2767 (" Invalid Word count %d: ",
2768 smb_buffer_response->WordCount));
2773 cifs_buf_release(smb_buffer);
2778 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2779 char *ntlm_session_key, int ntlmv2_flag,
2780 const struct nls_table *nls_codepage)
2782 struct smb_hdr *smb_buffer;
2783 struct smb_hdr *smb_buffer_response;
2784 SESSION_SETUP_ANDX *pSMB;
2785 SESSION_SETUP_ANDX *pSMBr;
2790 int remaining_words = 0;
2791 int bytes_returned = 0;
2793 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2794 PAUTHENTICATE_MESSAGE SecurityBlob;
2795 __u32 negotiate_flags, capabilities;
2798 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2801 user = ses->userName;
2802 domain = ses->domainName;
2803 smb_buffer = cifs_buf_get();
2804 if (smb_buffer == NULL) {
2807 smb_buffer_response = smb_buffer;
2808 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2809 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2811 /* send SMBsessionSetup here */
2812 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2813 NULL /* no tCon exists yet */ , 12 /* wct */ );
2815 smb_buffer->Mid = GetNextMid(ses->server);
2816 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2817 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2818 pSMB->req.AndXCommand = 0xFF;
2819 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2820 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2822 pSMB->req.hdr.Uid = ses->Suid;
2824 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2825 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2827 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2828 CAP_EXTENDED_SECURITY;
2829 if (ses->capabilities & CAP_UNICODE) {
2830 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2831 capabilities |= CAP_UNICODE;
2833 if (ses->capabilities & CAP_STATUS32) {
2834 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2835 capabilities |= CAP_STATUS32;
2837 if (ses->capabilities & CAP_DFS) {
2838 smb_buffer->Flags2 |= SMBFLG2_DFS;
2839 capabilities |= CAP_DFS;
2841 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2843 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2844 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2845 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2846 SecurityBlob->MessageType = NtLmAuthenticate;
2847 bcc_ptr += SecurityBlobLength;
2849 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2850 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2851 0x80000000 | NTLMSSP_NEGOTIATE_128;
2853 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2855 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2857 /* setup pointers to domain name and workstation name */
2859 SecurityBlob->WorkstationName.Buffer = 0;
2860 SecurityBlob->WorkstationName.Length = 0;
2861 SecurityBlob->WorkstationName.MaximumLength = 0;
2862 SecurityBlob->SessionKey.Length = 0;
2863 SecurityBlob->SessionKey.MaximumLength = 0;
2864 SecurityBlob->SessionKey.Buffer = 0;
2866 SecurityBlob->LmChallengeResponse.Length = 0;
2867 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2868 SecurityBlob->LmChallengeResponse.Buffer = 0;
2870 SecurityBlob->NtChallengeResponse.Length =
2871 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2872 SecurityBlob->NtChallengeResponse.MaximumLength =
2873 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2874 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2875 SecurityBlob->NtChallengeResponse.Buffer =
2876 cpu_to_le32(SecurityBlobLength);
2877 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2878 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2880 if (ses->capabilities & CAP_UNICODE) {
2881 if (domain == NULL) {
2882 SecurityBlob->DomainName.Buffer = 0;
2883 SecurityBlob->DomainName.Length = 0;
2884 SecurityBlob->DomainName.MaximumLength = 0;
2887 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2890 SecurityBlob->DomainName.MaximumLength =
2892 SecurityBlob->DomainName.Buffer =
2893 cpu_to_le32(SecurityBlobLength);
2895 SecurityBlobLength += len;
2896 SecurityBlob->DomainName.Length =
2900 SecurityBlob->UserName.Buffer = 0;
2901 SecurityBlob->UserName.Length = 0;
2902 SecurityBlob->UserName.MaximumLength = 0;
2905 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2908 SecurityBlob->UserName.MaximumLength =
2910 SecurityBlob->UserName.Buffer =
2911 cpu_to_le32(SecurityBlobLength);
2913 SecurityBlobLength += len;
2914 SecurityBlob->UserName.Length =
2918 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2919 SecurityBlob->WorkstationName.Length *= 2;
2920 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2921 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2922 bcc_ptr += SecurityBlob->WorkstationName.Length;
2923 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2924 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2926 if ((long) bcc_ptr % 2) {
2931 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2933 bcc_ptr += 2 * bytes_returned;
2935 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2937 bcc_ptr += 2 * bytes_returned;
2938 bcc_ptr += 2; /* null term version string */
2940 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2942 bcc_ptr += 2 * bytes_returned;
2945 bcc_ptr += 2; /* null terminate network opsys string */
2948 bcc_ptr += 2; /* null domain */
2949 } else { /* ASCII */
2950 if (domain == NULL) {
2951 SecurityBlob->DomainName.Buffer = 0;
2952 SecurityBlob->DomainName.Length = 0;
2953 SecurityBlob->DomainName.MaximumLength = 0;
2956 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2957 strncpy(bcc_ptr, domain, 63);
2958 len = strnlen(domain, 64);
2959 SecurityBlob->DomainName.MaximumLength =
2961 SecurityBlob->DomainName.Buffer =
2962 cpu_to_le32(SecurityBlobLength);
2964 SecurityBlobLength += len;
2965 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2968 SecurityBlob->UserName.Buffer = 0;
2969 SecurityBlob->UserName.Length = 0;
2970 SecurityBlob->UserName.MaximumLength = 0;
2973 strncpy(bcc_ptr, user, 63);
2974 len = strnlen(user, 64);
2975 SecurityBlob->UserName.MaximumLength =
2977 SecurityBlob->UserName.Buffer =
2978 cpu_to_le32(SecurityBlobLength);
2980 SecurityBlobLength += len;
2981 SecurityBlob->UserName.Length = cpu_to_le16(len);
2983 /* BB fill in our workstation name if known BB */
2985 strcpy(bcc_ptr, "Linux version ");
2986 bcc_ptr += strlen("Linux version ");
2987 strcpy(bcc_ptr, system_utsname.release);
2988 bcc_ptr += strlen(system_utsname.release) + 1;
2989 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2990 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2991 bcc_ptr++; /* null domain */
2994 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2995 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2996 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2997 smb_buffer->smb_buf_length += count;
2998 pSMB->req.ByteCount = cpu_to_le16(count);
3000 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3001 &bytes_returned, 1);
3003 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
3004 } else if ((smb_buffer_response->WordCount == 3)
3005 || (smb_buffer_response->WordCount == 4)) {
3006 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3008 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3009 if (action & GUEST_LOGIN)
3010 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
3011 /* if(SecurityBlob2->MessageType != NtLm??){
3012 cFYI("Unexpected message type on auth response is %d "));
3016 ("Does UID on challenge %d match auth response UID %d ",
3017 ses->Suid, smb_buffer_response->Uid));
3018 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
3019 bcc_ptr = pByteArea(smb_buffer_response);
3020 /* response can have either 3 or 4 word count - Samba sends 3 */
3021 if ((pSMBr->resp.hdr.WordCount == 3)
3022 || ((pSMBr->resp.hdr.WordCount == 4)
3024 pSMBr->resp.ByteCount))) {
3025 if (pSMBr->resp.hdr.WordCount == 4) {
3029 ("Security Blob Length %d ",
3034 ("NTLMSSP response to Authenticate "));
3036 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3037 if ((long) (bcc_ptr) % 2) {
3039 (BCC(smb_buffer_response)
3041 bcc_ptr++; /* Unicode strings must be word aligned */
3043 remaining_words = BCC(smb_buffer_response) / 2;
3046 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
3047 /* We look for obvious messed up bcc or strings in response so we do not go off
3048 the end since (at least) WIN2K and Windows XP have a major bug in not null
3049 terminating last Unicode string in response */
3051 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
3052 cifs_strfromUCS_le(ses->serverOS,
3056 bcc_ptr += 2 * (len + 1);
3057 remaining_words -= len + 1;
3058 ses->serverOS[2 * len] = 0;
3059 ses->serverOS[1 + (2 * len)] = 0;
3060 if (remaining_words > 0) {
3061 len = UniStrnlen((wchar_t *)
3066 kcalloc(1, 2 * (len + 1),
3068 cifs_strfromUCS_le(ses->
3074 bcc_ptr += 2 * (len + 1);
3075 ses->serverNOS[2 * len] = 0;
3076 ses->serverNOS[1+(2*len)] = 0;
3077 remaining_words -= len + 1;
3078 if (remaining_words > 0) {
3079 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3080 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3105 } /* else no more room so create dummy domain string */
3107 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
3108 } else { /* no room so create dummy domain and NOS string */
3109 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
3110 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
3112 } else { /* ASCII */
3113 len = strnlen(bcc_ptr, 1024);
3114 if (((long) bcc_ptr + len) -
3115 (long) pByteArea(smb_buffer_response)
3116 <= BCC(smb_buffer_response)) {
3117 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
3118 strncpy(ses->serverOS,bcc_ptr, len);
3121 bcc_ptr[0] = 0; /* null terminate the string */
3124 len = strnlen(bcc_ptr, 1024);
3125 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
3126 strncpy(ses->serverNOS, bcc_ptr, len);
3131 len = strnlen(bcc_ptr, 1024);
3132 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
3133 strncpy(ses->serverDomain, bcc_ptr, len);
3139 ("Variable field of length %d extends beyond end of smb ",
3144 (" Security Blob Length extends beyond end of SMB"));
3147 cERROR(1, ("No session structure passed in."));
3151 (" Invalid Word count %d: ",
3152 smb_buffer_response->WordCount));
3157 cifs_buf_release(smb_buffer);
3163 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3164 const char *tree, struct cifsTconInfo *tcon,
3165 const struct nls_table *nls_codepage)
3167 struct smb_hdr *smb_buffer;
3168 struct smb_hdr *smb_buffer_response;
3171 unsigned char *bcc_ptr;
3179 smb_buffer = cifs_buf_get();
3180 if (smb_buffer == NULL) {
3183 smb_buffer_response = smb_buffer;
3185 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3186 NULL /*no tid */ , 4 /*wct */ );
3188 smb_buffer->Mid = GetNextMid(ses->server);
3189 smb_buffer->Uid = ses->Suid;
3190 pSMB = (TCONX_REQ *) smb_buffer;
3191 pSMBr = (TCONX_RSP *) smb_buffer_response;
3193 pSMB->AndXCommand = 0xFF;
3194 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3195 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3196 bcc_ptr = &pSMB->Password[0];
3197 bcc_ptr++; /* skip password */
3199 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3200 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3202 if (ses->capabilities & CAP_STATUS32) {
3203 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3205 if (ses->capabilities & CAP_DFS) {
3206 smb_buffer->Flags2 |= SMBFLG2_DFS;
3208 if (ses->capabilities & CAP_UNICODE) {
3209 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3211 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
3212 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3213 bcc_ptr += 2; /* skip trailing null */
3214 } else { /* ASCII */
3216 strcpy(bcc_ptr, tree);
3217 bcc_ptr += strlen(tree) + 1;
3219 strcpy(bcc_ptr, "?????");
3220 bcc_ptr += strlen("?????");
3222 count = bcc_ptr - &pSMB->Password[0];
3223 pSMB->hdr.smb_buf_length += count;
3224 pSMB->ByteCount = cpu_to_le16(count);
3226 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3228 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3229 /* above now done in SendReceive */
3230 if ((rc == 0) && (tcon != NULL)) {
3231 tcon->tidStatus = CifsGood;
3232 tcon->tid = smb_buffer_response->Tid;
3233 bcc_ptr = pByteArea(smb_buffer_response);
3234 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3235 /* skip service field (NB: this field is always ASCII) */
3236 bcc_ptr += length + 1;
3237 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3238 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3239 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3240 if ((bcc_ptr + (2 * length)) -
3241 pByteArea(smb_buffer_response) <=
3242 BCC(smb_buffer_response)) {
3243 if(tcon->nativeFileSystem)
3244 kfree(tcon->nativeFileSystem);
3245 tcon->nativeFileSystem =
3246 kcalloc(1, length + 2, GFP_KERNEL);
3247 cifs_strfromUCS_le(tcon->nativeFileSystem,
3248 (wchar_t *) bcc_ptr,
3249 length, nls_codepage);
3250 bcc_ptr += 2 * length;
3251 bcc_ptr[0] = 0; /* null terminate the string */
3255 /* else do not bother copying these informational fields */
3257 length = strnlen(bcc_ptr, 1024);
3258 if ((bcc_ptr + length) -
3259 pByteArea(smb_buffer_response) <=
3260 BCC(smb_buffer_response)) {
3261 if(tcon->nativeFileSystem)
3262 kfree(tcon->nativeFileSystem);
3263 tcon->nativeFileSystem =
3264 kcalloc(1, length + 1, GFP_KERNEL);
3265 strncpy(tcon->nativeFileSystem, bcc_ptr,
3268 /* else do not bother copying these informational fields */
3270 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3271 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3272 } else if ((rc == 0) && tcon == NULL) {
3273 /* all we need to save for IPC$ connection */
3274 ses->ipc_tid = smb_buffer_response->Tid;
3278 cifs_buf_release(smb_buffer);
3283 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3287 struct cifsSesInfo *ses = NULL;
3288 struct task_struct *cifsd_task;
3292 if (cifs_sb->tcon) {
3293 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3294 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3299 tconInfoFree(cifs_sb->tcon);
3300 if ((ses) && (ses->server)) {
3301 /* save off task so we do not refer to ses later */
3302 cifsd_task = ses->server->tsk;
3303 cFYI(1, ("About to do SMBLogoff "));
3304 rc = CIFSSMBLogoff(xid, ses);
3308 } else if (rc == -ESHUTDOWN) {
3309 cFYI(1,("Waking up socket by sending it signal"));
3311 send_sig(SIGKILL,cifsd_task,1);
3312 wait_for_completion(&cifsd_complete);
3315 } /* else - we have an smb session
3316 left on this socket do not kill cifsd */
3318 cFYI(1, ("No session or bad tcon"));
3321 cifs_sb->tcon = NULL;
3323 set_current_state(TASK_INTERRUPTIBLE);
3324 schedule_timeout(HZ / 2);
3330 return rc; /* BB check if we should always return zero here */
3333 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3334 struct nls_table * nls_info)
3337 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3338 int ntlmv2_flag = FALSE;
3341 /* what if server changes its buffer size after dropping the session? */
3342 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3343 rc = CIFSSMBNegotiate(xid, pSesInfo);
3344 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3345 rc = CIFSSMBNegotiate(xid, pSesInfo);
3350 spin_lock(&GlobalMid_Lock);
3351 if(pSesInfo->server->tcpStatus != CifsExiting)
3352 pSesInfo->server->tcpStatus = CifsGood;
3355 spin_unlock(&GlobalMid_Lock);
3361 pSesInfo->capabilities = pSesInfo->server->capabilities;
3362 if(linuxExtEnabled == 0)
3363 pSesInfo->capabilities &= (~CAP_UNIX);
3364 /* pSesInfo->sequence_number = 0;*/
3365 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3366 pSesInfo->server->secMode,
3367 pSesInfo->server->capabilities,
3368 pSesInfo->server->timeZone));
3369 if (extended_security
3370 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3371 && (pSesInfo->server->secType == NTLMSSP)) {
3372 cFYI(1, ("New style sesssetup "));
3373 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3374 NULL /* security blob */,
3375 0 /* blob length */,
3377 } else if (extended_security
3378 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3379 && (pSesInfo->server->secType == RawNTLMSSP)) {
3380 cFYI(1, ("NTLMSSP sesssetup "));
3381 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3388 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3389 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3394 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3396 CalcNTLMv2_response(pSesInfo,v2_response);
3398 cifs_calculate_ntlmv2_mac_key(
3399 pSesInfo->server->mac_signing_key,
3400 response, ntlm_session_key, */
3402 /* BB Put dummy sig in SessSetup PDU? */
3409 SMBNTencrypt(pSesInfo->password,
3410 pSesInfo->server->cryptKey,
3414 cifs_calculate_mac_key(
3415 pSesInfo->server->mac_signing_key,
3417 pSesInfo->password);
3419 /* for better security the weaker lanman hash not sent
3420 in AuthSessSetup so we no longer calculate it */
3422 rc = CIFSNTLMSSPAuthSessSetup(xid,
3428 } else { /* old style NTLM 0.12 session setup */
3429 SMBNTencrypt(pSesInfo->password,
3430 pSesInfo->server->cryptKey,
3434 cifs_calculate_mac_key(
3435 pSesInfo->server->mac_signing_key,
3436 ntlm_session_key, pSesInfo->password);
3438 rc = CIFSSessSetup(xid, pSesInfo,
3439 ntlm_session_key, nls_info);
3442 cERROR(1,("Send error in SessSetup = %d",rc));
3444 cFYI(1,("CIFS Session Established successfully"));
3445 pSesInfo->status = CifsGood;