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 <linux/pagevec.h>
34 #include <asm/uaccess.h>
35 #include <asm/processor.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
41 #include "cifs_fs_sb.h"
44 #include "rfc1002pdu.h"
48 #define RFC1001_PORT 139
50 static DECLARE_COMPLETION(cifsd_complete);
52 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
54 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
57 extern mempool_t *cifs_req_poolp;
65 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
66 char *iocharset; /* local code page for mapping to and from Unicode */
67 char source_rfc1001_name[16]; /* netbios name of client */
68 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
78 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
79 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
80 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
82 unsigned remap:1; /* set to remap seven reserved chars in filenames */
83 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
85 unsigned nocase; /* request case insensitive filenames */
86 unsigned nobrl; /* disable sending byte range locks to srv */
90 unsigned short int port;
93 static int ipv4_connect(struct sockaddr_in *psin_server,
94 struct socket **csocket,
96 char * server_netb_name);
97 static int ipv6_connect(struct sockaddr_in6 *psin_server,
98 struct socket **csocket);
102 * cifs tcp session reconnection
104 * mark tcp session as reconnecting so temporarily locked
105 * mark all smb sessions as reconnecting for tcp session
106 * reconnect tcp session
107 * wake up waiters on reconnection? - (not needed currently)
111 cifs_reconnect(struct TCP_Server_Info *server)
114 struct list_head *tmp;
115 struct cifsSesInfo *ses;
116 struct cifsTconInfo *tcon;
117 struct mid_q_entry * mid_entry;
119 spin_lock(&GlobalMid_Lock);
120 if(server->tcpStatus == CifsExiting) {
121 /* the demux thread will exit normally
122 next time through the loop */
123 spin_unlock(&GlobalMid_Lock);
126 server->tcpStatus = CifsNeedReconnect;
127 spin_unlock(&GlobalMid_Lock);
130 cFYI(1, ("Reconnecting tcp session"));
132 /* before reconnecting the tcp session, mark the smb session (uid)
133 and the tid bad so they are not used until reconnected */
134 read_lock(&GlobalSMBSeslock);
135 list_for_each(tmp, &GlobalSMBSessionList) {
136 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
138 if (ses->server == server) {
139 ses->status = CifsNeedReconnect;
143 /* else tcp and smb sessions need reconnection */
145 list_for_each(tmp, &GlobalTreeConnectionList) {
146 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
147 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
148 tcon->tidStatus = CifsNeedReconnect;
151 read_unlock(&GlobalSMBSeslock);
152 /* do not want to be sending data on a socket we are freeing */
153 down(&server->tcpSem);
154 if(server->ssocket) {
155 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
156 server->ssocket->flags));
157 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
158 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
159 server->ssocket->flags));
160 sock_release(server->ssocket);
161 server->ssocket = NULL;
164 spin_lock(&GlobalMid_Lock);
165 list_for_each(tmp, &server->pending_mid_q) {
166 mid_entry = list_entry(tmp, struct
170 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
171 /* Mark other intransit requests as needing
172 retry so we do not immediately mark the
173 session bad again (ie after we reconnect
174 below) as they timeout too */
175 mid_entry->midState = MID_RETRY_NEEDED;
179 spin_unlock(&GlobalMid_Lock);
182 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
184 if(server->protocolType == IPV6) {
185 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
187 rc = ipv4_connect(&server->addr.sockAddr,
189 server->workstation_RFC1001_name,
190 server->server_RFC1001_name);
193 cFYI(1,("reconnect error %d",rc));
196 atomic_inc(&tcpSesReconnectCount);
197 spin_lock(&GlobalMid_Lock);
198 if(server->tcpStatus != CifsExiting)
199 server->tcpStatus = CifsGood;
200 server->sequence_number = 0;
201 spin_unlock(&GlobalMid_Lock);
202 /* atomic_set(&server->inFlight,0);*/
203 wake_up(&server->response_q);
211 0 not a transact2, or all data present
212 >0 transact2 with that much data missing
213 -EINVAL = invalid transact2
216 static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
218 struct smb_t2_rsp * pSMBt;
220 int data_in_this_rsp;
223 if(pSMB->Command != SMB_COM_TRANSACTION2)
226 /* check for plausible wct, bcc and t2 data and parm sizes */
227 /* check for parm and data offset going beyond end of smb */
228 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
229 cFYI(1,("invalid transact2 word count"));
233 pSMBt = (struct smb_t2_rsp *)pSMB;
235 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
236 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
238 remaining = total_data_size - data_in_this_rsp;
242 else if(remaining < 0) {
243 cFYI(1,("total data %d smaller than data in frame %d",
244 total_data_size, data_in_this_rsp));
247 cFYI(1,("missing %d bytes from transact2, check next response",
249 if(total_data_size > maxBufSize) {
250 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
251 total_data_size,maxBufSize));
258 static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
260 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
261 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
266 char * data_area_of_target;
267 char * data_area_of_buf2;
270 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
272 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
273 cFYI(1,("total data sizes of primary and secondary t2 differ"));
276 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
278 remaining = total_data_size - total_in_buf;
283 if(remaining == 0) /* nothing to do, ignore */
286 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
287 if(remaining < total_in_buf2) {
288 cFYI(1,("transact2 2nd response contains too much data"));
291 /* find end of first SMB data area */
292 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
293 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
294 /* validate target area */
296 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
297 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
299 data_area_of_target += total_in_buf;
301 /* copy second buffer into end of first buffer */
302 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
303 total_in_buf += total_in_buf2;
304 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
305 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
306 byte_count += total_in_buf2;
307 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
309 byte_count = pTargetSMB->smb_buf_length;
310 byte_count += total_in_buf2;
312 /* BB also add check that we are not beyond maximum buffer size */
314 pTargetSMB->smb_buf_length = byte_count;
316 if(remaining == total_in_buf2) {
317 cFYI(1,("found the last secondary response"));
318 return 0; /* we are done */
319 } else /* more responses to go */
325 cifs_demultiplex_thread(struct TCP_Server_Info *server)
328 unsigned int pdu_length, total_read;
329 struct smb_hdr *smb_buffer = NULL;
330 struct smb_hdr *bigbuf = NULL;
331 struct smb_hdr *smallbuf = NULL;
332 struct msghdr smb_msg;
334 struct socket *csocket = server->ssocket;
335 struct list_head *tmp;
336 struct cifsSesInfo *ses;
337 struct task_struct *task_to_wake = NULL;
338 struct mid_q_entry *mid_entry;
340 int isLargeBuf = FALSE;
345 allow_signal(SIGKILL);
346 current->flags |= PF_MEMALLOC;
347 server->tsk = current; /* save process info to wake at shutdown */
348 cFYI(1, ("Demultiplex PID: %d", current->pid));
349 write_lock(&GlobalSMBSeslock);
350 atomic_inc(&tcpSesAllocCount);
351 length = tcpSesAllocCount.counter;
352 write_unlock(&GlobalSMBSeslock);
353 complete(&cifsd_complete);
355 mempool_resize(cifs_req_poolp,
356 length + cifs_min_rcv,
360 while (server->tcpStatus != CifsExiting) {
363 if (bigbuf == NULL) {
364 bigbuf = cifs_buf_get();
366 cERROR(1,("No memory for large SMB response"));
368 /* retry will check if exiting */
371 } else if(isLargeBuf) {
372 /* we are reusing a dirtry large buf, clear its start */
373 memset(bigbuf, 0, sizeof (struct smb_hdr));
376 if (smallbuf == NULL) {
377 smallbuf = cifs_small_buf_get();
378 if(smallbuf == NULL) {
379 cERROR(1,("No memory for SMB response"));
381 /* retry will check if exiting */
384 /* beginning of smb buffer is cleared in our buf_get */
385 } else /* if existing small buf clear beginning */
386 memset(smallbuf, 0, sizeof (struct smb_hdr));
390 smb_buffer = smallbuf;
391 iov.iov_base = smb_buffer;
393 smb_msg.msg_control = NULL;
394 smb_msg.msg_controllen = 0;
396 kernel_recvmsg(csocket, &smb_msg,
397 &iov, 1, 4, 0 /* BB see socket.h flags */);
399 if(server->tcpStatus == CifsExiting) {
401 } else if (server->tcpStatus == CifsNeedReconnect) {
402 cFYI(1,("Reconnect after server stopped responding"));
403 cifs_reconnect(server);
404 cFYI(1,("call to reconnect done"));
405 csocket = server->ssocket;
407 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
408 msleep(1); /* minimum sleep to prevent looping
409 allowing socket to clear and app threads to set
410 tcpStatus CifsNeedReconnect if server hung */
412 } else if (length <= 0) {
413 if(server->tcpStatus == CifsNew) {
414 cFYI(1,("tcp session abend after SMBnegprot"));
415 /* some servers kill the TCP session rather than
416 returning an SMB negprot error, in which
417 case reconnecting here is not going to help,
418 and so simply return error to mount */
421 if(length == -EINTR) {
422 cFYI(1,("cifsd thread killed"));
425 cFYI(1,("Reconnect after unexpected peek error %d",
427 cifs_reconnect(server);
428 csocket = server->ssocket;
429 wake_up(&server->response_q);
431 } else if (length < 4) {
433 ("Frame under four bytes received (%d bytes long)",
435 cifs_reconnect(server);
436 csocket = server->ssocket;
437 wake_up(&server->response_q);
441 /* The right amount was read from socket - 4 bytes */
442 /* so we can now interpret the length field */
444 /* the first byte big endian of the length field,
445 is actually not part of the length but the type
446 with the most common, zero, as regular data */
447 temp = *((char *) smb_buffer);
449 /* Note that FC 1001 length is big endian on the wire,
450 but we convert it here so it is always manipulated
451 as host byte order */
452 pdu_length = ntohl(smb_buffer->smb_buf_length);
453 smb_buffer->smb_buf_length = pdu_length;
455 cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
457 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
459 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
460 cFYI(1,("Good RFC 1002 session rsp"));
462 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
463 /* we get this from Windows 98 instead of
464 an error on SMB negprot response */
465 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
467 if(server->tcpStatus == CifsNew) {
468 /* if nack on negprot (rather than
469 ret of smb negprot error) reconnecting
470 not going to help, ret error to mount */
473 /* give server a second to
474 clean up before reconnect attempt */
476 /* always try 445 first on reconnect
477 since we get NACK on some if we ever
478 connected to port 139 (the NACK is
479 since we do not begin with RFC1001
480 session initialize frame) */
481 server->addr.sockAddr.sin_port =
483 cifs_reconnect(server);
484 csocket = server->ssocket;
485 wake_up(&server->response_q);
488 } else if (temp != (char) 0) {
489 cERROR(1,("Unknown RFC 1002 frame"));
490 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
492 cifs_reconnect(server);
493 csocket = server->ssocket;
497 /* else we have an SMB response */
498 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
499 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
500 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
501 length, pdu_length+4));
502 cifs_reconnect(server);
503 csocket = server->ssocket;
504 wake_up(&server->response_q);
511 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
513 memcpy(bigbuf, smallbuf, 4);
517 iov.iov_base = 4 + (char *)smb_buffer;
518 iov.iov_len = pdu_length;
519 for (total_read = 0; total_read < pdu_length;
520 total_read += length) {
521 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
522 pdu_length - total_read, 0);
523 if((server->tcpStatus == CifsExiting) ||
524 (length == -EINTR)) {
528 } else if (server->tcpStatus == CifsNeedReconnect) {
529 cifs_reconnect(server);
530 csocket = server->ssocket;
531 /* Reconnect wakes up rspns q */
532 /* Now we will reread sock */
535 } else if ((length == -ERESTARTSYS) ||
536 (length == -EAGAIN)) {
537 msleep(1); /* minimum sleep to prevent looping,
538 allowing socket to clear and app
539 threads to set tcpStatus
540 CifsNeedReconnect if server hung*/
542 } else if (length <= 0) {
543 cERROR(1,("Received no data, expecting %d",
544 pdu_length - total_read));
545 cifs_reconnect(server);
546 csocket = server->ssocket;
553 else if(reconnect == 1)
556 length += 4; /* account for rfc1002 hdr */
559 dump_smb(smb_buffer, length);
560 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
561 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
567 spin_lock(&GlobalMid_Lock);
568 list_for_each(tmp, &server->pending_mid_q) {
569 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
571 if ((mid_entry->mid == smb_buffer->Mid) &&
572 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
573 (mid_entry->command == smb_buffer->Command)) {
574 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
575 /* We have a multipart transact2 resp */
577 if(mid_entry->resp_buf) {
578 /* merge response - fix up 1st*/
579 if(coalesce_t2(smb_buffer,
580 mid_entry->resp_buf)) {
583 /* all parts received */
588 cERROR(1,("1st trans2 resp needs bigbuf"));
589 /* BB maybe we can fix this up, switch
590 to already allocated large buffer? */
592 /* Have first buffer */
593 mid_entry->resp_buf =
595 mid_entry->largeBuf = 1;
601 mid_entry->resp_buf = smb_buffer;
603 mid_entry->largeBuf = 1;
605 mid_entry->largeBuf = 0;
607 task_to_wake = mid_entry->tsk;
608 mid_entry->midState = MID_RESPONSE_RECEIVED;
609 #ifdef CONFIG_CIFS_STATS2
610 mid_entry->when_received = jiffies;
615 spin_unlock(&GlobalMid_Lock);
617 /* Was previous buf put in mpx struct for multi-rsp? */
619 /* smb buffer will be freed by user thread */
625 wake_up_process(task_to_wake);
626 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
627 && (isMultiRsp == FALSE)) {
628 cERROR(1, ("No task to wake, unknown frame rcvd!"));
629 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
630 sizeof(struct smb_hdr));
632 } /* end while !EXITING */
634 spin_lock(&GlobalMid_Lock);
635 server->tcpStatus = CifsExiting;
637 /* check if we have blocked requests that need to free */
638 /* Note that cifs_max_pending is normally 50, but
639 can be set at module install time to as little as two */
640 if(atomic_read(&server->inFlight) >= cifs_max_pending)
641 atomic_set(&server->inFlight, cifs_max_pending - 1);
642 /* We do not want to set the max_pending too low or we
643 could end up with the counter going negative */
644 spin_unlock(&GlobalMid_Lock);
645 /* Although there should not be any requests blocked on
646 this queue it can not hurt to be paranoid and try to wake up requests
647 that may haven been blocked when more than 50 at time were on the wire
648 to the same server - they now will see the session is in exit state
649 and get out of SendReceive. */
650 wake_up_all(&server->request_q);
651 /* give those requests time to exit */
654 if(server->ssocket) {
655 sock_release(csocket);
656 server->ssocket = NULL;
658 /* buffer usuallly freed in free_mid - need to free it here on exit */
660 cifs_buf_release(bigbuf);
661 if (smallbuf != NULL)
662 cifs_small_buf_release(smallbuf);
664 read_lock(&GlobalSMBSeslock);
665 if (list_empty(&server->pending_mid_q)) {
666 /* loop through server session structures attached to this and
668 list_for_each(tmp, &GlobalSMBSessionList) {
670 list_entry(tmp, struct cifsSesInfo,
672 if (ses->server == server) {
673 ses->status = CifsExiting;
677 read_unlock(&GlobalSMBSeslock);
679 /* although we can not zero the server struct pointer yet,
680 since there are active requests which may depnd on them,
681 mark the corresponding SMB sessions as exiting too */
682 list_for_each(tmp, &GlobalSMBSessionList) {
683 ses = list_entry(tmp, struct cifsSesInfo,
685 if (ses->server == server) {
686 ses->status = CifsExiting;
690 spin_lock(&GlobalMid_Lock);
691 list_for_each(tmp, &server->pending_mid_q) {
692 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
693 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
695 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
696 task_to_wake = mid_entry->tsk;
698 wake_up_process(task_to_wake);
702 spin_unlock(&GlobalMid_Lock);
703 read_unlock(&GlobalSMBSeslock);
704 /* 1/8th of sec is more than enough time for them to exit */
708 if (!list_empty(&server->pending_mid_q)) {
709 /* mpx threads have not exited yet give them
710 at least the smb send timeout time for long ops */
711 /* due to delays on oplock break requests, we need
712 to wait at least 45 seconds before giving up
713 on a request getting a response and going ahead
715 cFYI(1, ("Wait for exit from demultiplex thread"));
717 /* if threads still have not exited they are probably never
718 coming home not much else we can do but free the memory */
721 write_lock(&GlobalSMBSeslock);
722 atomic_dec(&tcpSesAllocCount);
723 length = tcpSesAllocCount.counter;
725 /* last chance to mark ses pointers invalid
726 if there are any pointing to this (e.g
727 if a crazy root user tried to kill cifsd
728 kernel thread explicitly this might happen) */
729 list_for_each(tmp, &GlobalSMBSessionList) {
730 ses = list_entry(tmp, struct cifsSesInfo,
732 if (ses->server == server) {
736 write_unlock(&GlobalSMBSeslock);
740 mempool_resize(cifs_req_poolp,
741 length + cifs_min_rcv,
745 complete_and_exit(&cifsd_complete, 0);
750 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
754 unsigned int temp_len, i, j;
760 memset(vol->source_rfc1001_name,0x20,15);
761 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
762 /* does not have to be a perfect mapping since the field is
763 informational, only used for servers that do not support
764 port 445 and it can be overridden at mount time */
765 vol->source_rfc1001_name[i] =
766 toupper(system_utsname.nodename[i]);
768 vol->source_rfc1001_name[15] = 0;
769 /* null target name indicates to use *SMBSERVR default called name
770 if we end up sending RFC1001 session initialize */
771 vol->target_rfc1001_name[0] = 0;
772 vol->linux_uid = current->uid; /* current->euid instead? */
773 vol->linux_gid = current->gid;
774 vol->dir_mode = S_IRWXUGO;
775 /* 2767 perms indicate mandatory locking support */
776 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
778 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
781 /* default is always to request posix paths. */
782 vol->posix_paths = 1;
787 if(strncmp(options,"sep=",4) == 0) {
788 if(options[4] != 0) {
789 separator[0] = options[4];
792 cFYI(1,("Null separator not allowed"));
796 while ((data = strsep(&options, separator)) != NULL) {
799 if ((value = strchr(data, '=')) != NULL)
802 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
804 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
806 } else if (strnicmp(data, "user", 4) == 0) {
807 if (!value || !*value) {
809 "CIFS: invalid or missing username\n");
810 return 1; /* needs_arg; */
812 if (strnlen(value, 200) < 200) {
813 vol->username = value;
815 printk(KERN_WARNING "CIFS: username too long\n");
818 } else if (strnicmp(data, "pass", 4) == 0) {
820 vol->password = NULL;
822 } else if(value[0] == 0) {
823 /* check if string begins with double comma
824 since that would mean the password really
825 does start with a comma, and would not
826 indicate an empty string */
827 if(value[1] != separator[0]) {
828 vol->password = NULL;
832 temp_len = strlen(value);
833 /* removed password length check, NTLM passwords
834 can be arbitrarily long */
836 /* if comma in password, the string will be
837 prematurely null terminated. Commas in password are
838 specified across the cifs mount interface by a double
839 comma ie ,, and a comma used as in other cases ie ','
840 as a parameter delimiter/separator is single and due
841 to the strsep above is temporarily zeroed. */
843 /* NB: password legally can have multiple commas and
844 the only illegal character in a password is null */
846 if ((value[temp_len] == 0) &&
847 (value[temp_len+1] == separator[0])) {
849 value[temp_len] = separator[0];
850 temp_len+=2; /* move after the second comma */
851 while(value[temp_len] != 0) {
852 if (value[temp_len] == separator[0]) {
853 if (value[temp_len+1] ==
855 /* skip second comma */
858 /* single comma indicating start
865 if(value[temp_len] == 0) {
869 /* point option to start of next parm */
870 options = value + temp_len + 1;
872 /* go from value to value + temp_len condensing
873 double commas to singles. Note that this ends up
874 allocating a few bytes too many, which is ok */
875 vol->password = kzalloc(temp_len, GFP_KERNEL);
876 if(vol->password == NULL) {
877 printk("CIFS: no memory for pass\n");
880 for(i=0,j=0;i<temp_len;i++,j++) {
881 vol->password[j] = value[i];
882 if(value[i] == separator[0]
883 && value[i+1] == separator[0]) {
884 /* skip second comma */
888 vol->password[j] = 0;
890 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
891 if(vol->password == NULL) {
892 printk("CIFS: no memory for pass\n");
895 strcpy(vol->password, value);
897 } else if (strnicmp(data, "ip", 2) == 0) {
898 if (!value || !*value) {
900 } else if (strnlen(value, 35) < 35) {
903 printk(KERN_WARNING "CIFS: ip address too long\n");
906 } else if ((strnicmp(data, "unc", 3) == 0)
907 || (strnicmp(data, "target", 6) == 0)
908 || (strnicmp(data, "path", 4) == 0)) {
909 if (!value || !*value) {
911 "CIFS: invalid path to network resource\n");
912 return 1; /* needs_arg; */
914 if ((temp_len = strnlen(value, 300)) < 300) {
915 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
918 strcpy(vol->UNC,value);
919 if (strncmp(vol->UNC, "//", 2) == 0) {
922 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
924 "CIFS: UNC Path does not begin with // or \\\\ \n");
928 printk(KERN_WARNING "CIFS: UNC name too long\n");
931 } else if ((strnicmp(data, "domain", 3) == 0)
932 || (strnicmp(data, "workgroup", 5) == 0)) {
933 if (!value || !*value) {
934 printk(KERN_WARNING "CIFS: invalid domain name\n");
935 return 1; /* needs_arg; */
937 /* BB are there cases in which a comma can be valid in
938 a domain name and need special handling? */
939 if (strnlen(value, 65) < 65) {
940 vol->domainname = value;
941 cFYI(1, ("Domain name set"));
943 printk(KERN_WARNING "CIFS: domain name too long\n");
946 } else if (strnicmp(data, "iocharset", 9) == 0) {
947 if (!value || !*value) {
948 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
949 return 1; /* needs_arg; */
951 if (strnlen(value, 65) < 65) {
952 if(strnicmp(value,"default",7))
953 vol->iocharset = value;
954 /* if iocharset not set load_nls_default used by caller */
955 cFYI(1, ("iocharset set to %s",value));
957 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
960 } else if (strnicmp(data, "uid", 3) == 0) {
961 if (value && *value) {
963 simple_strtoul(value, &value, 0);
965 } else if (strnicmp(data, "gid", 3) == 0) {
966 if (value && *value) {
968 simple_strtoul(value, &value, 0);
970 } else if (strnicmp(data, "file_mode", 4) == 0) {
971 if (value && *value) {
973 simple_strtoul(value, &value, 0);
975 } else if (strnicmp(data, "dir_mode", 4) == 0) {
976 if (value && *value) {
978 simple_strtoul(value, &value, 0);
980 } else if (strnicmp(data, "dirmode", 4) == 0) {
981 if (value && *value) {
983 simple_strtoul(value, &value, 0);
985 } else if (strnicmp(data, "port", 4) == 0) {
986 if (value && *value) {
988 simple_strtoul(value, &value, 0);
990 } else if (strnicmp(data, "rsize", 5) == 0) {
991 if (value && *value) {
993 simple_strtoul(value, &value, 0);
995 } else if (strnicmp(data, "wsize", 5) == 0) {
996 if (value && *value) {
998 simple_strtoul(value, &value, 0);
1000 } else if (strnicmp(data, "sockopt", 5) == 0) {
1001 if (value && *value) {
1003 simple_strtoul(value, &value, 0);
1005 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1006 if (!value || !*value || (*value == ' ')) {
1007 cFYI(1,("invalid (empty) netbiosname specified"));
1009 memset(vol->source_rfc1001_name,0x20,15);
1011 /* BB are there cases in which a comma can be
1012 valid in this workstation netbios name (and need
1013 special handling)? */
1015 /* We do not uppercase netbiosname for user */
1019 vol->source_rfc1001_name[i] = value[i];
1021 /* The string has 16th byte zero still from
1022 set at top of the function */
1023 if((i==15) && (value[i] != 0))
1024 printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
1026 } else if (strnicmp(data, "servern", 7) == 0) {
1027 /* servernetbiosname specified override *SMBSERVER */
1028 if (!value || !*value || (*value == ' ')) {
1029 cFYI(1,("empty server netbiosname specified"));
1031 /* last byte, type, is 0x20 for servr type */
1032 memset(vol->target_rfc1001_name,0x20,16);
1035 /* BB are there cases in which a comma can be
1036 valid in this workstation netbios name (and need
1037 special handling)? */
1039 /* user or mount helper must uppercase netbiosname */
1043 vol->target_rfc1001_name[i] = value[i];
1045 /* The string has 16th byte zero still from
1046 set at top of the function */
1047 if((i==15) && (value[i] != 0))
1048 printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
1050 } else if (strnicmp(data, "credentials", 4) == 0) {
1052 } else if (strnicmp(data, "version", 3) == 0) {
1054 } else if (strnicmp(data, "guest",5) == 0) {
1056 } else if (strnicmp(data, "rw", 2) == 0) {
1058 } else if ((strnicmp(data, "suid", 4) == 0) ||
1059 (strnicmp(data, "nosuid", 6) == 0) ||
1060 (strnicmp(data, "exec", 4) == 0) ||
1061 (strnicmp(data, "noexec", 6) == 0) ||
1062 (strnicmp(data, "nodev", 5) == 0) ||
1063 (strnicmp(data, "noauto", 6) == 0) ||
1064 (strnicmp(data, "dev", 3) == 0)) {
1065 /* The mount tool or mount.cifs helper (if present)
1066 uses these opts to set flags, and the flags are read
1067 by the kernel vfs layer before we get here (ie
1068 before read super) so there is no point trying to
1069 parse these options again and set anything and it
1070 is ok to just ignore them */
1072 } else if (strnicmp(data, "ro", 2) == 0) {
1074 } else if (strnicmp(data, "hard", 4) == 0) {
1076 } else if (strnicmp(data, "soft", 4) == 0) {
1078 } else if (strnicmp(data, "perm", 4) == 0) {
1080 } else if (strnicmp(data, "noperm", 6) == 0) {
1082 } else if (strnicmp(data, "mapchars", 8) == 0) {
1084 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1086 } else if (strnicmp(data, "sfu", 3) == 0) {
1088 } else if (strnicmp(data, "nosfu", 5) == 0) {
1090 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1091 vol->posix_paths = 1;
1092 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1093 vol->posix_paths = 0;
1094 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1095 (strnicmp(data, "ignorecase", 10) == 0)) {
1097 } else if (strnicmp(data, "brl", 3) == 0) {
1099 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1100 (strnicmp(data, "nolock", 6) == 0)) {
1102 /* turn off mandatory locking in mode
1103 if remote locking is turned off since the
1104 local vfs will do advisory */
1105 if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1106 vol->file_mode = S_IALLUGO;
1107 } else if (strnicmp(data, "setuids", 7) == 0) {
1109 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1111 } else if (strnicmp(data, "nohard", 6) == 0) {
1113 } else if (strnicmp(data, "nosoft", 6) == 0) {
1115 } else if (strnicmp(data, "nointr", 6) == 0) {
1117 } else if (strnicmp(data, "intr", 4) == 0) {
1119 } else if (strnicmp(data, "serverino",7) == 0) {
1120 vol->server_ino = 1;
1121 } else if (strnicmp(data, "noserverino",9) == 0) {
1122 vol->server_ino = 0;
1123 } else if (strnicmp(data, "acl",3) == 0) {
1124 vol->no_psx_acl = 0;
1125 } else if (strnicmp(data, "noacl",5) == 0) {
1126 vol->no_psx_acl = 1;
1127 } else if (strnicmp(data, "direct",6) == 0) {
1129 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1131 } else if (strnicmp(data, "in6_addr",8) == 0) {
1132 if (!value || !*value) {
1133 vol->in6_addr = NULL;
1134 } else if (strnlen(value, 49) == 48) {
1135 vol->in6_addr = value;
1137 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1140 } else if (strnicmp(data, "noac", 4) == 0) {
1141 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1143 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1145 if (vol->UNC == NULL) {
1146 if(devname == NULL) {
1147 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1150 if ((temp_len = strnlen(devname, 300)) < 300) {
1151 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1152 if(vol->UNC == NULL)
1154 strcpy(vol->UNC,devname);
1155 if (strncmp(vol->UNC, "//", 2) == 0) {
1158 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1159 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1163 printk(KERN_WARNING "CIFS: UNC name too long\n");
1167 if(vol->UNCip == NULL)
1168 vol->UNCip = &vol->UNC[2];
1173 static struct cifsSesInfo *
1174 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1175 struct in6_addr *target_ip6_addr,
1176 char *userName, struct TCP_Server_Info **psrvTcp)
1178 struct list_head *tmp;
1179 struct cifsSesInfo *ses;
1181 read_lock(&GlobalSMBSeslock);
1183 list_for_each(tmp, &GlobalSMBSessionList) {
1184 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1186 if((target_ip_addr &&
1187 (ses->server->addr.sockAddr.sin_addr.s_addr
1188 == target_ip_addr->s_addr)) || (target_ip6_addr
1189 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1190 target_ip6_addr,sizeof(*target_ip6_addr)))){
1191 /* BB lock server and tcp session and increment use count here?? */
1192 *psrvTcp = ses->server; /* found a match on the TCP session */
1193 /* BB check if reconnection needed */
1195 (ses->userName, userName,
1196 MAX_USERNAME_SIZE) == 0){
1197 read_unlock(&GlobalSMBSeslock);
1198 return ses; /* found exact match on both tcp and SMB sessions */
1202 /* else tcp and smb sessions need reconnection */
1204 read_unlock(&GlobalSMBSeslock);
1208 static struct cifsTconInfo *
1209 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1211 struct list_head *tmp;
1212 struct cifsTconInfo *tcon;
1214 read_lock(&GlobalSMBSeslock);
1215 list_for_each(tmp, &GlobalTreeConnectionList) {
1216 cFYI(1, ("Next tcon - "));
1217 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1219 if (tcon->ses->server) {
1221 (" old ip addr: %x == new ip %x ?",
1222 tcon->ses->server->addr.sockAddr.sin_addr.
1223 s_addr, new_target_ip_addr));
1224 if (tcon->ses->server->addr.sockAddr.sin_addr.
1225 s_addr == new_target_ip_addr) {
1226 /* BB lock tcon and server and tcp session and increment use count here? */
1227 /* found a match on the TCP session */
1228 /* BB check if reconnection needed */
1229 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1230 tcon->treeName, uncName));
1232 (tcon->treeName, uncName,
1233 MAX_TREE_SIZE) == 0) {
1235 ("Matched UNC, old user: %s == new: %s ?",
1236 tcon->treeName, uncName));
1238 (tcon->ses->userName,
1240 MAX_USERNAME_SIZE) == 0) {
1241 read_unlock(&GlobalSMBSeslock);
1242 return tcon;/* also matched user (smb session)*/
1249 read_unlock(&GlobalSMBSeslock);
1254 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1255 const char *old_path, const struct nls_table *nls_codepage,
1258 unsigned char *referrals = NULL;
1259 unsigned int num_referrals;
1262 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1263 &num_referrals, &referrals, remap);
1265 /* BB Add in code to: if valid refrl, if not ip address contact
1266 the helper that resolves tcp names, mount to it, try to
1267 tcon to it unmount it if fail */
1275 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1276 const char *old_path, const struct nls_table *nls_codepage,
1277 unsigned int *pnum_referrals,
1278 unsigned char ** preferrals, int remap)
1283 *pnum_referrals = 0;
1285 if (pSesInfo->ipc_tid == 0) {
1286 temp_unc = kmalloc(2 /* for slashes */ +
1287 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1288 + 1 + 4 /* slash IPC$ */ + 2,
1290 if (temp_unc == NULL)
1294 strcpy(temp_unc + 2, pSesInfo->serverName);
1295 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1296 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1298 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1302 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1303 pnum_referrals, nls_codepage, remap);
1308 /* See RFC1001 section 14 on representation of Netbios names */
1309 static void rfc1002mangle(char * target,char * source, unsigned int length)
1313 for(i=0,j=0;i<(length);i++) {
1314 /* mask a nibble at a time and encode */
1315 target[j] = 'A' + (0x0F & (source[i] >> 4));
1316 target[j+1] = 'A' + (0x0F & source[i]);
1324 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1325 char * netbios_name, char * target_name)
1329 __be16 orig_port = 0;
1331 if(*csocket == NULL) {
1332 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1334 cERROR(1, ("Error %d creating socket",rc));
1338 /* BB other socket options to set KEEPALIVE, NODELAY? */
1339 cFYI(1,("Socket created"));
1340 (*csocket)->sk->sk_allocation = GFP_NOFS;
1344 psin_server->sin_family = AF_INET;
1345 if(psin_server->sin_port) { /* user overrode default port */
1346 rc = (*csocket)->ops->connect(*csocket,
1347 (struct sockaddr *) psin_server,
1348 sizeof (struct sockaddr_in),0);
1354 /* save original port so we can retry user specified port
1355 later if fall back ports fail this time */
1356 orig_port = psin_server->sin_port;
1358 /* do not retry on the same port we just failed on */
1359 if(psin_server->sin_port != htons(CIFS_PORT)) {
1360 psin_server->sin_port = htons(CIFS_PORT);
1362 rc = (*csocket)->ops->connect(*csocket,
1363 (struct sockaddr *) psin_server,
1364 sizeof (struct sockaddr_in),0);
1370 psin_server->sin_port = htons(RFC1001_PORT);
1371 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1372 psin_server, sizeof (struct sockaddr_in),0);
1377 /* give up here - unless we want to retry on different
1378 protocol families some day */
1381 psin_server->sin_port = orig_port;
1382 cFYI(1,("Error %d connecting to server via ipv4",rc));
1383 sock_release(*csocket);
1387 /* Eventually check for other socket options to change from
1388 the default. sock_setsockopt not used because it expects
1389 user space buffer */
1390 cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf,
1391 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1392 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1393 /* make the bufsizes depend on wsize/rsize and max requests */
1394 if((*csocket)->sk->sk_sndbuf < (200 * 1024))
1395 (*csocket)->sk->sk_sndbuf = 200 * 1024;
1396 if((*csocket)->sk->sk_rcvbuf < (140 * 1024))
1397 (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1399 /* send RFC1001 sessinit */
1400 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1401 /* some servers require RFC1001 sessinit before sending
1402 negprot - BB check reconnection in case where second
1403 sessinit is sent but no second negprot */
1404 struct rfc1002_session_packet * ses_init_buf;
1405 struct smb_hdr * smb_buf;
1406 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1408 ses_init_buf->trailer.session_req.called_len = 32;
1409 if(target_name && (target_name[0] != 0)) {
1410 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1413 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1414 DEFAULT_CIFS_CALLED_NAME,16);
1417 ses_init_buf->trailer.session_req.calling_len = 32;
1418 /* calling name ends in null (byte 16) from old smb
1420 if(netbios_name && (netbios_name[0] !=0)) {
1421 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1424 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1425 "LINUX_CIFS_CLNT",16);
1427 ses_init_buf->trailer.session_req.scope1 = 0;
1428 ses_init_buf->trailer.session_req.scope2 = 0;
1429 smb_buf = (struct smb_hdr *)ses_init_buf;
1430 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1431 smb_buf->smb_buf_length = 0x81000044;
1432 rc = smb_send(*csocket, smb_buf, 0x44,
1433 (struct sockaddr *)psin_server);
1434 kfree(ses_init_buf);
1436 /* else the negprot may still work without this
1437 even though malloc failed */
1445 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1449 __be16 orig_port = 0;
1451 if(*csocket == NULL) {
1452 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1454 cERROR(1, ("Error %d creating ipv6 socket",rc));
1458 /* BB other socket options to set KEEPALIVE, NODELAY? */
1459 cFYI(1,("ipv6 Socket created"));
1460 (*csocket)->sk->sk_allocation = GFP_NOFS;
1464 psin_server->sin6_family = AF_INET6;
1466 if(psin_server->sin6_port) { /* user overrode default port */
1467 rc = (*csocket)->ops->connect(*csocket,
1468 (struct sockaddr *) psin_server,
1469 sizeof (struct sockaddr_in6),0);
1475 /* save original port so we can retry user specified port
1476 later if fall back ports fail this time */
1478 orig_port = psin_server->sin6_port;
1479 /* do not retry on the same port we just failed on */
1480 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1481 psin_server->sin6_port = htons(CIFS_PORT);
1483 rc = (*csocket)->ops->connect(*csocket,
1484 (struct sockaddr *) psin_server,
1485 sizeof (struct sockaddr_in6),0);
1491 psin_server->sin6_port = htons(RFC1001_PORT);
1492 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1493 psin_server, sizeof (struct sockaddr_in6),0);
1498 /* give up here - unless we want to retry on different
1499 protocol families some day */
1502 psin_server->sin6_port = orig_port;
1503 cFYI(1,("Error %d connecting to server via ipv6",rc));
1504 sock_release(*csocket);
1508 /* Eventually check for other socket options to change from
1509 the default. sock_setsockopt not used because it expects
1510 user space buffer */
1511 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1517 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1518 char *mount_data, const char *devname)
1522 int address_type = AF_INET;
1523 struct socket *csocket = NULL;
1524 struct sockaddr_in sin_server;
1525 struct sockaddr_in6 sin_server6;
1526 struct smb_vol volume_info;
1527 struct cifsSesInfo *pSesInfo = NULL;
1528 struct cifsSesInfo *existingCifsSes = NULL;
1529 struct cifsTconInfo *tcon = NULL;
1530 struct TCP_Server_Info *srvTcp = NULL;
1534 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1536 memset(&volume_info,0,sizeof(struct smb_vol));
1537 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1538 kfree(volume_info.UNC);
1539 kfree(volume_info.password);
1544 if (volume_info.username) {
1545 /* BB fixme parse for domain name here */
1546 cFYI(1, ("Username: %s ", volume_info.username));
1549 cifserror("No username specified ");
1550 /* In userspace mount helper we can get user name from alternate
1551 locations such as env variables and files on disk */
1552 kfree(volume_info.UNC);
1553 kfree(volume_info.password);
1558 if (volume_info.UNCip && volume_info.UNC) {
1559 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1562 /* not ipv4 address, try ipv6 */
1563 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1565 address_type = AF_INET6;
1567 address_type = AF_INET;
1571 /* we failed translating address */
1572 kfree(volume_info.UNC);
1573 kfree(volume_info.password);
1578 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1581 } else if (volume_info.UNCip){
1582 /* BB using ip addr as server name connect to the DFS root below */
1583 cERROR(1,("Connecting to DFS root not implemented yet"));
1584 kfree(volume_info.UNC);
1585 kfree(volume_info.password);
1588 } else /* which servers DFS root would we conect to */ {
1590 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1591 kfree(volume_info.UNC);
1592 kfree(volume_info.password);
1597 /* this is needed for ASCII cp to Unicode converts */
1598 if(volume_info.iocharset == NULL) {
1599 cifs_sb->local_nls = load_nls_default();
1600 /* load_nls_default can not return null */
1602 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1603 if(cifs_sb->local_nls == NULL) {
1604 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1605 kfree(volume_info.UNC);
1606 kfree(volume_info.password);
1612 if(address_type == AF_INET)
1613 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1614 NULL /* no ipv6 addr */,
1615 volume_info.username, &srvTcp);
1616 else if(address_type == AF_INET6)
1617 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1618 &sin_server6.sin6_addr,
1619 volume_info.username, &srvTcp);
1621 kfree(volume_info.UNC);
1622 kfree(volume_info.password);
1629 cFYI(1, ("Existing tcp session with server found "));
1630 } else { /* create socket */
1631 if(volume_info.port)
1632 sin_server.sin_port = htons(volume_info.port);
1634 sin_server.sin_port = 0;
1635 rc = ipv4_connect(&sin_server,&csocket,
1636 volume_info.source_rfc1001_name,
1637 volume_info.target_rfc1001_name);
1640 ("Error connecting to IPv4 socket. Aborting operation"));
1642 sock_release(csocket);
1643 kfree(volume_info.UNC);
1644 kfree(volume_info.password);
1649 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1650 if (srvTcp == NULL) {
1652 sock_release(csocket);
1653 kfree(volume_info.UNC);
1654 kfree(volume_info.password);
1658 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1659 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1660 atomic_set(&srvTcp->inFlight,0);
1661 /* BB Add code for ipv6 case too */
1662 srvTcp->ssocket = csocket;
1663 srvTcp->protocolType = IPV4;
1664 init_waitqueue_head(&srvTcp->response_q);
1665 init_waitqueue_head(&srvTcp->request_q);
1666 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1667 /* at this point we are the only ones with the pointer
1668 to the struct since the kernel thread not created yet
1669 so no need to spinlock this init of tcpStatus */
1670 srvTcp->tcpStatus = CifsNew;
1671 init_MUTEX(&srvTcp->tcpSem);
1672 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1673 CLONE_FS | CLONE_FILES | CLONE_VM);
1676 sock_release(csocket);
1677 kfree(volume_info.UNC);
1678 kfree(volume_info.password);
1682 wait_for_completion(&cifsd_complete);
1684 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1685 memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
1686 srvTcp->sequence_number = 0;
1690 if (existingCifsSes) {
1691 pSesInfo = existingCifsSes;
1692 cFYI(1, ("Existing smb sess found "));
1693 kfree(volume_info.password);
1694 /* volume_info.UNC freed at end of function */
1696 cFYI(1, ("Existing smb sess not found "));
1697 pSesInfo = sesInfoAlloc();
1698 if (pSesInfo == NULL)
1701 pSesInfo->server = srvTcp;
1702 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1703 NIPQUAD(sin_server.sin_addr.s_addr));
1707 /* volume_info.password freed at unmount */
1708 if (volume_info.password)
1709 pSesInfo->password = volume_info.password;
1710 if (volume_info.username)
1711 strncpy(pSesInfo->userName,
1712 volume_info.username,MAX_USERNAME_SIZE);
1713 if (volume_info.domainname)
1714 strncpy(pSesInfo->domainName,
1715 volume_info.domainname,MAX_USERNAME_SIZE);
1716 pSesInfo->linux_uid = volume_info.linux_uid;
1717 down(&pSesInfo->sesSem);
1718 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1719 up(&pSesInfo->sesSem);
1721 atomic_inc(&srvTcp->socketUseCount);
1723 kfree(volume_info.password);
1726 /* search for existing tcon to this server share */
1728 if(volume_info.rsize > CIFSMaxBufSize) {
1729 cERROR(1,("rsize %d too large, using MaxBufSize",
1730 volume_info.rsize));
1731 cifs_sb->rsize = CIFSMaxBufSize;
1732 } else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1733 cifs_sb->rsize = volume_info.rsize;
1735 cifs_sb->rsize = CIFSMaxBufSize;
1737 if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
1738 cERROR(1,("wsize %d too large using 4096 instead",
1739 volume_info.wsize));
1740 cifs_sb->wsize = 4096;
1741 } else if(volume_info.wsize)
1742 cifs_sb->wsize = volume_info.wsize;
1744 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1745 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1746 cifs_sb->rsize = PAGE_CACHE_SIZE;
1747 /* Windows ME does this */
1748 cFYI(1,("Attempt to set readsize for mount to less than one page (4096)"));
1750 cifs_sb->mnt_uid = volume_info.linux_uid;
1751 cifs_sb->mnt_gid = volume_info.linux_gid;
1752 cifs_sb->mnt_file_mode = volume_info.file_mode;
1753 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1754 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1756 if(volume_info.noperm)
1757 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1758 if(volume_info.setuids)
1759 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1760 if(volume_info.server_ino)
1761 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1762 if(volume_info.remap)
1763 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1764 if(volume_info.no_xattr)
1765 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1766 if(volume_info.sfu_emul)
1767 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1768 if(volume_info.nobrl)
1769 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1771 if(volume_info.direct_io) {
1772 cFYI(1,("mounting share using direct i/o"));
1773 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1777 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1778 volume_info.username);
1780 cFYI(1, ("Found match on UNC path "));
1781 /* we can have only one retry value for a connection
1782 to a share so for resources mounted more than once
1783 to the same server share the last value passed in
1784 for the retry flag is used */
1785 tcon->retry = volume_info.retry;
1786 tcon->nocase = volume_info.nocase;
1788 tcon = tconInfoAlloc();
1792 /* check for null share name ie connect to dfs root */
1794 /* BB check if this works for exactly length three strings */
1795 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1796 && (strchr(volume_info.UNC + 3, '/') ==
1798 rc = connect_to_dfs_path(xid, pSesInfo,
1799 "", cifs_sb->local_nls,
1800 cifs_sb->mnt_cifs_flags &
1801 CIFS_MOUNT_MAP_SPECIAL_CHR);
1802 kfree(volume_info.UNC);
1806 rc = CIFSTCon(xid, pSesInfo,
1808 tcon, cifs_sb->local_nls);
1809 cFYI(1, ("CIFS Tcon rc = %d", rc));
1812 atomic_inc(&pSesInfo->inUse);
1813 tcon->retry = volume_info.retry;
1814 tcon->nocase = volume_info.nocase;
1820 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1821 sb->s_maxbytes = (u64) 1 << 63;
1823 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1826 sb->s_time_gran = 100;
1828 /* on error free sesinfo and tcon struct if needed */
1830 /* if session setup failed, use count is zero but
1831 we still need to free cifsd thread */
1832 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1833 spin_lock(&GlobalMid_Lock);
1834 srvTcp->tcpStatus = CifsExiting;
1835 spin_unlock(&GlobalMid_Lock);
1837 send_sig(SIGKILL,srvTcp->tsk,1);
1838 wait_for_completion(&cifsd_complete);
1841 /* If find_unc succeeded then rc == 0 so we can not end */
1842 if (tcon) /* up accidently freeing someone elses tcon struct */
1844 if (existingCifsSes == NULL) {
1846 if ((pSesInfo->server) &&
1847 (pSesInfo->status == CifsGood)) {
1849 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1850 /* if the socketUseCount is now zero */
1851 if((temp_rc == -ESHUTDOWN) &&
1852 (pSesInfo->server->tsk)) {
1853 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1854 wait_for_completion(&cifsd_complete);
1857 cFYI(1, ("No session or bad tcon"));
1858 sesInfoFree(pSesInfo);
1859 /* pSesInfo = NULL; */
1863 atomic_inc(&tcon->useCount);
1864 cifs_sb->tcon = tcon;
1865 tcon->ses = pSesInfo;
1867 /* do not care if following two calls succeed - informational only */
1868 CIFSSMBQFSDeviceInfo(xid, tcon);
1869 CIFSSMBQFSAttributeInfo(xid, tcon);
1870 if (tcon->ses->capabilities & CAP_UNIX) {
1871 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1872 if(!volume_info.no_psx_acl) {
1873 if(CIFS_UNIX_POSIX_ACL_CAP &
1874 le64_to_cpu(tcon->fsUnixInfo.Capability))
1875 cFYI(1,("server negotiated posix acl support"));
1876 sb->s_flags |= MS_POSIXACL;
1879 /* Try and negotiate POSIX pathnames if we can. */
1880 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
1881 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1882 if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
1883 cFYI(1,("negotiated posix pathnames support"));
1884 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
1886 cFYI(1,("posix pathnames support requested but not supported"));
1891 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
1892 cifs_sb->wsize = min(cifs_sb->wsize,
1893 (tcon->ses->server->maxBuf -
1894 MAX_CIFS_HDR_SIZE));
1895 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
1896 cifs_sb->rsize = min(cifs_sb->rsize,
1897 (tcon->ses->server->maxBuf -
1898 MAX_CIFS_HDR_SIZE));
1901 /* volume_info.password is freed above when existing session found
1902 (in which case it is not needed anymore) but when new sesion is created
1903 the password ptr is put in the new session structure (in which case the
1904 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((__le16 *) 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((__le16 *) bcc_ptr,
1997 "CIFS_LINUX_DOM", 32, nls_codepage);
2000 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2002 bcc_ptr += 2 * bytes_returned;
2005 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2007 bcc_ptr += 2 * bytes_returned;
2009 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
2011 bcc_ptr += 2 * bytes_returned;
2014 cifs_strtoUCS((__le16 *) 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 = kzalloc(2 * (len + 1), GFP_KERNEL);
2081 if(ses->serverOS == NULL)
2082 goto sesssetup_nomem;
2083 cifs_strfromUCS_le(ses->serverOS,
2084 (__le16 *)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 = kzalloc(2 * (len + 1),GFP_KERNEL);
2093 if(ses->serverNOS == NULL)
2094 goto sesssetup_nomem;
2095 cifs_strfromUCS_le(ses->serverNOS,
2096 (__le16 *)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 kzalloc(2*(len+1),GFP_KERNEL);
2111 if(ses->serverDomain == NULL)
2112 goto sesssetup_nomem;
2113 cifs_strfromUCS_le(ses->serverDomain,
2114 (__le16 *)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 kzalloc(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 kzalloc(2, GFP_KERNEL);
2129 kzalloc(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 = kzalloc(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 = kzalloc(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 = kzalloc(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((__le16 *) 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((__le16 *) bcc_ptr,
2264 "CIFS_LINUX_DOM", 32, nls_codepage);
2267 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2269 bcc_ptr += 2 * bytes_returned;
2272 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2274 bcc_ptr += 2 * bytes_returned;
2276 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2278 bcc_ptr += 2 * bytes_returned;
2281 cifs_strtoUCS((__le16 *) 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 kzalloc(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 kzalloc(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 = kzalloc(2*(len+1),GFP_KERNEL);
2386 cifs_strfromUCS_le(ses->serverDomain,
2389 bcc_ptr += 2*(len+1);
2390 ses->serverDomain[2*len] = 0;
2391 ses->serverDomain[1+(2*len)] = 0;
2392 } /* else no more room so create dummy domain string */
2395 kzalloc(2,GFP_KERNEL);
2396 } else { /* no room so create dummy domain and NOS string */
2397 ses->serverDomain = kzalloc(2, GFP_KERNEL);
2398 ses->serverNOS = kzalloc(2, GFP_KERNEL);
2400 } else { /* ASCII */
2402 len = strnlen(bcc_ptr, 1024);
2403 if (((long) bcc_ptr + len) - (long)
2404 pByteArea(smb_buffer_response)
2405 <= BCC(smb_buffer_response)) {
2406 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
2407 strncpy(ses->serverOS, bcc_ptr, len);
2410 bcc_ptr[0] = 0; /* null terminate the string */
2413 len = strnlen(bcc_ptr, 1024);
2414 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2415 strncpy(ses->serverNOS, bcc_ptr, len);
2420 len = strnlen(bcc_ptr, 1024);
2421 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
2422 strncpy(ses->serverDomain, bcc_ptr, len);
2428 ("Variable field of length %d extends beyond end of smb ",
2433 (" Security Blob Length extends beyond end of SMB"));
2436 cERROR(1, ("No session structure passed in."));
2440 (" Invalid Word count %d: ",
2441 smb_buffer_response->WordCount));
2446 cifs_buf_release(smb_buffer);
2452 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2453 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2454 const struct nls_table *nls_codepage)
2456 struct smb_hdr *smb_buffer;
2457 struct smb_hdr *smb_buffer_response;
2458 SESSION_SETUP_ANDX *pSMB;
2459 SESSION_SETUP_ANDX *pSMBr;
2463 int remaining_words = 0;
2464 int bytes_returned = 0;
2466 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2467 PNEGOTIATE_MESSAGE SecurityBlob;
2468 PCHALLENGE_MESSAGE SecurityBlob2;
2469 __u32 negotiate_flags, capabilities;
2472 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2475 domain = ses->domainName;
2476 *pNTLMv2_flag = FALSE;
2477 smb_buffer = cifs_buf_get();
2478 if (smb_buffer == NULL) {
2481 smb_buffer_response = smb_buffer;
2482 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2483 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2485 /* send SMBsessionSetup here */
2486 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2487 NULL /* no tCon exists yet */ , 12 /* wct */ );
2489 smb_buffer->Mid = GetNextMid(ses->server);
2490 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2491 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2493 pSMB->req.AndXCommand = 0xFF;
2494 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2495 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2497 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2498 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2500 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2501 CAP_EXTENDED_SECURITY;
2502 if (ses->capabilities & CAP_UNICODE) {
2503 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2504 capabilities |= CAP_UNICODE;
2506 if (ses->capabilities & CAP_STATUS32) {
2507 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2508 capabilities |= CAP_STATUS32;
2510 if (ses->capabilities & CAP_DFS) {
2511 smb_buffer->Flags2 |= SMBFLG2_DFS;
2512 capabilities |= CAP_DFS;
2514 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2516 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2517 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2518 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2519 SecurityBlob->MessageType = NtLmNegotiate;
2521 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2522 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2523 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2525 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2527 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2528 /* setup pointers to domain name and workstation name */
2529 bcc_ptr += SecurityBlobLength;
2531 SecurityBlob->WorkstationName.Buffer = 0;
2532 SecurityBlob->WorkstationName.Length = 0;
2533 SecurityBlob->WorkstationName.MaximumLength = 0;
2535 if (domain == NULL) {
2536 SecurityBlob->DomainName.Buffer = 0;
2537 SecurityBlob->DomainName.Length = 0;
2538 SecurityBlob->DomainName.MaximumLength = 0;
2541 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2542 strncpy(bcc_ptr, domain, 63);
2543 len = strnlen(domain, 64);
2544 SecurityBlob->DomainName.MaximumLength =
2546 SecurityBlob->DomainName.Buffer =
2547 cpu_to_le32((long) &SecurityBlob->
2549 (long) &SecurityBlob->Signature);
2551 SecurityBlobLength += len;
2552 SecurityBlob->DomainName.Length =
2555 if (ses->capabilities & CAP_UNICODE) {
2556 if ((long) bcc_ptr % 2) {
2562 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2564 bcc_ptr += 2 * bytes_returned;
2566 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2568 bcc_ptr += 2 * bytes_returned;
2569 bcc_ptr += 2; /* null terminate Linux version */
2571 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2573 bcc_ptr += 2 * bytes_returned;
2576 bcc_ptr += 2; /* null terminate network opsys string */
2579 bcc_ptr += 2; /* null domain */
2580 } else { /* ASCII */
2581 strcpy(bcc_ptr, "Linux version ");
2582 bcc_ptr += strlen("Linux version ");
2583 strcpy(bcc_ptr, system_utsname.release);
2584 bcc_ptr += strlen(system_utsname.release) + 1;
2585 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2586 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2587 bcc_ptr++; /* empty domain field */
2590 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2591 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2592 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2593 smb_buffer->smb_buf_length += count;
2594 pSMB->req.ByteCount = cpu_to_le16(count);
2596 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2597 &bytes_returned, 1);
2599 if (smb_buffer_response->Status.CifsError ==
2600 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2604 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2605 } else if ((smb_buffer_response->WordCount == 3)
2606 || (smb_buffer_response->WordCount == 4)) {
2607 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2608 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2610 if (action & GUEST_LOGIN)
2611 cFYI(1, (" Guest login"));
2612 /* Do we want to set anything in SesInfo struct when guest login? */
2614 bcc_ptr = pByteArea(smb_buffer_response);
2615 /* response can have either 3 or 4 word count - Samba sends 3 */
2617 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2618 if (SecurityBlob2->MessageType != NtLmChallenge) {
2620 ("Unexpected NTLMSSP message type received %d",
2621 SecurityBlob2->MessageType));
2623 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2624 cFYI(1, ("UID = %d ", ses->Suid));
2625 if ((pSMBr->resp.hdr.WordCount == 3)
2626 || ((pSMBr->resp.hdr.WordCount == 4)
2628 pSMBr->resp.ByteCount))) {
2630 if (pSMBr->resp.hdr.WordCount == 4) {
2631 bcc_ptr += blob_len;
2633 ("Security Blob Length %d ",
2637 cFYI(1, ("NTLMSSP Challenge rcvd "));
2639 memcpy(ses->server->cryptKey,
2640 SecurityBlob2->Challenge,
2641 CIFS_CRYPTO_KEY_SIZE);
2642 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2643 *pNTLMv2_flag = TRUE;
2645 if((SecurityBlob2->NegotiateFlags &
2646 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2647 || (sign_CIFS_PDUs > 1))
2648 ses->server->secMode |=
2649 SECMODE_SIGN_REQUIRED;
2650 if ((SecurityBlob2->NegotiateFlags &
2651 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2652 ses->server->secMode |=
2653 SECMODE_SIGN_ENABLED;
2655 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2656 if ((long) (bcc_ptr) % 2) {
2658 (BCC(smb_buffer_response)
2660 bcc_ptr++; /* Unicode strings must be word aligned */
2664 (smb_buffer_response) / 2;
2667 UniStrnlen((wchar_t *) bcc_ptr,
2668 remaining_words - 1);
2669 /* We look for obvious messed up bcc or strings in response so we do not go off
2670 the end since (at least) WIN2K and Windows XP have a major bug in not null
2671 terminating last Unicode string in response */
2673 kzalloc(2 * (len + 1), GFP_KERNEL);
2674 cifs_strfromUCS_le(ses->serverOS,
2678 bcc_ptr += 2 * (len + 1);
2679 remaining_words -= len + 1;
2680 ses->serverOS[2 * len] = 0;
2681 ses->serverOS[1 + (2 * len)] = 0;
2682 if (remaining_words > 0) {
2683 len = UniStrnlen((wchar_t *)
2688 kzalloc(2 * (len + 1),
2690 cifs_strfromUCS_le(ses->
2696 bcc_ptr += 2 * (len + 1);
2697 ses->serverNOS[2 * len] = 0;
2700 remaining_words -= len + 1;
2701 if (remaining_words > 0) {
2702 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2703 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2715 ses->serverDomain[2*len]
2720 } /* else no more room so create dummy domain string */
2725 } else { /* no room so create dummy domain and NOS string */
2727 kzalloc(2, GFP_KERNEL);
2729 kzalloc(2, GFP_KERNEL);
2731 } else { /* ASCII */
2732 len = strnlen(bcc_ptr, 1024);
2733 if (((long) bcc_ptr + len) - (long)
2734 pByteArea(smb_buffer_response)
2735 <= BCC(smb_buffer_response)) {
2739 strncpy(ses->serverOS,
2743 bcc_ptr[0] = 0; /* null terminate string */
2746 len = strnlen(bcc_ptr, 1024);
2750 strncpy(ses->serverNOS, bcc_ptr, len);
2755 len = strnlen(bcc_ptr, 1024);
2759 strncpy(ses->serverDomain, bcc_ptr, len);
2765 ("Variable field of length %d extends beyond end of smb ",
2770 (" Security Blob Length extends beyond end of SMB"));
2773 cERROR(1, ("No session structure passed in."));
2777 (" Invalid Word count %d: ",
2778 smb_buffer_response->WordCount));
2783 cifs_buf_release(smb_buffer);
2788 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2789 char *ntlm_session_key, int ntlmv2_flag,
2790 const struct nls_table *nls_codepage)
2792 struct smb_hdr *smb_buffer;
2793 struct smb_hdr *smb_buffer_response;
2794 SESSION_SETUP_ANDX *pSMB;
2795 SESSION_SETUP_ANDX *pSMBr;
2800 int remaining_words = 0;
2801 int bytes_returned = 0;
2803 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2804 PAUTHENTICATE_MESSAGE SecurityBlob;
2805 __u32 negotiate_flags, capabilities;
2808 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2811 user = ses->userName;
2812 domain = ses->domainName;
2813 smb_buffer = cifs_buf_get();
2814 if (smb_buffer == NULL) {
2817 smb_buffer_response = smb_buffer;
2818 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2819 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2821 /* send SMBsessionSetup here */
2822 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2823 NULL /* no tCon exists yet */ , 12 /* wct */ );
2825 smb_buffer->Mid = GetNextMid(ses->server);
2826 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2827 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2828 pSMB->req.AndXCommand = 0xFF;
2829 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2830 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2832 pSMB->req.hdr.Uid = ses->Suid;
2834 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2835 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2837 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2838 CAP_EXTENDED_SECURITY;
2839 if (ses->capabilities & CAP_UNICODE) {
2840 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2841 capabilities |= CAP_UNICODE;
2843 if (ses->capabilities & CAP_STATUS32) {
2844 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2845 capabilities |= CAP_STATUS32;
2847 if (ses->capabilities & CAP_DFS) {
2848 smb_buffer->Flags2 |= SMBFLG2_DFS;
2849 capabilities |= CAP_DFS;
2851 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2853 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2854 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2855 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2856 SecurityBlob->MessageType = NtLmAuthenticate;
2857 bcc_ptr += SecurityBlobLength;
2859 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2860 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2861 0x80000000 | NTLMSSP_NEGOTIATE_128;
2863 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2865 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2867 /* setup pointers to domain name and workstation name */
2869 SecurityBlob->WorkstationName.Buffer = 0;
2870 SecurityBlob->WorkstationName.Length = 0;
2871 SecurityBlob->WorkstationName.MaximumLength = 0;
2872 SecurityBlob->SessionKey.Length = 0;
2873 SecurityBlob->SessionKey.MaximumLength = 0;
2874 SecurityBlob->SessionKey.Buffer = 0;
2876 SecurityBlob->LmChallengeResponse.Length = 0;
2877 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2878 SecurityBlob->LmChallengeResponse.Buffer = 0;
2880 SecurityBlob->NtChallengeResponse.Length =
2881 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2882 SecurityBlob->NtChallengeResponse.MaximumLength =
2883 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2884 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2885 SecurityBlob->NtChallengeResponse.Buffer =
2886 cpu_to_le32(SecurityBlobLength);
2887 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2888 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2890 if (ses->capabilities & CAP_UNICODE) {
2891 if (domain == NULL) {
2892 SecurityBlob->DomainName.Buffer = 0;
2893 SecurityBlob->DomainName.Length = 0;
2894 SecurityBlob->DomainName.MaximumLength = 0;
2897 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2900 SecurityBlob->DomainName.MaximumLength =
2902 SecurityBlob->DomainName.Buffer =
2903 cpu_to_le32(SecurityBlobLength);
2905 SecurityBlobLength += len;
2906 SecurityBlob->DomainName.Length =
2910 SecurityBlob->UserName.Buffer = 0;
2911 SecurityBlob->UserName.Length = 0;
2912 SecurityBlob->UserName.MaximumLength = 0;
2915 cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
2918 SecurityBlob->UserName.MaximumLength =
2920 SecurityBlob->UserName.Buffer =
2921 cpu_to_le32(SecurityBlobLength);
2923 SecurityBlobLength += len;
2924 SecurityBlob->UserName.Length =
2928 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
2929 SecurityBlob->WorkstationName.Length *= 2;
2930 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2931 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2932 bcc_ptr += SecurityBlob->WorkstationName.Length;
2933 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2934 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2936 if ((long) bcc_ptr % 2) {
2941 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2943 bcc_ptr += 2 * bytes_returned;
2945 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2947 bcc_ptr += 2 * bytes_returned;
2948 bcc_ptr += 2; /* null term version string */
2950 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2952 bcc_ptr += 2 * bytes_returned;
2955 bcc_ptr += 2; /* null terminate network opsys string */
2958 bcc_ptr += 2; /* null domain */
2959 } else { /* ASCII */
2960 if (domain == NULL) {
2961 SecurityBlob->DomainName.Buffer = 0;
2962 SecurityBlob->DomainName.Length = 0;
2963 SecurityBlob->DomainName.MaximumLength = 0;
2966 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2967 strncpy(bcc_ptr, domain, 63);
2968 len = strnlen(domain, 64);
2969 SecurityBlob->DomainName.MaximumLength =
2971 SecurityBlob->DomainName.Buffer =
2972 cpu_to_le32(SecurityBlobLength);
2974 SecurityBlobLength += len;
2975 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2978 SecurityBlob->UserName.Buffer = 0;
2979 SecurityBlob->UserName.Length = 0;
2980 SecurityBlob->UserName.MaximumLength = 0;
2983 strncpy(bcc_ptr, user, 63);
2984 len = strnlen(user, 64);
2985 SecurityBlob->UserName.MaximumLength =
2987 SecurityBlob->UserName.Buffer =
2988 cpu_to_le32(SecurityBlobLength);
2990 SecurityBlobLength += len;
2991 SecurityBlob->UserName.Length = cpu_to_le16(len);
2993 /* BB fill in our workstation name if known BB */
2995 strcpy(bcc_ptr, "Linux version ");
2996 bcc_ptr += strlen("Linux version ");
2997 strcpy(bcc_ptr, system_utsname.release);
2998 bcc_ptr += strlen(system_utsname.release) + 1;
2999 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3000 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3001 bcc_ptr++; /* null domain */
3004 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3005 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3006 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3007 smb_buffer->smb_buf_length += count;
3008 pSMB->req.ByteCount = cpu_to_le16(count);
3010 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3011 &bytes_returned, 1);
3013 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
3014 } else if ((smb_buffer_response->WordCount == 3)
3015 || (smb_buffer_response->WordCount == 4)) {
3016 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3018 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3019 if (action & GUEST_LOGIN)
3020 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
3021 /* if(SecurityBlob2->MessageType != NtLm??){
3022 cFYI("Unexpected message type on auth response is %d "));
3026 ("Does UID on challenge %d match auth response UID %d ",
3027 ses->Suid, smb_buffer_response->Uid));
3028 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
3029 bcc_ptr = pByteArea(smb_buffer_response);
3030 /* response can have either 3 or 4 word count - Samba sends 3 */
3031 if ((pSMBr->resp.hdr.WordCount == 3)
3032 || ((pSMBr->resp.hdr.WordCount == 4)
3034 pSMBr->resp.ByteCount))) {
3035 if (pSMBr->resp.hdr.WordCount == 4) {
3039 ("Security Blob Length %d ",
3044 ("NTLMSSP response to Authenticate "));
3046 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3047 if ((long) (bcc_ptr) % 2) {
3049 (BCC(smb_buffer_response)
3051 bcc_ptr++; /* Unicode strings must be word aligned */
3053 remaining_words = BCC(smb_buffer_response) / 2;
3056 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
3057 /* We look for obvious messed up bcc or strings in response so we do not go off
3058 the end since (at least) WIN2K and Windows XP have a major bug in not null
3059 terminating last Unicode string in response */
3061 kzalloc(2 * (len + 1), GFP_KERNEL);
3062 cifs_strfromUCS_le(ses->serverOS,
3066 bcc_ptr += 2 * (len + 1);
3067 remaining_words -= len + 1;
3068 ses->serverOS[2 * len] = 0;
3069 ses->serverOS[1 + (2 * len)] = 0;
3070 if (remaining_words > 0) {
3071 len = UniStrnlen((wchar_t *)
3076 kzalloc(2 * (len + 1),
3078 cifs_strfromUCS_le(ses->
3084 bcc_ptr += 2 * (len + 1);
3085 ses->serverNOS[2 * len] = 0;
3086 ses->serverNOS[1+(2*len)] = 0;
3087 remaining_words -= len + 1;
3088 if (remaining_words > 0) {
3089 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3090 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3115 } /* else no more room so create dummy domain string */
3117 ses->serverDomain = kzalloc(2,GFP_KERNEL);
3118 } else { /* no room so create dummy domain and NOS string */
3119 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3120 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3122 } else { /* ASCII */
3123 len = strnlen(bcc_ptr, 1024);
3124 if (((long) bcc_ptr + len) -
3125 (long) pByteArea(smb_buffer_response)
3126 <= BCC(smb_buffer_response)) {
3127 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
3128 strncpy(ses->serverOS,bcc_ptr, len);
3131 bcc_ptr[0] = 0; /* null terminate the string */
3134 len = strnlen(bcc_ptr, 1024);
3135 ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
3136 strncpy(ses->serverNOS, bcc_ptr, len);
3141 len = strnlen(bcc_ptr, 1024);
3142 ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
3143 strncpy(ses->serverDomain, bcc_ptr, len);
3149 ("Variable field of length %d extends beyond end of smb ",
3154 (" Security Blob Length extends beyond end of SMB"));
3157 cERROR(1, ("No session structure passed in."));
3161 (" Invalid Word count %d: ",
3162 smb_buffer_response->WordCount));
3167 cifs_buf_release(smb_buffer);
3173 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3174 const char *tree, struct cifsTconInfo *tcon,
3175 const struct nls_table *nls_codepage)
3177 struct smb_hdr *smb_buffer;
3178 struct smb_hdr *smb_buffer_response;
3181 unsigned char *bcc_ptr;
3189 smb_buffer = cifs_buf_get();
3190 if (smb_buffer == NULL) {
3193 smb_buffer_response = smb_buffer;
3195 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3196 NULL /*no tid */ , 4 /*wct */ );
3198 smb_buffer->Mid = GetNextMid(ses->server);
3199 smb_buffer->Uid = ses->Suid;
3200 pSMB = (TCONX_REQ *) smb_buffer;
3201 pSMBr = (TCONX_RSP *) smb_buffer_response;
3203 pSMB->AndXCommand = 0xFF;
3204 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3205 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3206 bcc_ptr = &pSMB->Password[0];
3207 bcc_ptr++; /* skip password */
3209 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3210 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3212 if (ses->capabilities & CAP_STATUS32) {
3213 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3215 if (ses->capabilities & CAP_DFS) {
3216 smb_buffer->Flags2 |= SMBFLG2_DFS;
3218 if (ses->capabilities & CAP_UNICODE) {
3219 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3221 cifs_strtoUCS((__le16 *) bcc_ptr, tree, 100, nls_codepage);
3222 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3223 bcc_ptr += 2; /* skip trailing null */
3224 } else { /* ASCII */
3226 strcpy(bcc_ptr, tree);
3227 bcc_ptr += strlen(tree) + 1;
3229 strcpy(bcc_ptr, "?????");
3230 bcc_ptr += strlen("?????");
3232 count = bcc_ptr - &pSMB->Password[0];
3233 pSMB->hdr.smb_buf_length += count;
3234 pSMB->ByteCount = cpu_to_le16(count);
3236 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3238 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3239 /* above now done in SendReceive */
3240 if ((rc == 0) && (tcon != NULL)) {
3241 tcon->tidStatus = CifsGood;
3242 tcon->tid = smb_buffer_response->Tid;
3243 bcc_ptr = pByteArea(smb_buffer_response);
3244 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3245 /* skip service field (NB: this field is always ASCII) */
3246 bcc_ptr += length + 1;
3247 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3248 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3249 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3250 if ((bcc_ptr + (2 * length)) -
3251 pByteArea(smb_buffer_response) <=
3252 BCC(smb_buffer_response)) {
3253 kfree(tcon->nativeFileSystem);
3254 tcon->nativeFileSystem =
3255 kzalloc(length + 2, GFP_KERNEL);
3256 cifs_strfromUCS_le(tcon->nativeFileSystem,
3258 length, nls_codepage);
3259 bcc_ptr += 2 * length;
3260 bcc_ptr[0] = 0; /* null terminate the string */
3264 /* else do not bother copying these informational fields */
3266 length = strnlen(bcc_ptr, 1024);
3267 if ((bcc_ptr + length) -
3268 pByteArea(smb_buffer_response) <=
3269 BCC(smb_buffer_response)) {
3270 kfree(tcon->nativeFileSystem);
3271 tcon->nativeFileSystem =
3272 kzalloc(length + 1, GFP_KERNEL);
3273 strncpy(tcon->nativeFileSystem, bcc_ptr,
3276 /* else do not bother copying these informational fields */
3278 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3279 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3280 } else if ((rc == 0) && tcon == NULL) {
3281 /* all we need to save for IPC$ connection */
3282 ses->ipc_tid = smb_buffer_response->Tid;
3286 cifs_buf_release(smb_buffer);
3291 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3295 struct cifsSesInfo *ses = NULL;
3296 struct task_struct *cifsd_task;
3300 if (cifs_sb->tcon) {
3301 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3302 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3307 tconInfoFree(cifs_sb->tcon);
3308 if ((ses) && (ses->server)) {
3309 /* save off task so we do not refer to ses later */
3310 cifsd_task = ses->server->tsk;
3311 cFYI(1, ("About to do SMBLogoff "));
3312 rc = CIFSSMBLogoff(xid, ses);
3316 } else if (rc == -ESHUTDOWN) {
3317 cFYI(1,("Waking up socket by sending it signal"));
3319 send_sig(SIGKILL,cifsd_task,1);
3320 wait_for_completion(&cifsd_complete);
3323 } /* else - we have an smb session
3324 left on this socket do not kill cifsd */
3326 cFYI(1, ("No session or bad tcon"));
3329 cifs_sb->tcon = NULL;
3331 schedule_timeout_interruptible(msecs_to_jiffies(500));
3336 return rc; /* BB check if we should always return zero here */
3339 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3340 struct nls_table * nls_info)
3343 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3344 int ntlmv2_flag = FALSE;
3347 /* what if server changes its buffer size after dropping the session? */
3348 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3349 rc = CIFSSMBNegotiate(xid, pSesInfo);
3350 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3351 rc = CIFSSMBNegotiate(xid, pSesInfo);
3356 spin_lock(&GlobalMid_Lock);
3357 if(pSesInfo->server->tcpStatus != CifsExiting)
3358 pSesInfo->server->tcpStatus = CifsGood;
3361 spin_unlock(&GlobalMid_Lock);
3367 pSesInfo->capabilities = pSesInfo->server->capabilities;
3368 if(linuxExtEnabled == 0)
3369 pSesInfo->capabilities &= (~CAP_UNIX);
3370 /* pSesInfo->sequence_number = 0;*/
3371 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3372 pSesInfo->server->secMode,
3373 pSesInfo->server->capabilities,
3374 pSesInfo->server->timeZone));
3375 if (extended_security
3376 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3377 && (pSesInfo->server->secType == NTLMSSP)) {
3378 cFYI(1, ("New style sesssetup "));
3379 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3380 NULL /* security blob */,
3381 0 /* blob length */,
3383 } else if (extended_security
3384 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3385 && (pSesInfo->server->secType == RawNTLMSSP)) {
3386 cFYI(1, ("NTLMSSP sesssetup "));
3387 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3394 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3395 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3400 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3402 CalcNTLMv2_response(pSesInfo,v2_response);
3404 cifs_calculate_ntlmv2_mac_key(
3405 pSesInfo->server->mac_signing_key,
3406 response, ntlm_session_key, */
3408 /* BB Put dummy sig in SessSetup PDU? */
3415 SMBNTencrypt(pSesInfo->password,
3416 pSesInfo->server->cryptKey,
3420 cifs_calculate_mac_key(
3421 pSesInfo->server->mac_signing_key,
3423 pSesInfo->password);
3425 /* for better security the weaker lanman hash not sent
3426 in AuthSessSetup so we no longer calculate it */
3428 rc = CIFSNTLMSSPAuthSessSetup(xid,
3434 } else { /* old style NTLM 0.12 session setup */
3435 SMBNTencrypt(pSesInfo->password,
3436 pSesInfo->server->cryptKey,
3440 cifs_calculate_mac_key(
3441 pSesInfo->server->mac_signing_key,
3442 ntlm_session_key, pSesInfo->password);
3444 rc = CIFSSessSetup(xid, pSesInfo,
3445 ntlm_session_key, nls_info);
3448 cERROR(1,("Send error in SessSetup = %d",rc));
3450 cFYI(1,("CIFS Session Established successfully"));
3451 pSesInfo->status = CifsGood;