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"));
1896 /* volume_info.password is freed above when existing session found
1897 (in which case it is not needed anymore) but when new sesion is created
1898 the password ptr is put in the new session structure (in which case the
1899 password will be freed at unmount time) */
1901 kfree(volume_info.UNC);
1907 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1908 char session_key[CIFS_SESSION_KEY_SIZE],
1909 const struct nls_table *nls_codepage)
1911 struct smb_hdr *smb_buffer;
1912 struct smb_hdr *smb_buffer_response;
1913 SESSION_SETUP_ANDX *pSMB;
1914 SESSION_SETUP_ANDX *pSMBr;
1919 int remaining_words = 0;
1920 int bytes_returned = 0;
1925 cFYI(1, ("In sesssetup "));
1928 user = ses->userName;
1929 domain = ses->domainName;
1930 smb_buffer = cifs_buf_get();
1931 if (smb_buffer == NULL) {
1934 smb_buffer_response = smb_buffer;
1935 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1937 /* send SMBsessionSetup here */
1938 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1939 NULL /* no tCon exists yet */ , 13 /* wct */ );
1941 smb_buffer->Mid = GetNextMid(ses->server);
1942 pSMB->req_no_secext.AndXCommand = 0xFF;
1943 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1944 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1946 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1947 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1949 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1950 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1951 if (ses->capabilities & CAP_UNICODE) {
1952 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1953 capabilities |= CAP_UNICODE;
1955 if (ses->capabilities & CAP_STATUS32) {
1956 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1957 capabilities |= CAP_STATUS32;
1959 if (ses->capabilities & CAP_DFS) {
1960 smb_buffer->Flags2 |= SMBFLG2_DFS;
1961 capabilities |= CAP_DFS;
1963 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1965 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1966 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1968 pSMB->req_no_secext.CaseSensitivePasswordLength =
1969 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1970 bcc_ptr = pByteArea(smb_buffer);
1971 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1972 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1973 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1974 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1976 if (ses->capabilities & CAP_UNICODE) {
1977 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1982 bytes_returned = 0; /* skill null user */
1985 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1987 /* convert number of 16 bit words to bytes */
1988 bcc_ptr += 2 * bytes_returned;
1989 bcc_ptr += 2; /* trailing null */
1992 cifs_strtoUCS((wchar_t *) bcc_ptr,
1993 "CIFS_LINUX_DOM", 32, nls_codepage);
1996 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1998 bcc_ptr += 2 * bytes_returned;
2001 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2003 bcc_ptr += 2 * bytes_returned;
2005 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
2007 bcc_ptr += 2 * bytes_returned;
2010 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2012 bcc_ptr += 2 * bytes_returned;
2016 strncpy(bcc_ptr, user, 200);
2017 bcc_ptr += strnlen(user, 200);
2021 if (domain == NULL) {
2022 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2023 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2025 strncpy(bcc_ptr, domain, 64);
2026 bcc_ptr += strnlen(domain, 64);
2030 strcpy(bcc_ptr, "Linux version ");
2031 bcc_ptr += strlen("Linux version ");
2032 strcpy(bcc_ptr, system_utsname.release);
2033 bcc_ptr += strlen(system_utsname.release) + 1;
2034 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2035 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2037 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2038 smb_buffer->smb_buf_length += count;
2039 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2041 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2042 &bytes_returned, 1);
2044 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2045 } else if ((smb_buffer_response->WordCount == 3)
2046 || (smb_buffer_response->WordCount == 4)) {
2047 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2048 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2049 if (action & GUEST_LOGIN)
2050 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
2051 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2052 cFYI(1, ("UID = %d ", ses->Suid));
2053 /* response can have either 3 or 4 word count - Samba sends 3 */
2054 bcc_ptr = pByteArea(smb_buffer_response);
2055 if ((pSMBr->resp.hdr.WordCount == 3)
2056 || ((pSMBr->resp.hdr.WordCount == 4)
2057 && (blob_len < pSMBr->resp.ByteCount))) {
2058 if (pSMBr->resp.hdr.WordCount == 4)
2059 bcc_ptr += blob_len;
2061 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2062 if ((long) (bcc_ptr) % 2) {
2064 (BCC(smb_buffer_response) - 1) /2;
2065 bcc_ptr++; /* Unicode strings must be word aligned */
2068 BCC(smb_buffer_response) / 2;
2071 UniStrnlen((wchar_t *) bcc_ptr,
2072 remaining_words - 1);
2073 /* We look for obvious messed up bcc or strings in response so we do not go off
2074 the end since (at least) WIN2K and Windows XP have a major bug in not null
2075 terminating last Unicode string in response */
2076 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2077 if(ses->serverOS == NULL)
2078 goto sesssetup_nomem;
2079 cifs_strfromUCS_le(ses->serverOS,
2080 (wchar_t *)bcc_ptr, len,nls_codepage);
2081 bcc_ptr += 2 * (len + 1);
2082 remaining_words -= len + 1;
2083 ses->serverOS[2 * len] = 0;
2084 ses->serverOS[1 + (2 * len)] = 0;
2085 if (remaining_words > 0) {
2086 len = UniStrnlen((wchar_t *)bcc_ptr,
2088 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
2089 if(ses->serverNOS == NULL)
2090 goto sesssetup_nomem;
2091 cifs_strfromUCS_le(ses->serverNOS,
2092 (wchar_t *)bcc_ptr,len,nls_codepage);
2093 bcc_ptr += 2 * (len + 1);
2094 ses->serverNOS[2 * len] = 0;
2095 ses->serverNOS[1 + (2 * len)] = 0;
2096 if(strncmp(ses->serverNOS,
2097 "NT LAN Manager 4",16) == 0) {
2098 cFYI(1,("NT4 server"));
2099 ses->flags |= CIFS_SES_NT4;
2101 remaining_words -= len + 1;
2102 if (remaining_words > 0) {
2103 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2104 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2106 kcalloc(1, 2*(len+1),GFP_KERNEL);
2107 if(ses->serverDomain == NULL)
2108 goto sesssetup_nomem;
2109 cifs_strfromUCS_le(ses->serverDomain,
2110 (wchar_t *)bcc_ptr,len,nls_codepage);
2111 bcc_ptr += 2 * (len + 1);
2112 ses->serverDomain[2*len] = 0;
2113 ses->serverDomain[1+(2*len)] = 0;
2114 } /* else no more room so create dummy domain string */
2117 kcalloc(1, 2, GFP_KERNEL);
2118 } else { /* no room so create dummy domain and NOS string */
2119 /* if these kcallocs fail not much we
2120 can do, but better to not fail the
2123 kcalloc(1, 2, GFP_KERNEL);
2125 kcalloc(1, 2, GFP_KERNEL);
2127 } else { /* ASCII */
2128 len = strnlen(bcc_ptr, 1024);
2129 if (((long) bcc_ptr + len) - (long)
2130 pByteArea(smb_buffer_response)
2131 <= BCC(smb_buffer_response)) {
2132 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2133 if(ses->serverOS == NULL)
2134 goto sesssetup_nomem;
2135 strncpy(ses->serverOS,bcc_ptr, len);
2138 bcc_ptr[0] = 0; /* null terminate the string */
2141 len = strnlen(bcc_ptr, 1024);
2142 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2143 if(ses->serverNOS == NULL)
2144 goto sesssetup_nomem;
2145 strncpy(ses->serverNOS, bcc_ptr, len);
2150 len = strnlen(bcc_ptr, 1024);
2151 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2152 if(ses->serverDomain == NULL)
2153 goto sesssetup_nomem;
2154 strncpy(ses->serverDomain, bcc_ptr, len);
2160 ("Variable field of length %d extends beyond end of smb ",
2165 (" Security Blob Length extends beyond end of SMB"));
2169 (" Invalid Word count %d: ",
2170 smb_buffer_response->WordCount));
2173 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2174 since that could make reconnection harder, and
2175 reconnection might be needed to free memory */
2177 cifs_buf_release(smb_buffer);
2183 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2184 char *SecurityBlob,int SecurityBlobLength,
2185 const struct nls_table *nls_codepage)
2187 struct smb_hdr *smb_buffer;
2188 struct smb_hdr *smb_buffer_response;
2189 SESSION_SETUP_ANDX *pSMB;
2190 SESSION_SETUP_ANDX *pSMBr;
2195 int remaining_words = 0;
2196 int bytes_returned = 0;
2201 cFYI(1, ("In spnego sesssetup "));
2204 user = ses->userName;
2205 domain = ses->domainName;
2207 smb_buffer = cifs_buf_get();
2208 if (smb_buffer == NULL) {
2211 smb_buffer_response = smb_buffer;
2212 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2214 /* send SMBsessionSetup here */
2215 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2216 NULL /* no tCon exists yet */ , 12 /* wct */ );
2218 smb_buffer->Mid = GetNextMid(ses->server);
2219 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2220 pSMB->req.AndXCommand = 0xFF;
2221 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2222 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2224 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2225 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2227 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2228 CAP_EXTENDED_SECURITY;
2229 if (ses->capabilities & CAP_UNICODE) {
2230 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2231 capabilities |= CAP_UNICODE;
2233 if (ses->capabilities & CAP_STATUS32) {
2234 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2235 capabilities |= CAP_STATUS32;
2237 if (ses->capabilities & CAP_DFS) {
2238 smb_buffer->Flags2 |= SMBFLG2_DFS;
2239 capabilities |= CAP_DFS;
2241 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2243 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2244 bcc_ptr = pByteArea(smb_buffer);
2245 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2246 bcc_ptr += SecurityBlobLength;
2248 if (ses->capabilities & CAP_UNICODE) {
2249 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2254 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
2255 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2256 bcc_ptr += 2; /* trailing null */
2259 cifs_strtoUCS((wchar_t *) bcc_ptr,
2260 "CIFS_LINUX_DOM", 32, nls_codepage);
2263 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2265 bcc_ptr += 2 * bytes_returned;
2268 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2270 bcc_ptr += 2 * bytes_returned;
2272 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2274 bcc_ptr += 2 * bytes_returned;
2277 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2279 bcc_ptr += 2 * bytes_returned;
2282 strncpy(bcc_ptr, user, 200);
2283 bcc_ptr += strnlen(user, 200);
2286 if (domain == NULL) {
2287 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2288 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2290 strncpy(bcc_ptr, domain, 64);
2291 bcc_ptr += strnlen(domain, 64);
2295 strcpy(bcc_ptr, "Linux version ");
2296 bcc_ptr += strlen("Linux version ");
2297 strcpy(bcc_ptr, system_utsname.release);
2298 bcc_ptr += strlen(system_utsname.release) + 1;
2299 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2300 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2302 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2303 smb_buffer->smb_buf_length += count;
2304 pSMB->req.ByteCount = cpu_to_le16(count);
2306 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2307 &bytes_returned, 1);
2309 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2310 } else if ((smb_buffer_response->WordCount == 3)
2311 || (smb_buffer_response->WordCount == 4)) {
2312 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2314 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2315 if (action & GUEST_LOGIN)
2316 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2318 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2319 cFYI(1, ("UID = %d ", ses->Suid));
2320 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2322 /* BB Fix below to make endian neutral !! */
2324 if ((pSMBr->resp.hdr.WordCount == 3)
2325 || ((pSMBr->resp.hdr.WordCount == 4)
2327 pSMBr->resp.ByteCount))) {
2328 if (pSMBr->resp.hdr.WordCount == 4) {
2332 ("Security Blob Length %d ",
2336 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2337 if ((long) (bcc_ptr) % 2) {
2339 (BCC(smb_buffer_response)
2341 bcc_ptr++; /* Unicode strings must be word aligned */
2345 (smb_buffer_response) / 2;
2348 UniStrnlen((wchar_t *) bcc_ptr,
2349 remaining_words - 1);
2350 /* We look for obvious messed up bcc or strings in response so we do not go off
2351 the end since (at least) WIN2K and Windows XP have a major bug in not null
2352 terminating last Unicode string in response */
2354 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2355 cifs_strfromUCS_le(ses->serverOS,
2359 bcc_ptr += 2 * (len + 1);
2360 remaining_words -= len + 1;
2361 ses->serverOS[2 * len] = 0;
2362 ses->serverOS[1 + (2 * len)] = 0;
2363 if (remaining_words > 0) {
2364 len = UniStrnlen((wchar_t *)bcc_ptr,
2368 kcalloc(1, 2 * (len + 1),
2370 cifs_strfromUCS_le(ses->serverNOS,
2374 bcc_ptr += 2 * (len + 1);
2375 ses->serverNOS[2 * len] = 0;
2376 ses->serverNOS[1 + (2 * len)] = 0;
2377 remaining_words -= len + 1;
2378 if (remaining_words > 0) {
2379 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2380 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2381 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2382 cifs_strfromUCS_le(ses->serverDomain,
2386 bcc_ptr += 2*(len+1);
2387 ses->serverDomain[2*len] = 0;
2388 ses->serverDomain[1+(2*len)] = 0;
2389 } /* else no more room so create dummy domain string */
2392 kcalloc(1, 2,GFP_KERNEL);
2393 } else { /* no room so create dummy domain and NOS string */
2394 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2395 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2397 } else { /* ASCII */
2399 len = strnlen(bcc_ptr, 1024);
2400 if (((long) bcc_ptr + len) - (long)
2401 pByteArea(smb_buffer_response)
2402 <= BCC(smb_buffer_response)) {
2403 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2404 strncpy(ses->serverOS, bcc_ptr, len);
2407 bcc_ptr[0] = 0; /* null terminate the string */
2410 len = strnlen(bcc_ptr, 1024);
2411 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2412 strncpy(ses->serverNOS, bcc_ptr, len);
2417 len = strnlen(bcc_ptr, 1024);
2418 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2419 strncpy(ses->serverDomain, bcc_ptr, len);
2425 ("Variable field of length %d extends beyond end of smb ",
2430 (" Security Blob Length extends beyond end of SMB"));
2433 cERROR(1, ("No session structure passed in."));
2437 (" Invalid Word count %d: ",
2438 smb_buffer_response->WordCount));
2443 cifs_buf_release(smb_buffer);
2449 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2450 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2451 const struct nls_table *nls_codepage)
2453 struct smb_hdr *smb_buffer;
2454 struct smb_hdr *smb_buffer_response;
2455 SESSION_SETUP_ANDX *pSMB;
2456 SESSION_SETUP_ANDX *pSMBr;
2460 int remaining_words = 0;
2461 int bytes_returned = 0;
2463 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2464 PNEGOTIATE_MESSAGE SecurityBlob;
2465 PCHALLENGE_MESSAGE SecurityBlob2;
2466 __u32 negotiate_flags, capabilities;
2469 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2472 domain = ses->domainName;
2473 *pNTLMv2_flag = FALSE;
2474 smb_buffer = cifs_buf_get();
2475 if (smb_buffer == NULL) {
2478 smb_buffer_response = smb_buffer;
2479 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2480 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2482 /* send SMBsessionSetup here */
2483 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2484 NULL /* no tCon exists yet */ , 12 /* wct */ );
2486 smb_buffer->Mid = GetNextMid(ses->server);
2487 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2488 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2490 pSMB->req.AndXCommand = 0xFF;
2491 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2492 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2494 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2495 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2497 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2498 CAP_EXTENDED_SECURITY;
2499 if (ses->capabilities & CAP_UNICODE) {
2500 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2501 capabilities |= CAP_UNICODE;
2503 if (ses->capabilities & CAP_STATUS32) {
2504 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2505 capabilities |= CAP_STATUS32;
2507 if (ses->capabilities & CAP_DFS) {
2508 smb_buffer->Flags2 |= SMBFLG2_DFS;
2509 capabilities |= CAP_DFS;
2511 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2513 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2514 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2515 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2516 SecurityBlob->MessageType = NtLmNegotiate;
2518 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2519 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2520 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2522 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2524 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2525 /* setup pointers to domain name and workstation name */
2526 bcc_ptr += SecurityBlobLength;
2528 SecurityBlob->WorkstationName.Buffer = 0;
2529 SecurityBlob->WorkstationName.Length = 0;
2530 SecurityBlob->WorkstationName.MaximumLength = 0;
2532 if (domain == NULL) {
2533 SecurityBlob->DomainName.Buffer = 0;
2534 SecurityBlob->DomainName.Length = 0;
2535 SecurityBlob->DomainName.MaximumLength = 0;
2538 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2539 strncpy(bcc_ptr, domain, 63);
2540 len = strnlen(domain, 64);
2541 SecurityBlob->DomainName.MaximumLength =
2543 SecurityBlob->DomainName.Buffer =
2544 cpu_to_le32((long) &SecurityBlob->
2546 (long) &SecurityBlob->Signature);
2548 SecurityBlobLength += len;
2549 SecurityBlob->DomainName.Length =
2552 if (ses->capabilities & CAP_UNICODE) {
2553 if ((long) bcc_ptr % 2) {
2559 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2561 bcc_ptr += 2 * bytes_returned;
2563 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2565 bcc_ptr += 2 * bytes_returned;
2566 bcc_ptr += 2; /* null terminate Linux version */
2568 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2570 bcc_ptr += 2 * bytes_returned;
2573 bcc_ptr += 2; /* null terminate network opsys string */
2576 bcc_ptr += 2; /* null domain */
2577 } else { /* ASCII */
2578 strcpy(bcc_ptr, "Linux version ");
2579 bcc_ptr += strlen("Linux version ");
2580 strcpy(bcc_ptr, system_utsname.release);
2581 bcc_ptr += strlen(system_utsname.release) + 1;
2582 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2583 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2584 bcc_ptr++; /* empty domain field */
2587 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2588 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2589 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2590 smb_buffer->smb_buf_length += count;
2591 pSMB->req.ByteCount = cpu_to_le16(count);
2593 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2594 &bytes_returned, 1);
2596 if (smb_buffer_response->Status.CifsError ==
2597 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2601 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2602 } else if ((smb_buffer_response->WordCount == 3)
2603 || (smb_buffer_response->WordCount == 4)) {
2604 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2605 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2607 if (action & GUEST_LOGIN)
2608 cFYI(1, (" Guest login"));
2609 /* Do we want to set anything in SesInfo struct when guest login? */
2611 bcc_ptr = pByteArea(smb_buffer_response);
2612 /* response can have either 3 or 4 word count - Samba sends 3 */
2614 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2615 if (SecurityBlob2->MessageType != NtLmChallenge) {
2617 ("Unexpected NTLMSSP message type received %d",
2618 SecurityBlob2->MessageType));
2620 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2621 cFYI(1, ("UID = %d ", ses->Suid));
2622 if ((pSMBr->resp.hdr.WordCount == 3)
2623 || ((pSMBr->resp.hdr.WordCount == 4)
2625 pSMBr->resp.ByteCount))) {
2627 if (pSMBr->resp.hdr.WordCount == 4) {
2628 bcc_ptr += blob_len;
2630 ("Security Blob Length %d ",
2634 cFYI(1, ("NTLMSSP Challenge rcvd "));
2636 memcpy(ses->server->cryptKey,
2637 SecurityBlob2->Challenge,
2638 CIFS_CRYPTO_KEY_SIZE);
2639 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2640 *pNTLMv2_flag = TRUE;
2642 if((SecurityBlob2->NegotiateFlags &
2643 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2644 || (sign_CIFS_PDUs > 1))
2645 ses->server->secMode |=
2646 SECMODE_SIGN_REQUIRED;
2647 if ((SecurityBlob2->NegotiateFlags &
2648 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2649 ses->server->secMode |=
2650 SECMODE_SIGN_ENABLED;
2652 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2653 if ((long) (bcc_ptr) % 2) {
2655 (BCC(smb_buffer_response)
2657 bcc_ptr++; /* Unicode strings must be word aligned */
2661 (smb_buffer_response) / 2;
2664 UniStrnlen((wchar_t *) bcc_ptr,
2665 remaining_words - 1);
2666 /* We look for obvious messed up bcc or strings in response so we do not go off
2667 the end since (at least) WIN2K and Windows XP have a major bug in not null
2668 terminating last Unicode string in response */
2670 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2671 cifs_strfromUCS_le(ses->serverOS,
2675 bcc_ptr += 2 * (len + 1);
2676 remaining_words -= len + 1;
2677 ses->serverOS[2 * len] = 0;
2678 ses->serverOS[1 + (2 * len)] = 0;
2679 if (remaining_words > 0) {
2680 len = UniStrnlen((wchar_t *)
2685 kcalloc(1, 2 * (len + 1),
2687 cifs_strfromUCS_le(ses->
2693 bcc_ptr += 2 * (len + 1);
2694 ses->serverNOS[2 * len] = 0;
2697 remaining_words -= len + 1;
2698 if (remaining_words > 0) {
2699 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2700 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2725 } /* else no more room so create dummy domain string */
2730 } else { /* no room so create dummy domain and NOS string */
2732 kcalloc(1, 2, GFP_KERNEL);
2734 kcalloc(1, 2, GFP_KERNEL);
2736 } else { /* ASCII */
2737 len = strnlen(bcc_ptr, 1024);
2738 if (((long) bcc_ptr + len) - (long)
2739 pByteArea(smb_buffer_response)
2740 <= BCC(smb_buffer_response)) {
2744 strncpy(ses->serverOS,
2748 bcc_ptr[0] = 0; /* null terminate string */
2751 len = strnlen(bcc_ptr, 1024);
2755 strncpy(ses->serverNOS, bcc_ptr, len);
2760 len = strnlen(bcc_ptr, 1024);
2764 strncpy(ses->serverDomain, bcc_ptr, len);
2770 ("Variable field of length %d extends beyond end of smb ",
2775 (" Security Blob Length extends beyond end of SMB"));
2778 cERROR(1, ("No session structure passed in."));
2782 (" Invalid Word count %d: ",
2783 smb_buffer_response->WordCount));
2788 cifs_buf_release(smb_buffer);
2793 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2794 char *ntlm_session_key, int ntlmv2_flag,
2795 const struct nls_table *nls_codepage)
2797 struct smb_hdr *smb_buffer;
2798 struct smb_hdr *smb_buffer_response;
2799 SESSION_SETUP_ANDX *pSMB;
2800 SESSION_SETUP_ANDX *pSMBr;
2805 int remaining_words = 0;
2806 int bytes_returned = 0;
2808 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2809 PAUTHENTICATE_MESSAGE SecurityBlob;
2810 __u32 negotiate_flags, capabilities;
2813 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2816 user = ses->userName;
2817 domain = ses->domainName;
2818 smb_buffer = cifs_buf_get();
2819 if (smb_buffer == NULL) {
2822 smb_buffer_response = smb_buffer;
2823 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2824 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2826 /* send SMBsessionSetup here */
2827 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2828 NULL /* no tCon exists yet */ , 12 /* wct */ );
2830 smb_buffer->Mid = GetNextMid(ses->server);
2831 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2832 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2833 pSMB->req.AndXCommand = 0xFF;
2834 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2835 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2837 pSMB->req.hdr.Uid = ses->Suid;
2839 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2840 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2842 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2843 CAP_EXTENDED_SECURITY;
2844 if (ses->capabilities & CAP_UNICODE) {
2845 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2846 capabilities |= CAP_UNICODE;
2848 if (ses->capabilities & CAP_STATUS32) {
2849 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2850 capabilities |= CAP_STATUS32;
2852 if (ses->capabilities & CAP_DFS) {
2853 smb_buffer->Flags2 |= SMBFLG2_DFS;
2854 capabilities |= CAP_DFS;
2856 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2858 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2859 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2860 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2861 SecurityBlob->MessageType = NtLmAuthenticate;
2862 bcc_ptr += SecurityBlobLength;
2864 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2865 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2866 0x80000000 | NTLMSSP_NEGOTIATE_128;
2868 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2870 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2872 /* setup pointers to domain name and workstation name */
2874 SecurityBlob->WorkstationName.Buffer = 0;
2875 SecurityBlob->WorkstationName.Length = 0;
2876 SecurityBlob->WorkstationName.MaximumLength = 0;
2877 SecurityBlob->SessionKey.Length = 0;
2878 SecurityBlob->SessionKey.MaximumLength = 0;
2879 SecurityBlob->SessionKey.Buffer = 0;
2881 SecurityBlob->LmChallengeResponse.Length = 0;
2882 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2883 SecurityBlob->LmChallengeResponse.Buffer = 0;
2885 SecurityBlob->NtChallengeResponse.Length =
2886 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2887 SecurityBlob->NtChallengeResponse.MaximumLength =
2888 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2889 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2890 SecurityBlob->NtChallengeResponse.Buffer =
2891 cpu_to_le32(SecurityBlobLength);
2892 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2893 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2895 if (ses->capabilities & CAP_UNICODE) {
2896 if (domain == NULL) {
2897 SecurityBlob->DomainName.Buffer = 0;
2898 SecurityBlob->DomainName.Length = 0;
2899 SecurityBlob->DomainName.MaximumLength = 0;
2902 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2905 SecurityBlob->DomainName.MaximumLength =
2907 SecurityBlob->DomainName.Buffer =
2908 cpu_to_le32(SecurityBlobLength);
2910 SecurityBlobLength += len;
2911 SecurityBlob->DomainName.Length =
2915 SecurityBlob->UserName.Buffer = 0;
2916 SecurityBlob->UserName.Length = 0;
2917 SecurityBlob->UserName.MaximumLength = 0;
2920 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2923 SecurityBlob->UserName.MaximumLength =
2925 SecurityBlob->UserName.Buffer =
2926 cpu_to_le32(SecurityBlobLength);
2928 SecurityBlobLength += len;
2929 SecurityBlob->UserName.Length =
2933 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2934 SecurityBlob->WorkstationName.Length *= 2;
2935 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2936 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2937 bcc_ptr += SecurityBlob->WorkstationName.Length;
2938 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2939 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2941 if ((long) bcc_ptr % 2) {
2946 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2948 bcc_ptr += 2 * bytes_returned;
2950 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2952 bcc_ptr += 2 * bytes_returned;
2953 bcc_ptr += 2; /* null term version string */
2955 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2957 bcc_ptr += 2 * bytes_returned;
2960 bcc_ptr += 2; /* null terminate network opsys string */
2963 bcc_ptr += 2; /* null domain */
2964 } else { /* ASCII */
2965 if (domain == NULL) {
2966 SecurityBlob->DomainName.Buffer = 0;
2967 SecurityBlob->DomainName.Length = 0;
2968 SecurityBlob->DomainName.MaximumLength = 0;
2971 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2972 strncpy(bcc_ptr, domain, 63);
2973 len = strnlen(domain, 64);
2974 SecurityBlob->DomainName.MaximumLength =
2976 SecurityBlob->DomainName.Buffer =
2977 cpu_to_le32(SecurityBlobLength);
2979 SecurityBlobLength += len;
2980 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2983 SecurityBlob->UserName.Buffer = 0;
2984 SecurityBlob->UserName.Length = 0;
2985 SecurityBlob->UserName.MaximumLength = 0;
2988 strncpy(bcc_ptr, user, 63);
2989 len = strnlen(user, 64);
2990 SecurityBlob->UserName.MaximumLength =
2992 SecurityBlob->UserName.Buffer =
2993 cpu_to_le32(SecurityBlobLength);
2995 SecurityBlobLength += len;
2996 SecurityBlob->UserName.Length = cpu_to_le16(len);
2998 /* BB fill in our workstation name if known BB */
3000 strcpy(bcc_ptr, "Linux version ");
3001 bcc_ptr += strlen("Linux version ");
3002 strcpy(bcc_ptr, system_utsname.release);
3003 bcc_ptr += strlen(system_utsname.release) + 1;
3004 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3005 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3006 bcc_ptr++; /* null domain */
3009 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3010 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3011 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3012 smb_buffer->smb_buf_length += count;
3013 pSMB->req.ByteCount = cpu_to_le16(count);
3015 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3016 &bytes_returned, 1);
3018 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
3019 } else if ((smb_buffer_response->WordCount == 3)
3020 || (smb_buffer_response->WordCount == 4)) {
3021 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3023 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3024 if (action & GUEST_LOGIN)
3025 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
3026 /* if(SecurityBlob2->MessageType != NtLm??){
3027 cFYI("Unexpected message type on auth response is %d "));
3031 ("Does UID on challenge %d match auth response UID %d ",
3032 ses->Suid, smb_buffer_response->Uid));
3033 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
3034 bcc_ptr = pByteArea(smb_buffer_response);
3035 /* response can have either 3 or 4 word count - Samba sends 3 */
3036 if ((pSMBr->resp.hdr.WordCount == 3)
3037 || ((pSMBr->resp.hdr.WordCount == 4)
3039 pSMBr->resp.ByteCount))) {
3040 if (pSMBr->resp.hdr.WordCount == 4) {
3044 ("Security Blob Length %d ",
3049 ("NTLMSSP response to Authenticate "));
3051 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3052 if ((long) (bcc_ptr) % 2) {
3054 (BCC(smb_buffer_response)
3056 bcc_ptr++; /* Unicode strings must be word aligned */
3058 remaining_words = BCC(smb_buffer_response) / 2;
3061 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
3062 /* We look for obvious messed up bcc or strings in response so we do not go off
3063 the end since (at least) WIN2K and Windows XP have a major bug in not null
3064 terminating last Unicode string in response */
3066 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
3067 cifs_strfromUCS_le(ses->serverOS,
3071 bcc_ptr += 2 * (len + 1);
3072 remaining_words -= len + 1;
3073 ses->serverOS[2 * len] = 0;
3074 ses->serverOS[1 + (2 * len)] = 0;
3075 if (remaining_words > 0) {
3076 len = UniStrnlen((wchar_t *)
3081 kcalloc(1, 2 * (len + 1),
3083 cifs_strfromUCS_le(ses->
3089 bcc_ptr += 2 * (len + 1);
3090 ses->serverNOS[2 * len] = 0;
3091 ses->serverNOS[1+(2*len)] = 0;
3092 remaining_words -= len + 1;
3093 if (remaining_words > 0) {
3094 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3095 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3120 } /* else no more room so create dummy domain string */
3122 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
3123 } else { /* no room so create dummy domain and NOS string */
3124 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
3125 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
3127 } else { /* ASCII */
3128 len = strnlen(bcc_ptr, 1024);
3129 if (((long) bcc_ptr + len) -
3130 (long) pByteArea(smb_buffer_response)
3131 <= BCC(smb_buffer_response)) {
3132 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
3133 strncpy(ses->serverOS,bcc_ptr, len);
3136 bcc_ptr[0] = 0; /* null terminate the string */
3139 len = strnlen(bcc_ptr, 1024);
3140 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
3141 strncpy(ses->serverNOS, bcc_ptr, len);
3146 len = strnlen(bcc_ptr, 1024);
3147 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
3148 strncpy(ses->serverDomain, bcc_ptr, len);
3154 ("Variable field of length %d extends beyond end of smb ",
3159 (" Security Blob Length extends beyond end of SMB"));
3162 cERROR(1, ("No session structure passed in."));
3166 (" Invalid Word count %d: ",
3167 smb_buffer_response->WordCount));
3172 cifs_buf_release(smb_buffer);
3178 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3179 const char *tree, struct cifsTconInfo *tcon,
3180 const struct nls_table *nls_codepage)
3182 struct smb_hdr *smb_buffer;
3183 struct smb_hdr *smb_buffer_response;
3186 unsigned char *bcc_ptr;
3194 smb_buffer = cifs_buf_get();
3195 if (smb_buffer == NULL) {
3198 smb_buffer_response = smb_buffer;
3200 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3201 NULL /*no tid */ , 4 /*wct */ );
3203 smb_buffer->Mid = GetNextMid(ses->server);
3204 smb_buffer->Uid = ses->Suid;
3205 pSMB = (TCONX_REQ *) smb_buffer;
3206 pSMBr = (TCONX_RSP *) smb_buffer_response;
3208 pSMB->AndXCommand = 0xFF;
3209 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3210 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3211 bcc_ptr = &pSMB->Password[0];
3212 bcc_ptr++; /* skip password */
3214 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3215 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3217 if (ses->capabilities & CAP_STATUS32) {
3218 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3220 if (ses->capabilities & CAP_DFS) {
3221 smb_buffer->Flags2 |= SMBFLG2_DFS;
3223 if (ses->capabilities & CAP_UNICODE) {
3224 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3226 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
3227 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3228 bcc_ptr += 2; /* skip trailing null */
3229 } else { /* ASCII */
3231 strcpy(bcc_ptr, tree);
3232 bcc_ptr += strlen(tree) + 1;
3234 strcpy(bcc_ptr, "?????");
3235 bcc_ptr += strlen("?????");
3237 count = bcc_ptr - &pSMB->Password[0];
3238 pSMB->hdr.smb_buf_length += count;
3239 pSMB->ByteCount = cpu_to_le16(count);
3241 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3243 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3244 /* above now done in SendReceive */
3245 if ((rc == 0) && (tcon != NULL)) {
3246 tcon->tidStatus = CifsGood;
3247 tcon->tid = smb_buffer_response->Tid;
3248 bcc_ptr = pByteArea(smb_buffer_response);
3249 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3250 /* skip service field (NB: this field is always ASCII) */
3251 bcc_ptr += length + 1;
3252 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3253 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3254 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3255 if ((bcc_ptr + (2 * length)) -
3256 pByteArea(smb_buffer_response) <=
3257 BCC(smb_buffer_response)) {
3258 if(tcon->nativeFileSystem)
3259 kfree(tcon->nativeFileSystem);
3260 tcon->nativeFileSystem =
3261 kcalloc(1, length + 2, GFP_KERNEL);
3262 cifs_strfromUCS_le(tcon->nativeFileSystem,
3263 (wchar_t *) bcc_ptr,
3264 length, nls_codepage);
3265 bcc_ptr += 2 * length;
3266 bcc_ptr[0] = 0; /* null terminate the string */
3270 /* else do not bother copying these informational fields */
3272 length = strnlen(bcc_ptr, 1024);
3273 if ((bcc_ptr + length) -
3274 pByteArea(smb_buffer_response) <=
3275 BCC(smb_buffer_response)) {
3276 if(tcon->nativeFileSystem)
3277 kfree(tcon->nativeFileSystem);
3278 tcon->nativeFileSystem =
3279 kcalloc(1, length + 1, GFP_KERNEL);
3280 strncpy(tcon->nativeFileSystem, bcc_ptr,
3283 /* else do not bother copying these informational fields */
3285 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3286 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3287 } else if ((rc == 0) && tcon == NULL) {
3288 /* all we need to save for IPC$ connection */
3289 ses->ipc_tid = smb_buffer_response->Tid;
3293 cifs_buf_release(smb_buffer);
3298 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3302 struct cifsSesInfo *ses = NULL;
3303 struct task_struct *cifsd_task;
3307 if (cifs_sb->tcon) {
3308 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3309 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3314 tconInfoFree(cifs_sb->tcon);
3315 if ((ses) && (ses->server)) {
3316 /* save off task so we do not refer to ses later */
3317 cifsd_task = ses->server->tsk;
3318 cFYI(1, ("About to do SMBLogoff "));
3319 rc = CIFSSMBLogoff(xid, ses);
3323 } else if (rc == -ESHUTDOWN) {
3324 cFYI(1,("Waking up socket by sending it signal"));
3326 send_sig(SIGKILL,cifsd_task,1);
3327 wait_for_completion(&cifsd_complete);
3330 } /* else - we have an smb session
3331 left on this socket do not kill cifsd */
3333 cFYI(1, ("No session or bad tcon"));
3336 cifs_sb->tcon = NULL;
3338 set_current_state(TASK_INTERRUPTIBLE);
3339 schedule_timeout(HZ / 2);
3345 return rc; /* BB check if we should always return zero here */
3348 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3349 struct nls_table * nls_info)
3352 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3353 int ntlmv2_flag = FALSE;
3356 /* what if server changes its buffer size after dropping the session? */
3357 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3358 rc = CIFSSMBNegotiate(xid, pSesInfo);
3359 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3360 rc = CIFSSMBNegotiate(xid, pSesInfo);
3365 spin_lock(&GlobalMid_Lock);
3366 if(pSesInfo->server->tcpStatus != CifsExiting)
3367 pSesInfo->server->tcpStatus = CifsGood;
3370 spin_unlock(&GlobalMid_Lock);
3376 pSesInfo->capabilities = pSesInfo->server->capabilities;
3377 if(linuxExtEnabled == 0)
3378 pSesInfo->capabilities &= (~CAP_UNIX);
3379 /* pSesInfo->sequence_number = 0;*/
3380 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3381 pSesInfo->server->secMode,
3382 pSesInfo->server->capabilities,
3383 pSesInfo->server->timeZone));
3384 if (extended_security
3385 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3386 && (pSesInfo->server->secType == NTLMSSP)) {
3387 cFYI(1, ("New style sesssetup "));
3388 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3389 NULL /* security blob */,
3390 0 /* blob length */,
3392 } else if (extended_security
3393 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3394 && (pSesInfo->server->secType == RawNTLMSSP)) {
3395 cFYI(1, ("NTLMSSP sesssetup "));
3396 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3403 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3404 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3409 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3411 CalcNTLMv2_response(pSesInfo,v2_response);
3413 cifs_calculate_ntlmv2_mac_key(
3414 pSesInfo->server->mac_signing_key,
3415 response, ntlm_session_key, */
3417 /* BB Put dummy sig in SessSetup PDU? */
3424 SMBNTencrypt(pSesInfo->password,
3425 pSesInfo->server->cryptKey,
3429 cifs_calculate_mac_key(
3430 pSesInfo->server->mac_signing_key,
3432 pSesInfo->password);
3434 /* for better security the weaker lanman hash not sent
3435 in AuthSessSetup so we no longer calculate it */
3437 rc = CIFSNTLMSSPAuthSessSetup(xid,
3443 } else { /* old style NTLM 0.12 session setup */
3444 SMBNTencrypt(pSesInfo->password,
3445 pSesInfo->server->cryptKey,
3449 cifs_calculate_mac_key(
3450 pSesInfo->server->mac_signing_key,
3451 ntlm_session_key, pSesInfo->password);
3453 rc = CIFSSessSetup(xid, pSesInfo,
3454 ntlm_session_key, nls_info);
3457 cERROR(1,("Send error in SessSetup = %d",rc));
3459 cFYI(1,("CIFS Session Established successfully"));
3460 pSesInfo->status = CifsGood;