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 = 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 = 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) {
360 if (bigbuf == NULL) {
361 bigbuf = cifs_buf_get();
363 cERROR(1,("No memory for large SMB response"));
365 /* retry will check if exiting */
368 } else if(isLargeBuf) {
369 /* we are reusing a dirtry large buf, clear its start */
370 memset(bigbuf, 0, sizeof (struct smb_hdr));
373 if (smallbuf == NULL) {
374 smallbuf = cifs_small_buf_get();
375 if(smallbuf == NULL) {
376 cERROR(1,("No memory for SMB response"));
378 /* retry will check if exiting */
381 /* beginning of smb buffer is cleared in our buf_get */
382 } else /* if existing small buf clear beginning */
383 memset(smallbuf, 0, sizeof (struct smb_hdr));
387 smb_buffer = smallbuf;
388 iov.iov_base = smb_buffer;
390 smb_msg.msg_control = NULL;
391 smb_msg.msg_controllen = 0;
393 kernel_recvmsg(csocket, &smb_msg,
394 &iov, 1, 4, 0 /* BB see socket.h flags */);
396 if(server->tcpStatus == CifsExiting) {
398 } else if (server->tcpStatus == CifsNeedReconnect) {
399 cFYI(1,("Reconnect after server stopped responding"));
400 cifs_reconnect(server);
401 cFYI(1,("call to reconnect done"));
402 csocket = server->ssocket;
404 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
405 msleep(1); /* minimum sleep to prevent looping
406 allowing socket to clear and app threads to set
407 tcpStatus CifsNeedReconnect if server hung */
409 } else if (length <= 0) {
410 if(server->tcpStatus == CifsNew) {
411 cFYI(1,("tcp session abend after SMBnegprot"));
412 /* some servers kill the TCP session rather than
413 returning an SMB negprot error, in which
414 case reconnecting here is not going to help,
415 and so simply return error to mount */
418 if(length == -EINTR) {
419 cFYI(1,("cifsd thread killed"));
422 cFYI(1,("Reconnect after unexpected peek error %d",
424 cifs_reconnect(server);
425 csocket = server->ssocket;
426 wake_up(&server->response_q);
428 } else if (length < 4) {
430 ("Frame under four bytes received (%d bytes long)",
432 cifs_reconnect(server);
433 csocket = server->ssocket;
434 wake_up(&server->response_q);
438 /* The right amount was read from socket - 4 bytes */
439 /* so we can now interpret the length field */
441 /* the first byte big endian of the length field,
442 is actually not part of the length but the type
443 with the most common, zero, as regular data */
444 temp = *((char *) smb_buffer);
446 /* Note that FC 1001 length is big endian on the wire,
447 but we convert it here so it is always manipulated
448 as host byte order */
449 pdu_length = ntohl(smb_buffer->smb_buf_length);
450 smb_buffer->smb_buf_length = pdu_length;
452 cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
454 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
456 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
457 cFYI(1,("Good RFC 1002 session rsp"));
459 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
460 /* we get this from Windows 98 instead of
461 an error on SMB negprot response */
462 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
464 if(server->tcpStatus == CifsNew) {
465 /* if nack on negprot (rather than
466 ret of smb negprot error) reconnecting
467 not going to help, ret error to mount */
470 /* give server a second to
471 clean up before reconnect attempt */
473 /* always try 445 first on reconnect
474 since we get NACK on some if we ever
475 connected to port 139 (the NACK is
476 since we do not begin with RFC1001
477 session initialize frame) */
478 server->addr.sockAddr.sin_port =
480 cifs_reconnect(server);
481 csocket = server->ssocket;
482 wake_up(&server->response_q);
485 } else if (temp != (char) 0) {
486 cERROR(1,("Unknown RFC 1002 frame"));
487 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
489 cifs_reconnect(server);
490 csocket = server->ssocket;
494 /* else we have an SMB response */
495 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
496 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
497 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
498 length, pdu_length+4));
499 cifs_reconnect(server);
500 csocket = server->ssocket;
501 wake_up(&server->response_q);
508 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
510 memcpy(bigbuf, smallbuf, 4);
514 iov.iov_base = 4 + (char *)smb_buffer;
515 iov.iov_len = pdu_length;
516 for (total_read = 0; total_read < pdu_length;
517 total_read += length) {
518 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
519 pdu_length - total_read, 0);
520 if((server->tcpStatus == CifsExiting) ||
521 (length == -EINTR)) {
525 } else if (server->tcpStatus == CifsNeedReconnect) {
526 cifs_reconnect(server);
527 csocket = server->ssocket;
528 /* Reconnect wakes up rspns q */
529 /* Now we will reread sock */
532 } else if ((length == -ERESTARTSYS) ||
533 (length == -EAGAIN)) {
534 msleep(1); /* minimum sleep to prevent looping,
535 allowing socket to clear and app
536 threads to set tcpStatus
537 CifsNeedReconnect if server hung*/
539 } else if (length <= 0) {
540 cERROR(1,("Received no data, expecting %d",
541 pdu_length - total_read));
542 cifs_reconnect(server);
543 csocket = server->ssocket;
550 else if(reconnect == 1)
553 length += 4; /* account for rfc1002 hdr */
556 dump_smb(smb_buffer, length);
557 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
558 cERROR(1, ("Bad SMB Received "));
564 spin_lock(&GlobalMid_Lock);
565 list_for_each(tmp, &server->pending_mid_q) {
566 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
568 if ((mid_entry->mid == smb_buffer->Mid) &&
569 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
570 (mid_entry->command == smb_buffer->Command)) {
571 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
572 /* We have a multipart transact2 resp */
574 if(mid_entry->resp_buf) {
575 /* merge response - fix up 1st*/
576 if(coalesce_t2(smb_buffer,
577 mid_entry->resp_buf)) {
580 /* all parts received */
585 cERROR(1,("1st trans2 resp needs bigbuf"));
586 /* BB maybe we can fix this up, switch
587 to already allocated large buffer? */
589 /* Have first buffer */
590 mid_entry->resp_buf =
592 mid_entry->largeBuf = 1;
598 mid_entry->resp_buf = smb_buffer;
600 mid_entry->largeBuf = 1;
602 mid_entry->largeBuf = 0;
604 task_to_wake = mid_entry->tsk;
605 mid_entry->midState = MID_RESPONSE_RECEIVED;
609 spin_unlock(&GlobalMid_Lock);
611 /* Was previous buf put in mpx struct for multi-rsp? */
613 /* smb buffer will be freed by user thread */
619 wake_up_process(task_to_wake);
620 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
621 && (isMultiRsp == FALSE)) {
622 cERROR(1, ("No task to wake, unknown frame rcvd!"));
623 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
624 sizeof(struct smb_hdr));
626 } /* end while !EXITING */
628 spin_lock(&GlobalMid_Lock);
629 server->tcpStatus = CifsExiting;
631 /* check if we have blocked requests that need to free */
632 /* Note that cifs_max_pending is normally 50, but
633 can be set at module install time to as little as two */
634 if(atomic_read(&server->inFlight) >= cifs_max_pending)
635 atomic_set(&server->inFlight, cifs_max_pending - 1);
636 /* We do not want to set the max_pending too low or we
637 could end up with the counter going negative */
638 spin_unlock(&GlobalMid_Lock);
639 /* Although there should not be any requests blocked on
640 this queue it can not hurt to be paranoid and try to wake up requests
641 that may haven been blocked when more than 50 at time were on the wire
642 to the same server - they now will see the session is in exit state
643 and get out of SendReceive. */
644 wake_up_all(&server->request_q);
645 /* give those requests time to exit */
648 if(server->ssocket) {
649 sock_release(csocket);
650 server->ssocket = NULL;
652 /* buffer usuallly freed in free_mid - need to free it here on exit */
654 cifs_buf_release(bigbuf);
655 if (smallbuf != NULL)
656 cifs_small_buf_release(smallbuf);
658 read_lock(&GlobalSMBSeslock);
659 if (list_empty(&server->pending_mid_q)) {
660 /* loop through server session structures attached to this and
662 list_for_each(tmp, &GlobalSMBSessionList) {
664 list_entry(tmp, struct cifsSesInfo,
666 if (ses->server == server) {
667 ses->status = CifsExiting;
671 read_unlock(&GlobalSMBSeslock);
673 /* although we can not zero the server struct pointer yet,
674 since there are active requests which may depnd on them,
675 mark the corresponding SMB sessions as exiting too */
676 list_for_each(tmp, &GlobalSMBSessionList) {
677 ses = list_entry(tmp, struct cifsSesInfo,
679 if (ses->server == server) {
680 ses->status = CifsExiting;
684 spin_lock(&GlobalMid_Lock);
685 list_for_each(tmp, &server->pending_mid_q) {
686 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
687 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
689 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
690 task_to_wake = mid_entry->tsk;
692 wake_up_process(task_to_wake);
696 spin_unlock(&GlobalMid_Lock);
697 read_unlock(&GlobalSMBSeslock);
698 /* 1/8th of sec is more than enough time for them to exit */
702 if (!list_empty(&server->pending_mid_q)) {
703 /* mpx threads have not exited yet give them
704 at least the smb send timeout time for long ops */
705 /* due to delays on oplock break requests, we need
706 to wait at least 45 seconds before giving up
707 on a request getting a response and going ahead
709 cFYI(1, ("Wait for exit from demultiplex thread"));
711 /* if threads still have not exited they are probably never
712 coming home not much else we can do but free the memory */
715 write_lock(&GlobalSMBSeslock);
716 atomic_dec(&tcpSesAllocCount);
717 length = tcpSesAllocCount.counter;
719 /* last chance to mark ses pointers invalid
720 if there are any pointing to this (e.g
721 if a crazy root user tried to kill cifsd
722 kernel thread explicitly this might happen) */
723 list_for_each(tmp, &GlobalSMBSessionList) {
724 ses = list_entry(tmp, struct cifsSesInfo,
726 if (ses->server == server) {
730 write_unlock(&GlobalSMBSeslock);
734 mempool_resize(cifs_req_poolp,
735 length + cifs_min_rcv,
739 complete_and_exit(&cifsd_complete, 0);
744 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
748 unsigned int temp_len, i, j;
754 memset(vol->source_rfc1001_name,0x20,15);
755 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
756 /* does not have to be a perfect mapping since the field is
757 informational, only used for servers that do not support
758 port 445 and it can be overridden at mount time */
759 vol->source_rfc1001_name[i] =
760 toupper(system_utsname.nodename[i]);
762 vol->source_rfc1001_name[15] = 0;
763 /* null target name indicates to use *SMBSERVR default called name
764 if we end up sending RFC1001 session initialize */
765 vol->target_rfc1001_name[0] = 0;
766 vol->linux_uid = current->uid; /* current->euid instead? */
767 vol->linux_gid = current->gid;
768 vol->dir_mode = S_IRWXUGO;
769 /* 2767 perms indicate mandatory locking support */
770 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
772 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
775 /* default is always to request posix paths. */
776 vol->posix_paths = 1;
781 if(strncmp(options,"sep=",4) == 0) {
782 if(options[4] != 0) {
783 separator[0] = options[4];
786 cFYI(1,("Null separator not allowed"));
790 while ((data = strsep(&options, separator)) != NULL) {
793 if ((value = strchr(data, '=')) != NULL)
796 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
798 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
800 } else if (strnicmp(data, "user", 4) == 0) {
801 if (!value || !*value) {
803 "CIFS: invalid or missing username\n");
804 return 1; /* needs_arg; */
806 if (strnlen(value, 200) < 200) {
807 vol->username = value;
809 printk(KERN_WARNING "CIFS: username too long\n");
812 } else if (strnicmp(data, "pass", 4) == 0) {
814 vol->password = NULL;
816 } else if(value[0] == 0) {
817 /* check if string begins with double comma
818 since that would mean the password really
819 does start with a comma, and would not
820 indicate an empty string */
821 if(value[1] != separator[0]) {
822 vol->password = NULL;
826 temp_len = strlen(value);
827 /* removed password length check, NTLM passwords
828 can be arbitrarily long */
830 /* if comma in password, the string will be
831 prematurely null terminated. Commas in password are
832 specified across the cifs mount interface by a double
833 comma ie ,, and a comma used as in other cases ie ','
834 as a parameter delimiter/separator is single and due
835 to the strsep above is temporarily zeroed. */
837 /* NB: password legally can have multiple commas and
838 the only illegal character in a password is null */
840 if ((value[temp_len] == 0) &&
841 (value[temp_len+1] == separator[0])) {
843 value[temp_len] = separator[0];
844 temp_len+=2; /* move after the second comma */
845 while(value[temp_len] != 0) {
846 if (value[temp_len] == separator[0]) {
847 if (value[temp_len+1] ==
849 /* skip second comma */
852 /* single comma indicating start
859 if(value[temp_len] == 0) {
863 /* point option to start of next parm */
864 options = value + temp_len + 1;
866 /* go from value to value + temp_len condensing
867 double commas to singles. Note that this ends up
868 allocating a few bytes too many, which is ok */
869 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
870 if(vol->password == NULL) {
871 printk("CIFS: no memory for pass\n");
874 for(i=0,j=0;i<temp_len;i++,j++) {
875 vol->password[j] = value[i];
876 if(value[i] == separator[0]
877 && value[i+1] == separator[0]) {
878 /* skip second comma */
882 vol->password[j] = 0;
884 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
885 if(vol->password == NULL) {
886 printk("CIFS: no memory for pass\n");
889 strcpy(vol->password, value);
891 } else if (strnicmp(data, "ip", 2) == 0) {
892 if (!value || !*value) {
894 } else if (strnlen(value, 35) < 35) {
897 printk(KERN_WARNING "CIFS: ip address too long\n");
900 } else if ((strnicmp(data, "unc", 3) == 0)
901 || (strnicmp(data, "target", 6) == 0)
902 || (strnicmp(data, "path", 4) == 0)) {
903 if (!value || !*value) {
905 "CIFS: invalid path to network resource\n");
906 return 1; /* needs_arg; */
908 if ((temp_len = strnlen(value, 300)) < 300) {
909 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
912 strcpy(vol->UNC,value);
913 if (strncmp(vol->UNC, "//", 2) == 0) {
916 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
918 "CIFS: UNC Path does not begin with // or \\\\ \n");
922 printk(KERN_WARNING "CIFS: UNC name too long\n");
925 } else if ((strnicmp(data, "domain", 3) == 0)
926 || (strnicmp(data, "workgroup", 5) == 0)) {
927 if (!value || !*value) {
928 printk(KERN_WARNING "CIFS: invalid domain name\n");
929 return 1; /* needs_arg; */
931 /* BB are there cases in which a comma can be valid in
932 a domain name and need special handling? */
933 if (strnlen(value, 65) < 65) {
934 vol->domainname = value;
935 cFYI(1, ("Domain name set"));
937 printk(KERN_WARNING "CIFS: domain name too long\n");
940 } else if (strnicmp(data, "iocharset", 9) == 0) {
941 if (!value || !*value) {
942 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
943 return 1; /* needs_arg; */
945 if (strnlen(value, 65) < 65) {
946 if(strnicmp(value,"default",7))
947 vol->iocharset = value;
948 /* if iocharset not set load_nls_default used by caller */
949 cFYI(1, ("iocharset set to %s",value));
951 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
954 } else if (strnicmp(data, "uid", 3) == 0) {
955 if (value && *value) {
957 simple_strtoul(value, &value, 0);
959 } else if (strnicmp(data, "gid", 3) == 0) {
960 if (value && *value) {
962 simple_strtoul(value, &value, 0);
964 } else if (strnicmp(data, "file_mode", 4) == 0) {
965 if (value && *value) {
967 simple_strtoul(value, &value, 0);
969 } else if (strnicmp(data, "dir_mode", 4) == 0) {
970 if (value && *value) {
972 simple_strtoul(value, &value, 0);
974 } else if (strnicmp(data, "dirmode", 4) == 0) {
975 if (value && *value) {
977 simple_strtoul(value, &value, 0);
979 } else if (strnicmp(data, "port", 4) == 0) {
980 if (value && *value) {
982 simple_strtoul(value, &value, 0);
984 } else if (strnicmp(data, "rsize", 5) == 0) {
985 if (value && *value) {
987 simple_strtoul(value, &value, 0);
989 } else if (strnicmp(data, "wsize", 5) == 0) {
990 if (value && *value) {
992 simple_strtoul(value, &value, 0);
994 } else if (strnicmp(data, "sockopt", 5) == 0) {
995 if (value && *value) {
997 simple_strtoul(value, &value, 0);
999 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1000 if (!value || !*value || (*value == ' ')) {
1001 cFYI(1,("invalid (empty) netbiosname specified"));
1003 memset(vol->source_rfc1001_name,0x20,15);
1005 /* BB are there cases in which a comma can be
1006 valid in this workstation netbios name (and need
1007 special handling)? */
1009 /* We do not uppercase netbiosname for user */
1013 vol->source_rfc1001_name[i] = value[i];
1015 /* The string has 16th byte zero still from
1016 set at top of the function */
1017 if((i==15) && (value[i] != 0))
1018 printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
1020 } else if (strnicmp(data, "servern", 7) == 0) {
1021 /* servernetbiosname specified override *SMBSERVER */
1022 if (!value || !*value || (*value == ' ')) {
1023 cFYI(1,("empty server netbiosname specified"));
1025 /* last byte, type, is 0x20 for servr type */
1026 memset(vol->target_rfc1001_name,0x20,16);
1029 /* BB are there cases in which a comma can be
1030 valid in this workstation netbios name (and need
1031 special handling)? */
1033 /* user or mount helper must uppercase netbiosname */
1037 vol->target_rfc1001_name[i] = value[i];
1039 /* The string has 16th byte zero still from
1040 set at top of the function */
1041 if((i==15) && (value[i] != 0))
1042 printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
1044 } else if (strnicmp(data, "credentials", 4) == 0) {
1046 } else if (strnicmp(data, "version", 3) == 0) {
1048 } else if (strnicmp(data, "guest",5) == 0) {
1050 } else if (strnicmp(data, "rw", 2) == 0) {
1052 } else if ((strnicmp(data, "suid", 4) == 0) ||
1053 (strnicmp(data, "nosuid", 6) == 0) ||
1054 (strnicmp(data, "exec", 4) == 0) ||
1055 (strnicmp(data, "noexec", 6) == 0) ||
1056 (strnicmp(data, "nodev", 5) == 0) ||
1057 (strnicmp(data, "noauto", 6) == 0) ||
1058 (strnicmp(data, "dev", 3) == 0)) {
1059 /* The mount tool or mount.cifs helper (if present)
1060 uses these opts to set flags, and the flags are read
1061 by the kernel vfs layer before we get here (ie
1062 before read super) so there is no point trying to
1063 parse these options again and set anything and it
1064 is ok to just ignore them */
1066 } else if (strnicmp(data, "ro", 2) == 0) {
1068 } else if (strnicmp(data, "hard", 4) == 0) {
1070 } else if (strnicmp(data, "soft", 4) == 0) {
1072 } else if (strnicmp(data, "perm", 4) == 0) {
1074 } else if (strnicmp(data, "noperm", 6) == 0) {
1076 } else if (strnicmp(data, "mapchars", 8) == 0) {
1078 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1080 } else if (strnicmp(data, "sfu", 3) == 0) {
1082 } else if (strnicmp(data, "nosfu", 5) == 0) {
1084 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1085 vol->posix_paths = 1;
1086 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1087 vol->posix_paths = 0;
1088 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1089 (strnicmp(data, "ignorecase", 10) == 0)) {
1091 } else if (strnicmp(data, "brl", 3) == 0) {
1093 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1094 (strnicmp(data, "nolock", 6) == 0)) {
1096 /* turn off mandatory locking in mode
1097 if remote locking is turned off since the
1098 local vfs will do advisory */
1099 if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1100 vol->file_mode = S_IALLUGO;
1101 } else if (strnicmp(data, "setuids", 7) == 0) {
1103 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1105 } else if (strnicmp(data, "nohard", 6) == 0) {
1107 } else if (strnicmp(data, "nosoft", 6) == 0) {
1109 } else if (strnicmp(data, "nointr", 6) == 0) {
1111 } else if (strnicmp(data, "intr", 4) == 0) {
1113 } else if (strnicmp(data, "serverino",7) == 0) {
1114 vol->server_ino = 1;
1115 } else if (strnicmp(data, "noserverino",9) == 0) {
1116 vol->server_ino = 0;
1117 } else if (strnicmp(data, "acl",3) == 0) {
1118 vol->no_psx_acl = 0;
1119 } else if (strnicmp(data, "noacl",5) == 0) {
1120 vol->no_psx_acl = 1;
1121 } else if (strnicmp(data, "direct",6) == 0) {
1123 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1125 } else if (strnicmp(data, "in6_addr",8) == 0) {
1126 if (!value || !*value) {
1127 vol->in6_addr = NULL;
1128 } else if (strnlen(value, 49) == 48) {
1129 vol->in6_addr = value;
1131 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1134 } else if (strnicmp(data, "noac", 4) == 0) {
1135 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1137 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1139 if (vol->UNC == NULL) {
1140 if(devname == NULL) {
1141 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1144 if ((temp_len = strnlen(devname, 300)) < 300) {
1145 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1146 if(vol->UNC == NULL)
1148 strcpy(vol->UNC,devname);
1149 if (strncmp(vol->UNC, "//", 2) == 0) {
1152 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1153 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1157 printk(KERN_WARNING "CIFS: UNC name too long\n");
1161 if(vol->UNCip == NULL)
1162 vol->UNCip = &vol->UNC[2];
1167 static struct cifsSesInfo *
1168 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1169 struct in6_addr *target_ip6_addr,
1170 char *userName, struct TCP_Server_Info **psrvTcp)
1172 struct list_head *tmp;
1173 struct cifsSesInfo *ses;
1175 read_lock(&GlobalSMBSeslock);
1177 list_for_each(tmp, &GlobalSMBSessionList) {
1178 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1180 if((target_ip_addr &&
1181 (ses->server->addr.sockAddr.sin_addr.s_addr
1182 == target_ip_addr->s_addr)) || (target_ip6_addr
1183 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1184 target_ip6_addr,sizeof(*target_ip6_addr)))){
1185 /* BB lock server and tcp session and increment use count here?? */
1186 *psrvTcp = ses->server; /* found a match on the TCP session */
1187 /* BB check if reconnection needed */
1189 (ses->userName, userName,
1190 MAX_USERNAME_SIZE) == 0){
1191 read_unlock(&GlobalSMBSeslock);
1192 return ses; /* found exact match on both tcp and SMB sessions */
1196 /* else tcp and smb sessions need reconnection */
1198 read_unlock(&GlobalSMBSeslock);
1202 static struct cifsTconInfo *
1203 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1205 struct list_head *tmp;
1206 struct cifsTconInfo *tcon;
1208 read_lock(&GlobalSMBSeslock);
1209 list_for_each(tmp, &GlobalTreeConnectionList) {
1210 cFYI(1, ("Next tcon - "));
1211 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1213 if (tcon->ses->server) {
1215 (" old ip addr: %x == new ip %x ?",
1216 tcon->ses->server->addr.sockAddr.sin_addr.
1217 s_addr, new_target_ip_addr));
1218 if (tcon->ses->server->addr.sockAddr.sin_addr.
1219 s_addr == new_target_ip_addr) {
1220 /* BB lock tcon and server and tcp session and increment use count here? */
1221 /* found a match on the TCP session */
1222 /* BB check if reconnection needed */
1223 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1224 tcon->treeName, uncName));
1226 (tcon->treeName, uncName,
1227 MAX_TREE_SIZE) == 0) {
1229 ("Matched UNC, old user: %s == new: %s ?",
1230 tcon->treeName, uncName));
1232 (tcon->ses->userName,
1234 MAX_USERNAME_SIZE) == 0) {
1235 read_unlock(&GlobalSMBSeslock);
1236 return tcon;/* also matched user (smb session)*/
1243 read_unlock(&GlobalSMBSeslock);
1248 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1249 const char *old_path, const struct nls_table *nls_codepage,
1252 unsigned char *referrals = NULL;
1253 unsigned int num_referrals;
1256 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1257 &num_referrals, &referrals, remap);
1259 /* BB Add in code to: if valid refrl, if not ip address contact
1260 the helper that resolves tcp names, mount to it, try to
1261 tcon to it unmount it if fail */
1270 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1271 const char *old_path, const struct nls_table *nls_codepage,
1272 unsigned int *pnum_referrals,
1273 unsigned char ** preferrals, int remap)
1278 *pnum_referrals = 0;
1280 if (pSesInfo->ipc_tid == 0) {
1281 temp_unc = kmalloc(2 /* for slashes */ +
1282 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1283 + 1 + 4 /* slash IPC$ */ + 2,
1285 if (temp_unc == NULL)
1289 strcpy(temp_unc + 2, pSesInfo->serverName);
1290 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1291 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1293 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1297 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1298 pnum_referrals, nls_codepage, remap);
1303 /* See RFC1001 section 14 on representation of Netbios names */
1304 static void rfc1002mangle(char * target,char * source, unsigned int length)
1308 for(i=0,j=0;i<(length);i++) {
1309 /* mask a nibble at a time and encode */
1310 target[j] = 'A' + (0x0F & (source[i] >> 4));
1311 target[j+1] = 'A' + (0x0F & source[i]);
1319 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1320 char * netbios_name, char * target_name)
1324 __be16 orig_port = 0;
1326 if(*csocket == NULL) {
1327 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1329 cERROR(1, ("Error %d creating socket",rc));
1333 /* BB other socket options to set KEEPALIVE, NODELAY? */
1334 cFYI(1,("Socket created"));
1335 (*csocket)->sk->sk_allocation = GFP_NOFS;
1339 psin_server->sin_family = AF_INET;
1340 if(psin_server->sin_port) { /* user overrode default port */
1341 rc = (*csocket)->ops->connect(*csocket,
1342 (struct sockaddr *) psin_server,
1343 sizeof (struct sockaddr_in),0);
1349 /* save original port so we can retry user specified port
1350 later if fall back ports fail this time */
1351 orig_port = psin_server->sin_port;
1353 /* do not retry on the same port we just failed on */
1354 if(psin_server->sin_port != htons(CIFS_PORT)) {
1355 psin_server->sin_port = htons(CIFS_PORT);
1357 rc = (*csocket)->ops->connect(*csocket,
1358 (struct sockaddr *) psin_server,
1359 sizeof (struct sockaddr_in),0);
1365 psin_server->sin_port = htons(RFC1001_PORT);
1366 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1367 psin_server, sizeof (struct sockaddr_in),0);
1372 /* give up here - unless we want to retry on different
1373 protocol families some day */
1376 psin_server->sin_port = orig_port;
1377 cFYI(1,("Error %d connecting to server via ipv4",rc));
1378 sock_release(*csocket);
1382 /* Eventually check for other socket options to change from
1383 the default. sock_setsockopt not used because it expects
1384 user space buffer */
1385 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1387 /* send RFC1001 sessinit */
1389 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1390 /* some servers require RFC1001 sessinit before sending
1391 negprot - BB check reconnection in case where second
1392 sessinit is sent but no second negprot */
1393 struct rfc1002_session_packet * ses_init_buf;
1394 struct smb_hdr * smb_buf;
1395 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1397 ses_init_buf->trailer.session_req.called_len = 32;
1398 if(target_name && (target_name[0] != 0)) {
1399 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1402 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1403 DEFAULT_CIFS_CALLED_NAME,16);
1406 ses_init_buf->trailer.session_req.calling_len = 32;
1407 /* calling name ends in null (byte 16) from old smb
1409 if(netbios_name && (netbios_name[0] !=0)) {
1410 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1413 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1414 "LINUX_CIFS_CLNT",16);
1416 ses_init_buf->trailer.session_req.scope1 = 0;
1417 ses_init_buf->trailer.session_req.scope2 = 0;
1418 smb_buf = (struct smb_hdr *)ses_init_buf;
1419 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1420 smb_buf->smb_buf_length = 0x81000044;
1421 rc = smb_send(*csocket, smb_buf, 0x44,
1422 (struct sockaddr *)psin_server);
1423 kfree(ses_init_buf);
1425 /* else the negprot may still work without this
1426 even though malloc failed */
1434 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1438 __be16 orig_port = 0;
1440 if(*csocket == NULL) {
1441 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1443 cERROR(1, ("Error %d creating ipv6 socket",rc));
1447 /* BB other socket options to set KEEPALIVE, NODELAY? */
1448 cFYI(1,("ipv6 Socket created"));
1449 (*csocket)->sk->sk_allocation = GFP_NOFS;
1453 psin_server->sin6_family = AF_INET6;
1455 if(psin_server->sin6_port) { /* user overrode default port */
1456 rc = (*csocket)->ops->connect(*csocket,
1457 (struct sockaddr *) psin_server,
1458 sizeof (struct sockaddr_in6),0);
1464 /* save original port so we can retry user specified port
1465 later if fall back ports fail this time */
1467 orig_port = psin_server->sin6_port;
1468 /* do not retry on the same port we just failed on */
1469 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1470 psin_server->sin6_port = htons(CIFS_PORT);
1472 rc = (*csocket)->ops->connect(*csocket,
1473 (struct sockaddr *) psin_server,
1474 sizeof (struct sockaddr_in6),0);
1480 psin_server->sin6_port = htons(RFC1001_PORT);
1481 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1482 psin_server, sizeof (struct sockaddr_in6),0);
1487 /* give up here - unless we want to retry on different
1488 protocol families some day */
1491 psin_server->sin6_port = orig_port;
1492 cFYI(1,("Error %d connecting to server via ipv6",rc));
1493 sock_release(*csocket);
1497 /* Eventually check for other socket options to change from
1498 the default. sock_setsockopt not used because it expects
1499 user space buffer */
1500 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1506 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1507 char *mount_data, const char *devname)
1511 int address_type = AF_INET;
1512 struct socket *csocket = NULL;
1513 struct sockaddr_in sin_server;
1514 struct sockaddr_in6 sin_server6;
1515 struct smb_vol volume_info;
1516 struct cifsSesInfo *pSesInfo = NULL;
1517 struct cifsSesInfo *existingCifsSes = NULL;
1518 struct cifsTconInfo *tcon = NULL;
1519 struct TCP_Server_Info *srvTcp = NULL;
1523 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1525 memset(&volume_info,0,sizeof(struct smb_vol));
1526 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1528 kfree(volume_info.UNC);
1529 if(volume_info.password)
1530 kfree(volume_info.password);
1535 if (volume_info.username) {
1536 /* BB fixme parse for domain name here */
1537 cFYI(1, ("Username: %s ", volume_info.username));
1540 cifserror("No username specified ");
1541 /* In userspace mount helper we can get user name from alternate
1542 locations such as env variables and files on disk */
1544 kfree(volume_info.UNC);
1545 if(volume_info.password)
1546 kfree(volume_info.password);
1551 if (volume_info.UNCip && volume_info.UNC) {
1552 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1555 /* not ipv4 address, try ipv6 */
1556 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1558 address_type = AF_INET6;
1560 address_type = AF_INET;
1564 /* we failed translating address */
1566 kfree(volume_info.UNC);
1567 if(volume_info.password)
1568 kfree(volume_info.password);
1573 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1576 } else if (volume_info.UNCip){
1577 /* BB using ip addr as server name connect to the DFS root below */
1578 cERROR(1,("Connecting to DFS root not implemented yet"));
1580 kfree(volume_info.UNC);
1581 if(volume_info.password)
1582 kfree(volume_info.password);
1585 } else /* which servers DFS root would we conect to */ {
1587 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1589 kfree(volume_info.UNC);
1590 if(volume_info.password)
1591 kfree(volume_info.password);
1596 /* this is needed for ASCII cp to Unicode converts */
1597 if(volume_info.iocharset == NULL) {
1598 cifs_sb->local_nls = load_nls_default();
1599 /* load_nls_default can not return null */
1601 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1602 if(cifs_sb->local_nls == NULL) {
1603 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1605 kfree(volume_info.UNC);
1606 if(volume_info.password)
1607 kfree(volume_info.password);
1613 if(address_type == AF_INET)
1614 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1615 NULL /* no ipv6 addr */,
1616 volume_info.username, &srvTcp);
1617 else if(address_type == AF_INET6)
1618 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1619 &sin_server6.sin6_addr,
1620 volume_info.username, &srvTcp);
1623 kfree(volume_info.UNC);
1624 if(volume_info.password)
1625 kfree(volume_info.password);
1632 cFYI(1, ("Existing tcp session with server found "));
1633 } else { /* create socket */
1634 if(volume_info.port)
1635 sin_server.sin_port = htons(volume_info.port);
1637 sin_server.sin_port = 0;
1638 rc = ipv4_connect(&sin_server,&csocket,
1639 volume_info.source_rfc1001_name,
1640 volume_info.target_rfc1001_name);
1643 ("Error connecting to IPv4 socket. Aborting operation"));
1645 sock_release(csocket);
1647 kfree(volume_info.UNC);
1648 if(volume_info.password)
1649 kfree(volume_info.password);
1654 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1655 if (srvTcp == NULL) {
1657 sock_release(csocket);
1659 kfree(volume_info.UNC);
1660 if(volume_info.password)
1661 kfree(volume_info.password);
1665 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1666 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1667 atomic_set(&srvTcp->inFlight,0);
1668 /* BB Add code for ipv6 case too */
1669 srvTcp->ssocket = csocket;
1670 srvTcp->protocolType = IPV4;
1671 init_waitqueue_head(&srvTcp->response_q);
1672 init_waitqueue_head(&srvTcp->request_q);
1673 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1674 /* at this point we are the only ones with the pointer
1675 to the struct since the kernel thread not created yet
1676 so no need to spinlock this init of tcpStatus */
1677 srvTcp->tcpStatus = CifsNew;
1678 init_MUTEX(&srvTcp->tcpSem);
1679 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1680 CLONE_FS | CLONE_FILES | CLONE_VM);
1683 sock_release(csocket);
1685 kfree(volume_info.UNC);
1686 if(volume_info.password)
1687 kfree(volume_info.password);
1691 wait_for_completion(&cifsd_complete);
1693 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1694 memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
1695 srvTcp->sequence_number = 0;
1699 if (existingCifsSes) {
1700 pSesInfo = existingCifsSes;
1701 cFYI(1, ("Existing smb sess found "));
1702 if(volume_info.password)
1703 kfree(volume_info.password);
1704 /* volume_info.UNC freed at end of function */
1706 cFYI(1, ("Existing smb sess not found "));
1707 pSesInfo = sesInfoAlloc();
1708 if (pSesInfo == NULL)
1711 pSesInfo->server = srvTcp;
1712 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1713 NIPQUAD(sin_server.sin_addr.s_addr));
1717 /* volume_info.password freed at unmount */
1718 if (volume_info.password)
1719 pSesInfo->password = volume_info.password;
1720 if (volume_info.username)
1721 strncpy(pSesInfo->userName,
1722 volume_info.username,MAX_USERNAME_SIZE);
1723 if (volume_info.domainname)
1724 strncpy(pSesInfo->domainName,
1725 volume_info.domainname,MAX_USERNAME_SIZE);
1726 pSesInfo->linux_uid = volume_info.linux_uid;
1727 down(&pSesInfo->sesSem);
1728 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1729 up(&pSesInfo->sesSem);
1731 atomic_inc(&srvTcp->socketUseCount);
1733 if(volume_info.password)
1734 kfree(volume_info.password);
1737 /* search for existing tcon to this server share */
1739 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1740 cifs_sb->rsize = volume_info.rsize;
1742 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1743 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1744 cifs_sb->wsize = volume_info.wsize;
1746 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1747 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1748 cifs_sb->rsize = PAGE_CACHE_SIZE;
1749 /* Windows ME does this */
1750 cFYI(1,("Attempt to set readsize for mount to less than one page (4096)"));
1752 cifs_sb->mnt_uid = volume_info.linux_uid;
1753 cifs_sb->mnt_gid = volume_info.linux_gid;
1754 cifs_sb->mnt_file_mode = volume_info.file_mode;
1755 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1756 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1758 if(volume_info.noperm)
1759 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1760 if(volume_info.setuids)
1761 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1762 if(volume_info.server_ino)
1763 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1764 if(volume_info.remap)
1765 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1766 if(volume_info.no_xattr)
1767 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1768 if(volume_info.sfu_emul)
1769 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1770 if(volume_info.nobrl)
1771 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1773 if(volume_info.direct_io) {
1774 cFYI(1,("mounting share using direct i/o"));
1775 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1779 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1780 volume_info.username);
1782 cFYI(1, ("Found match on UNC path "));
1783 /* we can have only one retry value for a connection
1784 to a share so for resources mounted more than once
1785 to the same server share the last value passed in
1786 for the retry flag is used */
1787 tcon->retry = volume_info.retry;
1788 tcon->nocase = volume_info.nocase;
1790 tcon = tconInfoAlloc();
1794 /* check for null share name ie connect to dfs root */
1796 /* BB check if this works for exactly length three strings */
1797 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1798 && (strchr(volume_info.UNC + 3, '/') ==
1800 rc = connect_to_dfs_path(xid, pSesInfo,
1801 "", cifs_sb->local_nls,
1802 cifs_sb->mnt_cifs_flags &
1803 CIFS_MOUNT_MAP_SPECIAL_CHR);
1805 kfree(volume_info.UNC);
1809 rc = CIFSTCon(xid, pSesInfo,
1811 tcon, cifs_sb->local_nls);
1812 cFYI(1, ("CIFS Tcon rc = %d", rc));
1815 atomic_inc(&pSesInfo->inUse);
1816 tcon->retry = volume_info.retry;
1817 tcon->nocase = volume_info.nocase;
1823 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1824 sb->s_maxbytes = (u64) 1 << 63;
1826 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1829 sb->s_time_gran = 100;
1831 /* on error free sesinfo and tcon struct if needed */
1833 /* if session setup failed, use count is zero but
1834 we still need to free cifsd thread */
1835 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1836 spin_lock(&GlobalMid_Lock);
1837 srvTcp->tcpStatus = CifsExiting;
1838 spin_unlock(&GlobalMid_Lock);
1840 send_sig(SIGKILL,srvTcp->tsk,1);
1841 wait_for_completion(&cifsd_complete);
1844 /* If find_unc succeeded then rc == 0 so we can not end */
1845 if (tcon) /* up accidently freeing someone elses tcon struct */
1847 if (existingCifsSes == NULL) {
1849 if ((pSesInfo->server) &&
1850 (pSesInfo->status == CifsGood)) {
1852 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1853 /* if the socketUseCount is now zero */
1854 if((temp_rc == -ESHUTDOWN) &&
1855 (pSesInfo->server->tsk)) {
1856 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1857 wait_for_completion(&cifsd_complete);
1860 cFYI(1, ("No session or bad tcon"));
1861 sesInfoFree(pSesInfo);
1862 /* pSesInfo = NULL; */
1866 atomic_inc(&tcon->useCount);
1867 cifs_sb->tcon = tcon;
1868 tcon->ses = pSesInfo;
1870 /* do not care if following two calls succeed - informational only */
1871 CIFSSMBQFSDeviceInfo(xid, tcon);
1872 CIFSSMBQFSAttributeInfo(xid, tcon);
1873 if (tcon->ses->capabilities & CAP_UNIX) {
1874 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1875 if(!volume_info.no_psx_acl) {
1876 if(CIFS_UNIX_POSIX_ACL_CAP &
1877 le64_to_cpu(tcon->fsUnixInfo.Capability))
1878 cFYI(1,("server negotiated posix acl support"));
1879 sb->s_flags |= MS_POSIXACL;
1882 /* Try and negotiate POSIX pathnames if we can. */
1883 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
1884 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1885 if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
1886 cFYI(1,("negotiated posix pathnames support"));
1887 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
1889 cFYI(1,("posix pathnames support requested but not supported"));
1894 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
1895 cifs_sb->wsize = min(cifs_sb->wsize,
1896 (tcon->ses->server->maxBuf -
1897 MAX_CIFS_HDR_SIZE));
1900 /* volume_info.password is freed above when existing session found
1901 (in which case it is not needed anymore) but when new sesion is created
1902 the password ptr is put in the new session structure (in which case the
1903 password will be freed at unmount time) */
1905 kfree(volume_info.UNC);
1911 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1912 char session_key[CIFS_SESSION_KEY_SIZE],
1913 const struct nls_table *nls_codepage)
1915 struct smb_hdr *smb_buffer;
1916 struct smb_hdr *smb_buffer_response;
1917 SESSION_SETUP_ANDX *pSMB;
1918 SESSION_SETUP_ANDX *pSMBr;
1923 int remaining_words = 0;
1924 int bytes_returned = 0;
1929 cFYI(1, ("In sesssetup "));
1932 user = ses->userName;
1933 domain = ses->domainName;
1934 smb_buffer = cifs_buf_get();
1935 if (smb_buffer == NULL) {
1938 smb_buffer_response = smb_buffer;
1939 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1941 /* send SMBsessionSetup here */
1942 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1943 NULL /* no tCon exists yet */ , 13 /* wct */ );
1945 smb_buffer->Mid = GetNextMid(ses->server);
1946 pSMB->req_no_secext.AndXCommand = 0xFF;
1947 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1948 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1950 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1951 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1953 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1954 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1955 if (ses->capabilities & CAP_UNICODE) {
1956 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1957 capabilities |= CAP_UNICODE;
1959 if (ses->capabilities & CAP_STATUS32) {
1960 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1961 capabilities |= CAP_STATUS32;
1963 if (ses->capabilities & CAP_DFS) {
1964 smb_buffer->Flags2 |= SMBFLG2_DFS;
1965 capabilities |= CAP_DFS;
1967 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1969 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1970 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1972 pSMB->req_no_secext.CaseSensitivePasswordLength =
1973 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1974 bcc_ptr = pByteArea(smb_buffer);
1975 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1976 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1977 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1978 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1980 if (ses->capabilities & CAP_UNICODE) {
1981 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1986 bytes_returned = 0; /* skill null user */
1989 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1991 /* convert number of 16 bit words to bytes */
1992 bcc_ptr += 2 * bytes_returned;
1993 bcc_ptr += 2; /* trailing null */
1996 cifs_strtoUCS((wchar_t *) bcc_ptr,
1997 "CIFS_LINUX_DOM", 32, nls_codepage);
2000 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2002 bcc_ptr += 2 * bytes_returned;
2005 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2007 bcc_ptr += 2 * bytes_returned;
2009 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
2011 bcc_ptr += 2 * bytes_returned;
2014 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2016 bcc_ptr += 2 * bytes_returned;
2020 strncpy(bcc_ptr, user, 200);
2021 bcc_ptr += strnlen(user, 200);
2025 if (domain == NULL) {
2026 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2027 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2029 strncpy(bcc_ptr, domain, 64);
2030 bcc_ptr += strnlen(domain, 64);
2034 strcpy(bcc_ptr, "Linux version ");
2035 bcc_ptr += strlen("Linux version ");
2036 strcpy(bcc_ptr, system_utsname.release);
2037 bcc_ptr += strlen(system_utsname.release) + 1;
2038 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2039 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2041 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2042 smb_buffer->smb_buf_length += count;
2043 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2045 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2046 &bytes_returned, 1);
2048 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2049 } else if ((smb_buffer_response->WordCount == 3)
2050 || (smb_buffer_response->WordCount == 4)) {
2051 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2052 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2053 if (action & GUEST_LOGIN)
2054 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
2055 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2056 cFYI(1, ("UID = %d ", ses->Suid));
2057 /* response can have either 3 or 4 word count - Samba sends 3 */
2058 bcc_ptr = pByteArea(smb_buffer_response);
2059 if ((pSMBr->resp.hdr.WordCount == 3)
2060 || ((pSMBr->resp.hdr.WordCount == 4)
2061 && (blob_len < pSMBr->resp.ByteCount))) {
2062 if (pSMBr->resp.hdr.WordCount == 4)
2063 bcc_ptr += blob_len;
2065 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2066 if ((long) (bcc_ptr) % 2) {
2068 (BCC(smb_buffer_response) - 1) /2;
2069 bcc_ptr++; /* Unicode strings must be word aligned */
2072 BCC(smb_buffer_response) / 2;
2075 UniStrnlen((wchar_t *) bcc_ptr,
2076 remaining_words - 1);
2077 /* We look for obvious messed up bcc or strings in response so we do not go off
2078 the end since (at least) WIN2K and Windows XP have a major bug in not null
2079 terminating last Unicode string in response */
2080 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2081 if(ses->serverOS == NULL)
2082 goto sesssetup_nomem;
2083 cifs_strfromUCS_le(ses->serverOS,
2084 (wchar_t *)bcc_ptr, len,nls_codepage);
2085 bcc_ptr += 2 * (len + 1);
2086 remaining_words -= len + 1;
2087 ses->serverOS[2 * len] = 0;
2088 ses->serverOS[1 + (2 * len)] = 0;
2089 if (remaining_words > 0) {
2090 len = UniStrnlen((wchar_t *)bcc_ptr,
2092 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
2093 if(ses->serverNOS == NULL)
2094 goto sesssetup_nomem;
2095 cifs_strfromUCS_le(ses->serverNOS,
2096 (wchar_t *)bcc_ptr,len,nls_codepage);
2097 bcc_ptr += 2 * (len + 1);
2098 ses->serverNOS[2 * len] = 0;
2099 ses->serverNOS[1 + (2 * len)] = 0;
2100 if(strncmp(ses->serverNOS,
2101 "NT LAN Manager 4",16) == 0) {
2102 cFYI(1,("NT4 server"));
2103 ses->flags |= CIFS_SES_NT4;
2105 remaining_words -= len + 1;
2106 if (remaining_words > 0) {
2107 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2108 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2110 kcalloc(1, 2*(len+1),GFP_KERNEL);
2111 if(ses->serverDomain == NULL)
2112 goto sesssetup_nomem;
2113 cifs_strfromUCS_le(ses->serverDomain,
2114 (wchar_t *)bcc_ptr,len,nls_codepage);
2115 bcc_ptr += 2 * (len + 1);
2116 ses->serverDomain[2*len] = 0;
2117 ses->serverDomain[1+(2*len)] = 0;
2118 } /* else no more room so create dummy domain string */
2121 kcalloc(1, 2, GFP_KERNEL);
2122 } else { /* no room so create dummy domain and NOS string */
2123 /* if these kcallocs fail not much we
2124 can do, but better to not fail the
2127 kcalloc(1, 2, GFP_KERNEL);
2129 kcalloc(1, 2, GFP_KERNEL);
2131 } else { /* ASCII */
2132 len = strnlen(bcc_ptr, 1024);
2133 if (((long) bcc_ptr + len) - (long)
2134 pByteArea(smb_buffer_response)
2135 <= BCC(smb_buffer_response)) {
2136 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2137 if(ses->serverOS == NULL)
2138 goto sesssetup_nomem;
2139 strncpy(ses->serverOS,bcc_ptr, len);
2142 bcc_ptr[0] = 0; /* null terminate the string */
2145 len = strnlen(bcc_ptr, 1024);
2146 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2147 if(ses->serverNOS == NULL)
2148 goto sesssetup_nomem;
2149 strncpy(ses->serverNOS, bcc_ptr, len);
2154 len = strnlen(bcc_ptr, 1024);
2155 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2156 if(ses->serverDomain == NULL)
2157 goto sesssetup_nomem;
2158 strncpy(ses->serverDomain, bcc_ptr, len);
2164 ("Variable field of length %d extends beyond end of smb ",
2169 (" Security Blob Length extends beyond end of SMB"));
2173 (" Invalid Word count %d: ",
2174 smb_buffer_response->WordCount));
2177 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2178 since that could make reconnection harder, and
2179 reconnection might be needed to free memory */
2181 cifs_buf_release(smb_buffer);
2187 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2188 char *SecurityBlob,int SecurityBlobLength,
2189 const struct nls_table *nls_codepage)
2191 struct smb_hdr *smb_buffer;
2192 struct smb_hdr *smb_buffer_response;
2193 SESSION_SETUP_ANDX *pSMB;
2194 SESSION_SETUP_ANDX *pSMBr;
2199 int remaining_words = 0;
2200 int bytes_returned = 0;
2205 cFYI(1, ("In spnego sesssetup "));
2208 user = ses->userName;
2209 domain = ses->domainName;
2211 smb_buffer = cifs_buf_get();
2212 if (smb_buffer == NULL) {
2215 smb_buffer_response = smb_buffer;
2216 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2218 /* send SMBsessionSetup here */
2219 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2220 NULL /* no tCon exists yet */ , 12 /* wct */ );
2222 smb_buffer->Mid = GetNextMid(ses->server);
2223 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2224 pSMB->req.AndXCommand = 0xFF;
2225 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2226 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2228 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2229 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2231 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2232 CAP_EXTENDED_SECURITY;
2233 if (ses->capabilities & CAP_UNICODE) {
2234 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2235 capabilities |= CAP_UNICODE;
2237 if (ses->capabilities & CAP_STATUS32) {
2238 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2239 capabilities |= CAP_STATUS32;
2241 if (ses->capabilities & CAP_DFS) {
2242 smb_buffer->Flags2 |= SMBFLG2_DFS;
2243 capabilities |= CAP_DFS;
2245 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2247 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2248 bcc_ptr = pByteArea(smb_buffer);
2249 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2250 bcc_ptr += SecurityBlobLength;
2252 if (ses->capabilities & CAP_UNICODE) {
2253 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2258 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
2259 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2260 bcc_ptr += 2; /* trailing null */
2263 cifs_strtoUCS((wchar_t *) bcc_ptr,
2264 "CIFS_LINUX_DOM", 32, nls_codepage);
2267 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2269 bcc_ptr += 2 * bytes_returned;
2272 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2274 bcc_ptr += 2 * bytes_returned;
2276 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2278 bcc_ptr += 2 * bytes_returned;
2281 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2283 bcc_ptr += 2 * bytes_returned;
2286 strncpy(bcc_ptr, user, 200);
2287 bcc_ptr += strnlen(user, 200);
2290 if (domain == NULL) {
2291 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2292 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2294 strncpy(bcc_ptr, domain, 64);
2295 bcc_ptr += strnlen(domain, 64);
2299 strcpy(bcc_ptr, "Linux version ");
2300 bcc_ptr += strlen("Linux version ");
2301 strcpy(bcc_ptr, system_utsname.release);
2302 bcc_ptr += strlen(system_utsname.release) + 1;
2303 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2304 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2306 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2307 smb_buffer->smb_buf_length += count;
2308 pSMB->req.ByteCount = cpu_to_le16(count);
2310 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2311 &bytes_returned, 1);
2313 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2314 } else if ((smb_buffer_response->WordCount == 3)
2315 || (smb_buffer_response->WordCount == 4)) {
2316 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2318 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2319 if (action & GUEST_LOGIN)
2320 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2322 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2323 cFYI(1, ("UID = %d ", ses->Suid));
2324 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2326 /* BB Fix below to make endian neutral !! */
2328 if ((pSMBr->resp.hdr.WordCount == 3)
2329 || ((pSMBr->resp.hdr.WordCount == 4)
2331 pSMBr->resp.ByteCount))) {
2332 if (pSMBr->resp.hdr.WordCount == 4) {
2336 ("Security Blob Length %d ",
2340 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2341 if ((long) (bcc_ptr) % 2) {
2343 (BCC(smb_buffer_response)
2345 bcc_ptr++; /* Unicode strings must be word aligned */
2349 (smb_buffer_response) / 2;
2352 UniStrnlen((wchar_t *) bcc_ptr,
2353 remaining_words - 1);
2354 /* We look for obvious messed up bcc or strings in response so we do not go off
2355 the end since (at least) WIN2K and Windows XP have a major bug in not null
2356 terminating last Unicode string in response */
2358 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2359 cifs_strfromUCS_le(ses->serverOS,
2363 bcc_ptr += 2 * (len + 1);
2364 remaining_words -= len + 1;
2365 ses->serverOS[2 * len] = 0;
2366 ses->serverOS[1 + (2 * len)] = 0;
2367 if (remaining_words > 0) {
2368 len = UniStrnlen((wchar_t *)bcc_ptr,
2372 kcalloc(1, 2 * (len + 1),
2374 cifs_strfromUCS_le(ses->serverNOS,
2378 bcc_ptr += 2 * (len + 1);
2379 ses->serverNOS[2 * len] = 0;
2380 ses->serverNOS[1 + (2 * len)] = 0;
2381 remaining_words -= len + 1;
2382 if (remaining_words > 0) {
2383 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2384 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2385 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2386 cifs_strfromUCS_le(ses->serverDomain,
2390 bcc_ptr += 2*(len+1);
2391 ses->serverDomain[2*len] = 0;
2392 ses->serverDomain[1+(2*len)] = 0;
2393 } /* else no more room so create dummy domain string */
2396 kcalloc(1, 2,GFP_KERNEL);
2397 } else { /* no room so create dummy domain and NOS string */
2398 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2399 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2401 } else { /* ASCII */
2403 len = strnlen(bcc_ptr, 1024);
2404 if (((long) bcc_ptr + len) - (long)
2405 pByteArea(smb_buffer_response)
2406 <= BCC(smb_buffer_response)) {
2407 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2408 strncpy(ses->serverOS, bcc_ptr, len);
2411 bcc_ptr[0] = 0; /* null terminate the string */
2414 len = strnlen(bcc_ptr, 1024);
2415 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2416 strncpy(ses->serverNOS, bcc_ptr, len);
2421 len = strnlen(bcc_ptr, 1024);
2422 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2423 strncpy(ses->serverDomain, bcc_ptr, len);
2429 ("Variable field of length %d extends beyond end of smb ",
2434 (" Security Blob Length extends beyond end of SMB"));
2437 cERROR(1, ("No session structure passed in."));
2441 (" Invalid Word count %d: ",
2442 smb_buffer_response->WordCount));
2447 cifs_buf_release(smb_buffer);
2453 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2454 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2455 const struct nls_table *nls_codepage)
2457 struct smb_hdr *smb_buffer;
2458 struct smb_hdr *smb_buffer_response;
2459 SESSION_SETUP_ANDX *pSMB;
2460 SESSION_SETUP_ANDX *pSMBr;
2464 int remaining_words = 0;
2465 int bytes_returned = 0;
2467 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2468 PNEGOTIATE_MESSAGE SecurityBlob;
2469 PCHALLENGE_MESSAGE SecurityBlob2;
2470 __u32 negotiate_flags, capabilities;
2473 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2476 domain = ses->domainName;
2477 *pNTLMv2_flag = FALSE;
2478 smb_buffer = cifs_buf_get();
2479 if (smb_buffer == NULL) {
2482 smb_buffer_response = smb_buffer;
2483 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2484 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2486 /* send SMBsessionSetup here */
2487 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2488 NULL /* no tCon exists yet */ , 12 /* wct */ );
2490 smb_buffer->Mid = GetNextMid(ses->server);
2491 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2492 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2494 pSMB->req.AndXCommand = 0xFF;
2495 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2496 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2498 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2499 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2501 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2502 CAP_EXTENDED_SECURITY;
2503 if (ses->capabilities & CAP_UNICODE) {
2504 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2505 capabilities |= CAP_UNICODE;
2507 if (ses->capabilities & CAP_STATUS32) {
2508 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2509 capabilities |= CAP_STATUS32;
2511 if (ses->capabilities & CAP_DFS) {
2512 smb_buffer->Flags2 |= SMBFLG2_DFS;
2513 capabilities |= CAP_DFS;
2515 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2517 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2518 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2519 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2520 SecurityBlob->MessageType = NtLmNegotiate;
2522 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2523 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2524 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2526 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2528 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2529 /* setup pointers to domain name and workstation name */
2530 bcc_ptr += SecurityBlobLength;
2532 SecurityBlob->WorkstationName.Buffer = 0;
2533 SecurityBlob->WorkstationName.Length = 0;
2534 SecurityBlob->WorkstationName.MaximumLength = 0;
2536 if (domain == NULL) {
2537 SecurityBlob->DomainName.Buffer = 0;
2538 SecurityBlob->DomainName.Length = 0;
2539 SecurityBlob->DomainName.MaximumLength = 0;
2542 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2543 strncpy(bcc_ptr, domain, 63);
2544 len = strnlen(domain, 64);
2545 SecurityBlob->DomainName.MaximumLength =
2547 SecurityBlob->DomainName.Buffer =
2548 cpu_to_le32((long) &SecurityBlob->
2550 (long) &SecurityBlob->Signature);
2552 SecurityBlobLength += len;
2553 SecurityBlob->DomainName.Length =
2556 if (ses->capabilities & CAP_UNICODE) {
2557 if ((long) bcc_ptr % 2) {
2563 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2565 bcc_ptr += 2 * bytes_returned;
2567 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2569 bcc_ptr += 2 * bytes_returned;
2570 bcc_ptr += 2; /* null terminate Linux version */
2572 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2574 bcc_ptr += 2 * bytes_returned;
2577 bcc_ptr += 2; /* null terminate network opsys string */
2580 bcc_ptr += 2; /* null domain */
2581 } else { /* ASCII */
2582 strcpy(bcc_ptr, "Linux version ");
2583 bcc_ptr += strlen("Linux version ");
2584 strcpy(bcc_ptr, system_utsname.release);
2585 bcc_ptr += strlen(system_utsname.release) + 1;
2586 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2587 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2588 bcc_ptr++; /* empty domain field */
2591 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2592 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2593 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2594 smb_buffer->smb_buf_length += count;
2595 pSMB->req.ByteCount = cpu_to_le16(count);
2597 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2598 &bytes_returned, 1);
2600 if (smb_buffer_response->Status.CifsError ==
2601 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2605 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2606 } else if ((smb_buffer_response->WordCount == 3)
2607 || (smb_buffer_response->WordCount == 4)) {
2608 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2609 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2611 if (action & GUEST_LOGIN)
2612 cFYI(1, (" Guest login"));
2613 /* Do we want to set anything in SesInfo struct when guest login? */
2615 bcc_ptr = pByteArea(smb_buffer_response);
2616 /* response can have either 3 or 4 word count - Samba sends 3 */
2618 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2619 if (SecurityBlob2->MessageType != NtLmChallenge) {
2621 ("Unexpected NTLMSSP message type received %d",
2622 SecurityBlob2->MessageType));
2624 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2625 cFYI(1, ("UID = %d ", ses->Suid));
2626 if ((pSMBr->resp.hdr.WordCount == 3)
2627 || ((pSMBr->resp.hdr.WordCount == 4)
2629 pSMBr->resp.ByteCount))) {
2631 if (pSMBr->resp.hdr.WordCount == 4) {
2632 bcc_ptr += blob_len;
2634 ("Security Blob Length %d ",
2638 cFYI(1, ("NTLMSSP Challenge rcvd "));
2640 memcpy(ses->server->cryptKey,
2641 SecurityBlob2->Challenge,
2642 CIFS_CRYPTO_KEY_SIZE);
2643 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2644 *pNTLMv2_flag = TRUE;
2646 if((SecurityBlob2->NegotiateFlags &
2647 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2648 || (sign_CIFS_PDUs > 1))
2649 ses->server->secMode |=
2650 SECMODE_SIGN_REQUIRED;
2651 if ((SecurityBlob2->NegotiateFlags &
2652 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2653 ses->server->secMode |=
2654 SECMODE_SIGN_ENABLED;
2656 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2657 if ((long) (bcc_ptr) % 2) {
2659 (BCC(smb_buffer_response)
2661 bcc_ptr++; /* Unicode strings must be word aligned */
2665 (smb_buffer_response) / 2;
2668 UniStrnlen((wchar_t *) bcc_ptr,
2669 remaining_words - 1);
2670 /* We look for obvious messed up bcc or strings in response so we do not go off
2671 the end since (at least) WIN2K and Windows XP have a major bug in not null
2672 terminating last Unicode string in response */
2674 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2675 cifs_strfromUCS_le(ses->serverOS,
2679 bcc_ptr += 2 * (len + 1);
2680 remaining_words -= len + 1;
2681 ses->serverOS[2 * len] = 0;
2682 ses->serverOS[1 + (2 * len)] = 0;
2683 if (remaining_words > 0) {
2684 len = UniStrnlen((wchar_t *)
2689 kcalloc(1, 2 * (len + 1),
2691 cifs_strfromUCS_le(ses->
2697 bcc_ptr += 2 * (len + 1);
2698 ses->serverNOS[2 * len] = 0;
2701 remaining_words -= len + 1;
2702 if (remaining_words > 0) {
2703 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2704 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2729 } /* else no more room so create dummy domain string */
2734 } else { /* no room so create dummy domain and NOS string */
2736 kcalloc(1, 2, GFP_KERNEL);
2738 kcalloc(1, 2, GFP_KERNEL);
2740 } else { /* ASCII */
2741 len = strnlen(bcc_ptr, 1024);
2742 if (((long) bcc_ptr + len) - (long)
2743 pByteArea(smb_buffer_response)
2744 <= BCC(smb_buffer_response)) {
2748 strncpy(ses->serverOS,
2752 bcc_ptr[0] = 0; /* null terminate string */
2755 len = strnlen(bcc_ptr, 1024);
2759 strncpy(ses->serverNOS, bcc_ptr, len);
2764 len = strnlen(bcc_ptr, 1024);
2768 strncpy(ses->serverDomain, bcc_ptr, len);
2774 ("Variable field of length %d extends beyond end of smb ",
2779 (" Security Blob Length extends beyond end of SMB"));
2782 cERROR(1, ("No session structure passed in."));
2786 (" Invalid Word count %d: ",
2787 smb_buffer_response->WordCount));
2792 cifs_buf_release(smb_buffer);
2797 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2798 char *ntlm_session_key, int ntlmv2_flag,
2799 const struct nls_table *nls_codepage)
2801 struct smb_hdr *smb_buffer;
2802 struct smb_hdr *smb_buffer_response;
2803 SESSION_SETUP_ANDX *pSMB;
2804 SESSION_SETUP_ANDX *pSMBr;
2809 int remaining_words = 0;
2810 int bytes_returned = 0;
2812 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2813 PAUTHENTICATE_MESSAGE SecurityBlob;
2814 __u32 negotiate_flags, capabilities;
2817 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2820 user = ses->userName;
2821 domain = ses->domainName;
2822 smb_buffer = cifs_buf_get();
2823 if (smb_buffer == NULL) {
2826 smb_buffer_response = smb_buffer;
2827 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2828 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2830 /* send SMBsessionSetup here */
2831 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2832 NULL /* no tCon exists yet */ , 12 /* wct */ );
2834 smb_buffer->Mid = GetNextMid(ses->server);
2835 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2836 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2837 pSMB->req.AndXCommand = 0xFF;
2838 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2839 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2841 pSMB->req.hdr.Uid = ses->Suid;
2843 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2844 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2846 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2847 CAP_EXTENDED_SECURITY;
2848 if (ses->capabilities & CAP_UNICODE) {
2849 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2850 capabilities |= CAP_UNICODE;
2852 if (ses->capabilities & CAP_STATUS32) {
2853 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2854 capabilities |= CAP_STATUS32;
2856 if (ses->capabilities & CAP_DFS) {
2857 smb_buffer->Flags2 |= SMBFLG2_DFS;
2858 capabilities |= CAP_DFS;
2860 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2862 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2863 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2864 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2865 SecurityBlob->MessageType = NtLmAuthenticate;
2866 bcc_ptr += SecurityBlobLength;
2868 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2869 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2870 0x80000000 | NTLMSSP_NEGOTIATE_128;
2872 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2874 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2876 /* setup pointers to domain name and workstation name */
2878 SecurityBlob->WorkstationName.Buffer = 0;
2879 SecurityBlob->WorkstationName.Length = 0;
2880 SecurityBlob->WorkstationName.MaximumLength = 0;
2881 SecurityBlob->SessionKey.Length = 0;
2882 SecurityBlob->SessionKey.MaximumLength = 0;
2883 SecurityBlob->SessionKey.Buffer = 0;
2885 SecurityBlob->LmChallengeResponse.Length = 0;
2886 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2887 SecurityBlob->LmChallengeResponse.Buffer = 0;
2889 SecurityBlob->NtChallengeResponse.Length =
2890 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2891 SecurityBlob->NtChallengeResponse.MaximumLength =
2892 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2893 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2894 SecurityBlob->NtChallengeResponse.Buffer =
2895 cpu_to_le32(SecurityBlobLength);
2896 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2897 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2899 if (ses->capabilities & CAP_UNICODE) {
2900 if (domain == NULL) {
2901 SecurityBlob->DomainName.Buffer = 0;
2902 SecurityBlob->DomainName.Length = 0;
2903 SecurityBlob->DomainName.MaximumLength = 0;
2906 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2909 SecurityBlob->DomainName.MaximumLength =
2911 SecurityBlob->DomainName.Buffer =
2912 cpu_to_le32(SecurityBlobLength);
2914 SecurityBlobLength += len;
2915 SecurityBlob->DomainName.Length =
2919 SecurityBlob->UserName.Buffer = 0;
2920 SecurityBlob->UserName.Length = 0;
2921 SecurityBlob->UserName.MaximumLength = 0;
2924 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2927 SecurityBlob->UserName.MaximumLength =
2929 SecurityBlob->UserName.Buffer =
2930 cpu_to_le32(SecurityBlobLength);
2932 SecurityBlobLength += len;
2933 SecurityBlob->UserName.Length =
2937 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2938 SecurityBlob->WorkstationName.Length *= 2;
2939 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2940 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2941 bcc_ptr += SecurityBlob->WorkstationName.Length;
2942 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2943 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2945 if ((long) bcc_ptr % 2) {
2950 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2952 bcc_ptr += 2 * bytes_returned;
2954 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2956 bcc_ptr += 2 * bytes_returned;
2957 bcc_ptr += 2; /* null term version string */
2959 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2961 bcc_ptr += 2 * bytes_returned;
2964 bcc_ptr += 2; /* null terminate network opsys string */
2967 bcc_ptr += 2; /* null domain */
2968 } else { /* ASCII */
2969 if (domain == NULL) {
2970 SecurityBlob->DomainName.Buffer = 0;
2971 SecurityBlob->DomainName.Length = 0;
2972 SecurityBlob->DomainName.MaximumLength = 0;
2975 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2976 strncpy(bcc_ptr, domain, 63);
2977 len = strnlen(domain, 64);
2978 SecurityBlob->DomainName.MaximumLength =
2980 SecurityBlob->DomainName.Buffer =
2981 cpu_to_le32(SecurityBlobLength);
2983 SecurityBlobLength += len;
2984 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2987 SecurityBlob->UserName.Buffer = 0;
2988 SecurityBlob->UserName.Length = 0;
2989 SecurityBlob->UserName.MaximumLength = 0;
2992 strncpy(bcc_ptr, user, 63);
2993 len = strnlen(user, 64);
2994 SecurityBlob->UserName.MaximumLength =
2996 SecurityBlob->UserName.Buffer =
2997 cpu_to_le32(SecurityBlobLength);
2999 SecurityBlobLength += len;
3000 SecurityBlob->UserName.Length = cpu_to_le16(len);
3002 /* BB fill in our workstation name if known BB */
3004 strcpy(bcc_ptr, "Linux version ");
3005 bcc_ptr += strlen("Linux version ");
3006 strcpy(bcc_ptr, system_utsname.release);
3007 bcc_ptr += strlen(system_utsname.release) + 1;
3008 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3009 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3010 bcc_ptr++; /* null domain */
3013 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3014 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3015 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3016 smb_buffer->smb_buf_length += count;
3017 pSMB->req.ByteCount = cpu_to_le16(count);
3019 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3020 &bytes_returned, 1);
3022 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
3023 } else if ((smb_buffer_response->WordCount == 3)
3024 || (smb_buffer_response->WordCount == 4)) {
3025 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3027 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3028 if (action & GUEST_LOGIN)
3029 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
3030 /* if(SecurityBlob2->MessageType != NtLm??){
3031 cFYI("Unexpected message type on auth response is %d "));
3035 ("Does UID on challenge %d match auth response UID %d ",
3036 ses->Suid, smb_buffer_response->Uid));
3037 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
3038 bcc_ptr = pByteArea(smb_buffer_response);
3039 /* response can have either 3 or 4 word count - Samba sends 3 */
3040 if ((pSMBr->resp.hdr.WordCount == 3)
3041 || ((pSMBr->resp.hdr.WordCount == 4)
3043 pSMBr->resp.ByteCount))) {
3044 if (pSMBr->resp.hdr.WordCount == 4) {
3048 ("Security Blob Length %d ",
3053 ("NTLMSSP response to Authenticate "));
3055 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3056 if ((long) (bcc_ptr) % 2) {
3058 (BCC(smb_buffer_response)
3060 bcc_ptr++; /* Unicode strings must be word aligned */
3062 remaining_words = BCC(smb_buffer_response) / 2;
3065 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
3066 /* We look for obvious messed up bcc or strings in response so we do not go off
3067 the end since (at least) WIN2K and Windows XP have a major bug in not null
3068 terminating last Unicode string in response */
3070 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
3071 cifs_strfromUCS_le(ses->serverOS,
3075 bcc_ptr += 2 * (len + 1);
3076 remaining_words -= len + 1;
3077 ses->serverOS[2 * len] = 0;
3078 ses->serverOS[1 + (2 * len)] = 0;
3079 if (remaining_words > 0) {
3080 len = UniStrnlen((wchar_t *)
3085 kcalloc(1, 2 * (len + 1),
3087 cifs_strfromUCS_le(ses->
3093 bcc_ptr += 2 * (len + 1);
3094 ses->serverNOS[2 * len] = 0;
3095 ses->serverNOS[1+(2*len)] = 0;
3096 remaining_words -= len + 1;
3097 if (remaining_words > 0) {
3098 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3099 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3124 } /* else no more room so create dummy domain string */
3126 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
3127 } else { /* no room so create dummy domain and NOS string */
3128 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
3129 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
3131 } else { /* ASCII */
3132 len = strnlen(bcc_ptr, 1024);
3133 if (((long) bcc_ptr + len) -
3134 (long) pByteArea(smb_buffer_response)
3135 <= BCC(smb_buffer_response)) {
3136 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
3137 strncpy(ses->serverOS,bcc_ptr, len);
3140 bcc_ptr[0] = 0; /* null terminate the string */
3143 len = strnlen(bcc_ptr, 1024);
3144 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
3145 strncpy(ses->serverNOS, bcc_ptr, len);
3150 len = strnlen(bcc_ptr, 1024);
3151 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
3152 strncpy(ses->serverDomain, bcc_ptr, len);
3158 ("Variable field of length %d extends beyond end of smb ",
3163 (" Security Blob Length extends beyond end of SMB"));
3166 cERROR(1, ("No session structure passed in."));
3170 (" Invalid Word count %d: ",
3171 smb_buffer_response->WordCount));
3176 cifs_buf_release(smb_buffer);
3182 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3183 const char *tree, struct cifsTconInfo *tcon,
3184 const struct nls_table *nls_codepage)
3186 struct smb_hdr *smb_buffer;
3187 struct smb_hdr *smb_buffer_response;
3190 unsigned char *bcc_ptr;
3198 smb_buffer = cifs_buf_get();
3199 if (smb_buffer == NULL) {
3202 smb_buffer_response = smb_buffer;
3204 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3205 NULL /*no tid */ , 4 /*wct */ );
3207 smb_buffer->Mid = GetNextMid(ses->server);
3208 smb_buffer->Uid = ses->Suid;
3209 pSMB = (TCONX_REQ *) smb_buffer;
3210 pSMBr = (TCONX_RSP *) smb_buffer_response;
3212 pSMB->AndXCommand = 0xFF;
3213 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3214 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3215 bcc_ptr = &pSMB->Password[0];
3216 bcc_ptr++; /* skip password */
3218 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3219 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3221 if (ses->capabilities & CAP_STATUS32) {
3222 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3224 if (ses->capabilities & CAP_DFS) {
3225 smb_buffer->Flags2 |= SMBFLG2_DFS;
3227 if (ses->capabilities & CAP_UNICODE) {
3228 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3230 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
3231 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3232 bcc_ptr += 2; /* skip trailing null */
3233 } else { /* ASCII */
3235 strcpy(bcc_ptr, tree);
3236 bcc_ptr += strlen(tree) + 1;
3238 strcpy(bcc_ptr, "?????");
3239 bcc_ptr += strlen("?????");
3241 count = bcc_ptr - &pSMB->Password[0];
3242 pSMB->hdr.smb_buf_length += count;
3243 pSMB->ByteCount = cpu_to_le16(count);
3245 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3247 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3248 /* above now done in SendReceive */
3249 if ((rc == 0) && (tcon != NULL)) {
3250 tcon->tidStatus = CifsGood;
3251 tcon->tid = smb_buffer_response->Tid;
3252 bcc_ptr = pByteArea(smb_buffer_response);
3253 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3254 /* skip service field (NB: this field is always ASCII) */
3255 bcc_ptr += length + 1;
3256 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3257 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3258 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3259 if ((bcc_ptr + (2 * length)) -
3260 pByteArea(smb_buffer_response) <=
3261 BCC(smb_buffer_response)) {
3262 if(tcon->nativeFileSystem)
3263 kfree(tcon->nativeFileSystem);
3264 tcon->nativeFileSystem =
3265 kcalloc(1, length + 2, GFP_KERNEL);
3266 cifs_strfromUCS_le(tcon->nativeFileSystem,
3267 (wchar_t *) bcc_ptr,
3268 length, nls_codepage);
3269 bcc_ptr += 2 * length;
3270 bcc_ptr[0] = 0; /* null terminate the string */
3274 /* else do not bother copying these informational fields */
3276 length = strnlen(bcc_ptr, 1024);
3277 if ((bcc_ptr + length) -
3278 pByteArea(smb_buffer_response) <=
3279 BCC(smb_buffer_response)) {
3280 if(tcon->nativeFileSystem)
3281 kfree(tcon->nativeFileSystem);
3282 tcon->nativeFileSystem =
3283 kcalloc(1, length + 1, GFP_KERNEL);
3284 strncpy(tcon->nativeFileSystem, bcc_ptr,
3287 /* else do not bother copying these informational fields */
3289 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3290 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3291 } else if ((rc == 0) && tcon == NULL) {
3292 /* all we need to save for IPC$ connection */
3293 ses->ipc_tid = smb_buffer_response->Tid;
3297 cifs_buf_release(smb_buffer);
3302 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3306 struct cifsSesInfo *ses = NULL;
3307 struct task_struct *cifsd_task;
3311 if (cifs_sb->tcon) {
3312 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3313 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3318 tconInfoFree(cifs_sb->tcon);
3319 if ((ses) && (ses->server)) {
3320 /* save off task so we do not refer to ses later */
3321 cifsd_task = ses->server->tsk;
3322 cFYI(1, ("About to do SMBLogoff "));
3323 rc = CIFSSMBLogoff(xid, ses);
3327 } else if (rc == -ESHUTDOWN) {
3328 cFYI(1,("Waking up socket by sending it signal"));
3330 send_sig(SIGKILL,cifsd_task,1);
3331 wait_for_completion(&cifsd_complete);
3334 } /* else - we have an smb session
3335 left on this socket do not kill cifsd */
3337 cFYI(1, ("No session or bad tcon"));
3340 cifs_sb->tcon = NULL;
3342 set_current_state(TASK_INTERRUPTIBLE);
3343 schedule_timeout(HZ / 2);
3349 return rc; /* BB check if we should always return zero here */
3352 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3353 struct nls_table * nls_info)
3356 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3357 int ntlmv2_flag = FALSE;
3360 /* what if server changes its buffer size after dropping the session? */
3361 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3362 rc = CIFSSMBNegotiate(xid, pSesInfo);
3363 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3364 rc = CIFSSMBNegotiate(xid, pSesInfo);
3369 spin_lock(&GlobalMid_Lock);
3370 if(pSesInfo->server->tcpStatus != CifsExiting)
3371 pSesInfo->server->tcpStatus = CifsGood;
3374 spin_unlock(&GlobalMid_Lock);
3380 pSesInfo->capabilities = pSesInfo->server->capabilities;
3381 if(linuxExtEnabled == 0)
3382 pSesInfo->capabilities &= (~CAP_UNIX);
3383 /* pSesInfo->sequence_number = 0;*/
3384 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3385 pSesInfo->server->secMode,
3386 pSesInfo->server->capabilities,
3387 pSesInfo->server->timeZone));
3388 if (extended_security
3389 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3390 && (pSesInfo->server->secType == NTLMSSP)) {
3391 cFYI(1, ("New style sesssetup "));
3392 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3393 NULL /* security blob */,
3394 0 /* blob length */,
3396 } else if (extended_security
3397 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3398 && (pSesInfo->server->secType == RawNTLMSSP)) {
3399 cFYI(1, ("NTLMSSP sesssetup "));
3400 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3407 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3408 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3413 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3415 CalcNTLMv2_response(pSesInfo,v2_response);
3417 cifs_calculate_ntlmv2_mac_key(
3418 pSesInfo->server->mac_signing_key,
3419 response, ntlm_session_key, */
3421 /* BB Put dummy sig in SessSetup PDU? */
3428 SMBNTencrypt(pSesInfo->password,
3429 pSesInfo->server->cryptKey,
3433 cifs_calculate_mac_key(
3434 pSesInfo->server->mac_signing_key,
3436 pSesInfo->password);
3438 /* for better security the weaker lanman hash not sent
3439 in AuthSessSetup so we no longer calculate it */
3441 rc = CIFSNTLMSSPAuthSessSetup(xid,
3447 } else { /* old style NTLM 0.12 session setup */
3448 SMBNTencrypt(pSesInfo->password,
3449 pSesInfo->server->cryptKey,
3453 cifs_calculate_mac_key(
3454 pSesInfo->server->mac_signing_key,
3455 ntlm_session_key, pSesInfo->password);
3457 rc = CIFSSessSetup(xid, pSesInfo,
3458 ntlm_session_key, nls_info);
3461 cERROR(1,("Send error in SessSetup = %d",rc));
3463 cFYI(1,("CIFS Session Established successfully"));
3464 pSesInfo->status = CifsGood;