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 */
75 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
76 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
77 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
79 unsigned remap:1; /* set to remap seven reserved chars in filenames */
80 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
82 unsigned nocase; /* request case insensitive filenames */
83 unsigned nobrl; /* disable sending byte range locks to srv */
87 unsigned short int port;
90 static int ipv4_connect(struct sockaddr_in *psin_server,
91 struct socket **csocket,
93 static int ipv6_connect(struct sockaddr_in6 *psin_server,
94 struct socket **csocket);
98 * cifs tcp session reconnection
100 * mark tcp session as reconnecting so temporarily locked
101 * mark all smb sessions as reconnecting for tcp session
102 * reconnect tcp session
103 * wake up waiters on reconnection? - (not needed currently)
107 cifs_reconnect(struct TCP_Server_Info *server)
110 struct list_head *tmp;
111 struct cifsSesInfo *ses;
112 struct cifsTconInfo *tcon;
113 struct mid_q_entry * mid_entry;
115 spin_lock(&GlobalMid_Lock);
116 if(server->tcpStatus == CifsExiting) {
117 /* the demux thread will exit normally
118 next time through the loop */
119 spin_unlock(&GlobalMid_Lock);
122 server->tcpStatus = CifsNeedReconnect;
123 spin_unlock(&GlobalMid_Lock);
126 cFYI(1, ("Reconnecting tcp session"));
128 /* before reconnecting the tcp session, mark the smb session (uid)
129 and the tid bad so they are not used until reconnected */
130 read_lock(&GlobalSMBSeslock);
131 list_for_each(tmp, &GlobalSMBSessionList) {
132 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
134 if (ses->server == server) {
135 ses->status = CifsNeedReconnect;
139 /* else tcp and smb sessions need reconnection */
141 list_for_each(tmp, &GlobalTreeConnectionList) {
142 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
143 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
144 tcon->tidStatus = CifsNeedReconnect;
147 read_unlock(&GlobalSMBSeslock);
148 /* do not want to be sending data on a socket we are freeing */
149 down(&server->tcpSem);
150 if(server->ssocket) {
151 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
152 server->ssocket->flags));
153 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
154 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
155 server->ssocket->flags));
156 sock_release(server->ssocket);
157 server->ssocket = NULL;
160 spin_lock(&GlobalMid_Lock);
161 list_for_each(tmp, &server->pending_mid_q) {
162 mid_entry = list_entry(tmp, struct
166 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
167 /* Mark other intransit requests as needing
168 retry so we do not immediately mark the
169 session bad again (ie after we reconnect
170 below) as they timeout too */
171 mid_entry->midState = MID_RETRY_NEEDED;
175 spin_unlock(&GlobalMid_Lock);
178 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
180 if(server->protocolType == IPV6) {
181 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
183 rc = ipv4_connect(&server->addr.sockAddr,
185 server->workstation_RFC1001_name);
190 atomic_inc(&tcpSesReconnectCount);
191 spin_lock(&GlobalMid_Lock);
192 if(server->tcpStatus != CifsExiting)
193 server->tcpStatus = CifsGood;
194 server->sequence_number = 0;
195 spin_unlock(&GlobalMid_Lock);
196 /* atomic_set(&server->inFlight,0);*/
197 wake_up(&server->response_q);
205 0 not a transact2, or all data present
206 >0 transact2 with that much data missing
207 -EINVAL = invalid transact2
210 static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
212 struct smb_t2_rsp * pSMBt;
214 int data_in_this_rsp;
217 if(pSMB->Command != SMB_COM_TRANSACTION2)
220 /* check for plausible wct, bcc and t2 data and parm sizes */
221 /* check for parm and data offset going beyond end of smb */
222 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
223 cFYI(1,("invalid transact2 word count"));
227 pSMBt = (struct smb_t2_rsp *)pSMB;
229 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
230 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
232 remaining = total_data_size - data_in_this_rsp;
236 else if(remaining < 0) {
237 cFYI(1,("total data %d smaller than data in frame %d",
238 total_data_size, data_in_this_rsp));
241 cFYI(1,("missing %d bytes from transact2, check next response",
243 if(total_data_size > maxBufSize) {
244 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
245 total_data_size,maxBufSize));
252 static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
254 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
255 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
260 char * data_area_of_target;
261 char * data_area_of_buf2;
264 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
266 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
267 cFYI(1,("total data sizes of primary and secondary t2 differ"));
270 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
272 remaining = total_data_size - total_in_buf;
277 if(remaining == 0) /* nothing to do, ignore */
280 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
281 if(remaining < total_in_buf2) {
282 cFYI(1,("transact2 2nd response contains too much data"));
285 /* find end of first SMB data area */
286 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
287 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
288 /* validate target area */
290 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
291 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
293 data_area_of_target += total_in_buf;
295 /* copy second buffer into end of first buffer */
296 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
297 total_in_buf += total_in_buf2;
298 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
299 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
300 byte_count += total_in_buf2;
301 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
303 byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
304 byte_count += total_in_buf2;
306 /* BB also add check that we are not beyond maximum buffer size */
308 pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
310 if(remaining == total_in_buf2) {
311 cFYI(1,("found the last secondary response"));
312 return 0; /* we are done */
313 } else /* more responses to go */
319 cifs_demultiplex_thread(struct TCP_Server_Info *server)
322 unsigned int pdu_length, total_read;
323 struct smb_hdr *smb_buffer = NULL;
324 struct smb_hdr *bigbuf = NULL;
325 struct smb_hdr *smallbuf = NULL;
326 struct msghdr smb_msg;
328 struct socket *csocket = server->ssocket;
329 struct list_head *tmp;
330 struct cifsSesInfo *ses;
331 struct task_struct *task_to_wake = NULL;
332 struct mid_q_entry *mid_entry;
334 int isLargeBuf = FALSE;
339 allow_signal(SIGKILL);
340 current->flags |= PF_MEMALLOC;
341 server->tsk = current; /* save process info to wake at shutdown */
342 cFYI(1, ("Demultiplex PID: %d", current->pid));
343 write_lock(&GlobalSMBSeslock);
344 atomic_inc(&tcpSesAllocCount);
345 length = tcpSesAllocCount.counter;
346 write_unlock(&GlobalSMBSeslock);
347 complete(&cifsd_complete);
349 mempool_resize(cifs_req_poolp,
350 length + cifs_min_rcv,
354 while (server->tcpStatus != CifsExiting) {
355 if (bigbuf == NULL) {
356 bigbuf = cifs_buf_get();
358 cERROR(1,("No memory for large SMB response"));
360 /* retry will check if exiting */
363 } else if(isLargeBuf) {
364 /* we are reusing a dirtry large buf, clear its start */
365 memset(bigbuf, 0, sizeof (struct smb_hdr));
368 if (smallbuf == NULL) {
369 smallbuf = cifs_small_buf_get();
370 if(smallbuf == NULL) {
371 cERROR(1,("No memory for SMB response"));
373 /* retry will check if exiting */
376 /* beginning of smb buffer is cleared in our buf_get */
377 } else /* if existing small buf clear beginning */
378 memset(smallbuf, 0, sizeof (struct smb_hdr));
382 smb_buffer = smallbuf;
383 iov.iov_base = smb_buffer;
385 smb_msg.msg_control = NULL;
386 smb_msg.msg_controllen = 0;
388 kernel_recvmsg(csocket, &smb_msg,
389 &iov, 1, 4, 0 /* BB see socket.h flags */);
391 if(server->tcpStatus == CifsExiting) {
393 } else if (server->tcpStatus == CifsNeedReconnect) {
394 cFYI(1,("Reconnect after server stopped responding"));
395 cifs_reconnect(server);
396 cFYI(1,("call to reconnect done"));
397 csocket = server->ssocket;
399 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
400 msleep(1); /* minimum sleep to prevent looping
401 allowing socket to clear and app threads to set
402 tcpStatus CifsNeedReconnect if server hung */
404 } else if (length <= 0) {
405 if(server->tcpStatus == CifsNew) {
406 cFYI(1,("tcp session abend after SMBnegprot"));
407 /* some servers kill the TCP session rather than
408 returning an SMB negprot error, in which
409 case reconnecting here is not going to help,
410 and so simply return error to mount */
413 if(length == -EINTR) {
414 cFYI(1,("cifsd thread killed"));
417 cFYI(1,("Reconnect after unexpected peek error %d",
419 cifs_reconnect(server);
420 csocket = server->ssocket;
421 wake_up(&server->response_q);
423 } else if (length < 4) {
425 ("Frame under four bytes received (%d bytes long)",
427 cifs_reconnect(server);
428 csocket = server->ssocket;
429 wake_up(&server->response_q);
433 /* the right amount was read from socket - 4 bytes */
435 pdu_length = ntohl(smb_buffer->smb_buf_length);
436 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
438 temp = (char *) smb_buffer;
439 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
441 } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
442 cFYI(1,("Good RFC 1002 session rsp"));
444 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
445 /* we get this from Windows 98 instead of
446 an error on SMB negprot response */
447 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
449 if(server->tcpStatus == CifsNew) {
450 /* if nack on negprot (rather than
451 ret of smb negprot error) reconnecting
452 not going to help, ret error to mount */
455 /* give server a second to
456 clean up before reconnect attempt */
458 /* always try 445 first on reconnect
459 since we get NACK on some if we ever
460 connected to port 139 (the NACK is
461 since we do not begin with RFC1001
462 session initialize frame) */
463 server->addr.sockAddr.sin_port =
465 cifs_reconnect(server);
466 csocket = server->ssocket;
467 wake_up(&server->response_q);
470 } else if (temp[0] != (char) 0) {
471 cERROR(1,("Unknown RFC 1002 frame"));
472 cifs_dump_mem(" Received Data: ", temp, length);
473 cifs_reconnect(server);
474 csocket = server->ssocket;
478 /* else we have an SMB response */
479 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
480 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
481 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
482 length, pdu_length+4));
483 cifs_reconnect(server);
484 csocket = server->ssocket;
485 wake_up(&server->response_q);
492 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
494 memcpy(bigbuf, smallbuf, 4);
498 iov.iov_base = 4 + (char *)smb_buffer;
499 iov.iov_len = pdu_length;
500 for (total_read = 0; total_read < pdu_length;
501 total_read += length) {
502 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
503 pdu_length - total_read, 0);
504 if((server->tcpStatus == CifsExiting) ||
505 (length == -EINTR)) {
509 } else if (server->tcpStatus == CifsNeedReconnect) {
510 cifs_reconnect(server);
511 csocket = server->ssocket;
512 /* Reconnect wakes up rspns q */
513 /* Now we will reread sock */
516 } else if ((length == -ERESTARTSYS) ||
517 (length == -EAGAIN)) {
518 msleep(1); /* minimum sleep to prevent looping,
519 allowing socket to clear and app
520 threads to set tcpStatus
521 CifsNeedReconnect if server hung*/
523 } else if (length <= 0) {
524 cERROR(1,("Received no data, expecting %d",
525 pdu_length - total_read));
526 cifs_reconnect(server);
527 csocket = server->ssocket;
534 else if(reconnect == 1)
537 length += 4; /* account for rfc1002 hdr */
540 dump_smb(smb_buffer, length);
541 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
542 cERROR(1, ("Bad SMB Received "));
548 spin_lock(&GlobalMid_Lock);
549 list_for_each(tmp, &server->pending_mid_q) {
550 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
552 if ((mid_entry->mid == smb_buffer->Mid) &&
553 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
554 (mid_entry->command == smb_buffer->Command)) {
555 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
556 /* We have a multipart transact2 resp */
558 if(mid_entry->resp_buf) {
559 /* merge response - fix up 1st*/
560 if(coalesce_t2(smb_buffer,
561 mid_entry->resp_buf)) {
564 /* all parts received */
569 cERROR(1,("1st trans2 resp needs bigbuf"));
570 /* BB maybe we can fix this up, switch
571 to already allocated large buffer? */
573 /* Have first buffer */
574 mid_entry->resp_buf =
576 mid_entry->largeBuf = 1;
582 mid_entry->resp_buf = smb_buffer;
584 mid_entry->largeBuf = 1;
586 mid_entry->largeBuf = 0;
588 task_to_wake = mid_entry->tsk;
589 mid_entry->midState = MID_RESPONSE_RECEIVED;
593 spin_unlock(&GlobalMid_Lock);
595 /* Was previous buf put in mpx struct for multi-rsp? */
597 /* smb buffer will be freed by user thread */
603 wake_up_process(task_to_wake);
604 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
605 && (isMultiRsp == FALSE)) {
606 cERROR(1, ("No task to wake, unknown frame rcvd!"));
607 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
609 } /* end while !EXITING */
611 spin_lock(&GlobalMid_Lock);
612 server->tcpStatus = CifsExiting;
614 /* check if we have blocked requests that need to free */
615 /* Note that cifs_max_pending is normally 50, but
616 can be set at module install time to as little as two */
617 if(atomic_read(&server->inFlight) >= cifs_max_pending)
618 atomic_set(&server->inFlight, cifs_max_pending - 1);
619 /* We do not want to set the max_pending too low or we
620 could end up with the counter going negative */
621 spin_unlock(&GlobalMid_Lock);
622 /* Although there should not be any requests blocked on
623 this queue it can not hurt to be paranoid and try to wake up requests
624 that may haven been blocked when more than 50 at time were on the wire
625 to the same server - they now will see the session is in exit state
626 and get out of SendReceive. */
627 wake_up_all(&server->request_q);
628 /* give those requests time to exit */
631 if(server->ssocket) {
632 sock_release(csocket);
633 server->ssocket = NULL;
635 /* buffer usuallly freed in free_mid - need to free it here on exit */
637 cifs_buf_release(bigbuf);
638 if (smallbuf != NULL)
639 cifs_small_buf_release(smallbuf);
641 read_lock(&GlobalSMBSeslock);
642 if (list_empty(&server->pending_mid_q)) {
643 /* loop through server session structures attached to this and
645 list_for_each(tmp, &GlobalSMBSessionList) {
647 list_entry(tmp, struct cifsSesInfo,
649 if (ses->server == server) {
650 ses->status = CifsExiting;
654 read_unlock(&GlobalSMBSeslock);
656 /* although we can not zero the server struct pointer yet,
657 since there are active requests which may depnd on them,
658 mark the corresponding SMB sessions as exiting too */
659 list_for_each(tmp, &GlobalSMBSessionList) {
660 ses = list_entry(tmp, struct cifsSesInfo,
662 if (ses->server == server) {
663 ses->status = CifsExiting;
667 spin_lock(&GlobalMid_Lock);
668 list_for_each(tmp, &server->pending_mid_q) {
669 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
670 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
672 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
673 task_to_wake = mid_entry->tsk;
675 wake_up_process(task_to_wake);
679 spin_unlock(&GlobalMid_Lock);
680 read_unlock(&GlobalSMBSeslock);
681 /* 1/8th of sec is more than enough time for them to exit */
685 if (!list_empty(&server->pending_mid_q)) {
686 /* mpx threads have not exited yet give them
687 at least the smb send timeout time for long ops */
688 /* due to delays on oplock break requests, we need
689 to wait at least 45 seconds before giving up
690 on a request getting a response and going ahead
692 cFYI(1, ("Wait for exit from demultiplex thread"));
694 /* if threads still have not exited they are probably never
695 coming home not much else we can do but free the memory */
698 write_lock(&GlobalSMBSeslock);
699 atomic_dec(&tcpSesAllocCount);
700 length = tcpSesAllocCount.counter;
702 /* last chance to mark ses pointers invalid
703 if there are any pointing to this (e.g
704 if a crazy root user tried to kill cifsd
705 kernel thread explicitly this might happen) */
706 list_for_each(tmp, &GlobalSMBSessionList) {
707 ses = list_entry(tmp, struct cifsSesInfo,
709 if (ses->server == server) {
713 write_unlock(&GlobalSMBSeslock);
717 mempool_resize(cifs_req_poolp,
718 length + cifs_min_rcv,
722 complete_and_exit(&cifsd_complete, 0);
727 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
731 unsigned int temp_len, i, j;
737 memset(vol->source_rfc1001_name,0x20,15);
738 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
739 /* does not have to be a perfect mapping since the field is
740 informational, only used for servers that do not support
741 port 445 and it can be overridden at mount time */
742 vol->source_rfc1001_name[i] =
743 toupper(system_utsname.nodename[i]);
745 vol->source_rfc1001_name[15] = 0;
747 vol->linux_uid = current->uid; /* current->euid instead? */
748 vol->linux_gid = current->gid;
749 vol->dir_mode = S_IRWXUGO;
750 /* 2767 perms indicate mandatory locking support */
751 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
753 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
756 /* default is always to request posix paths. */
757 vol->posix_paths = 1;
762 if(strncmp(options,"sep=",4) == 0) {
763 if(options[4] != 0) {
764 separator[0] = options[4];
767 cFYI(1,("Null separator not allowed"));
771 while ((data = strsep(&options, separator)) != NULL) {
774 if ((value = strchr(data, '=')) != NULL)
777 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
779 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
781 } else if (strnicmp(data, "user", 4) == 0) {
782 if (!value || !*value) {
784 "CIFS: invalid or missing username\n");
785 return 1; /* needs_arg; */
787 if (strnlen(value, 200) < 200) {
788 vol->username = value;
790 printk(KERN_WARNING "CIFS: username too long\n");
793 } else if (strnicmp(data, "pass", 4) == 0) {
795 vol->password = NULL;
797 } else if(value[0] == 0) {
798 /* check if string begins with double comma
799 since that would mean the password really
800 does start with a comma, and would not
801 indicate an empty string */
802 if(value[1] != separator[0]) {
803 vol->password = NULL;
807 temp_len = strlen(value);
808 /* removed password length check, NTLM passwords
809 can be arbitrarily long */
811 /* if comma in password, the string will be
812 prematurely null terminated. Commas in password are
813 specified across the cifs mount interface by a double
814 comma ie ,, and a comma used as in other cases ie ','
815 as a parameter delimiter/separator is single and due
816 to the strsep above is temporarily zeroed. */
818 /* NB: password legally can have multiple commas and
819 the only illegal character in a password is null */
821 if ((value[temp_len] == 0) &&
822 (value[temp_len+1] == separator[0])) {
824 value[temp_len] = separator[0];
825 temp_len+=2; /* move after the second comma */
826 while(value[temp_len] != 0) {
827 if (value[temp_len] == separator[0]) {
828 if (value[temp_len+1] ==
830 /* skip second comma */
833 /* single comma indicating start
840 if(value[temp_len] == 0) {
844 /* point option to start of next parm */
845 options = value + temp_len + 1;
847 /* go from value to value + temp_len condensing
848 double commas to singles. Note that this ends up
849 allocating a few bytes too many, which is ok */
850 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
851 if(vol->password == NULL) {
852 printk("CIFS: no memory for pass\n");
855 for(i=0,j=0;i<temp_len;i++,j++) {
856 vol->password[j] = value[i];
857 if(value[i] == separator[0]
858 && value[i+1] == separator[0]) {
859 /* skip second comma */
863 vol->password[j] = 0;
865 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
866 if(vol->password == NULL) {
867 printk("CIFS: no memory for pass\n");
870 strcpy(vol->password, value);
872 } else if (strnicmp(data, "ip", 2) == 0) {
873 if (!value || !*value) {
875 } else if (strnlen(value, 35) < 35) {
878 printk(KERN_WARNING "CIFS: ip address too long\n");
881 } else if ((strnicmp(data, "unc", 3) == 0)
882 || (strnicmp(data, "target", 6) == 0)
883 || (strnicmp(data, "path", 4) == 0)) {
884 if (!value || !*value) {
886 "CIFS: invalid path to network resource\n");
887 return 1; /* needs_arg; */
889 if ((temp_len = strnlen(value, 300)) < 300) {
890 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
893 strcpy(vol->UNC,value);
894 if (strncmp(vol->UNC, "//", 2) == 0) {
897 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
899 "CIFS: UNC Path does not begin with // or \\\\ \n");
903 printk(KERN_WARNING "CIFS: UNC name too long\n");
906 } else if ((strnicmp(data, "domain", 3) == 0)
907 || (strnicmp(data, "workgroup", 5) == 0)) {
908 if (!value || !*value) {
909 printk(KERN_WARNING "CIFS: invalid domain name\n");
910 return 1; /* needs_arg; */
912 /* BB are there cases in which a comma can be valid in
913 a domain name and need special handling? */
914 if (strnlen(value, 65) < 65) {
915 vol->domainname = value;
916 cFYI(1, ("Domain name set"));
918 printk(KERN_WARNING "CIFS: domain name too long\n");
921 } else if (strnicmp(data, "iocharset", 9) == 0) {
922 if (!value || !*value) {
923 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
924 return 1; /* needs_arg; */
926 if (strnlen(value, 65) < 65) {
927 if(strnicmp(value,"default",7))
928 vol->iocharset = value;
929 /* if iocharset not set load_nls_default used by caller */
930 cFYI(1, ("iocharset set to %s",value));
932 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
935 } else if (strnicmp(data, "uid", 3) == 0) {
936 if (value && *value) {
938 simple_strtoul(value, &value, 0);
940 } else if (strnicmp(data, "gid", 3) == 0) {
941 if (value && *value) {
943 simple_strtoul(value, &value, 0);
945 } else if (strnicmp(data, "file_mode", 4) == 0) {
946 if (value && *value) {
948 simple_strtoul(value, &value, 0);
950 } else if (strnicmp(data, "dir_mode", 4) == 0) {
951 if (value && *value) {
953 simple_strtoul(value, &value, 0);
955 } else if (strnicmp(data, "dirmode", 4) == 0) {
956 if (value && *value) {
958 simple_strtoul(value, &value, 0);
960 } else if (strnicmp(data, "port", 4) == 0) {
961 if (value && *value) {
963 simple_strtoul(value, &value, 0);
965 } else if (strnicmp(data, "rsize", 5) == 0) {
966 if (value && *value) {
968 simple_strtoul(value, &value, 0);
970 } else if (strnicmp(data, "wsize", 5) == 0) {
971 if (value && *value) {
973 simple_strtoul(value, &value, 0);
975 } else if (strnicmp(data, "sockopt", 5) == 0) {
976 if (value && *value) {
978 simple_strtoul(value, &value, 0);
980 } else if (strnicmp(data, "netbiosname", 4) == 0) {
981 if (!value || !*value || (*value == ' ')) {
982 cFYI(1,("invalid (empty) netbiosname specified"));
984 memset(vol->source_rfc1001_name,0x20,15);
986 /* BB are there cases in which a comma can be
987 valid in this workstation netbios name (and need
988 special handling)? */
990 /* We do not uppercase netbiosname for user */
994 vol->source_rfc1001_name[i] = value[i];
996 /* The string has 16th byte zero still from
997 set at top of the function */
998 if((i==15) && (value[i] != 0))
999 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
1001 } else if (strnicmp(data, "credentials", 4) == 0) {
1003 } else if (strnicmp(data, "version", 3) == 0) {
1005 } else if (strnicmp(data, "guest",5) == 0) {
1007 } else if (strnicmp(data, "rw", 2) == 0) {
1009 } else if ((strnicmp(data, "suid", 4) == 0) ||
1010 (strnicmp(data, "nosuid", 6) == 0) ||
1011 (strnicmp(data, "exec", 4) == 0) ||
1012 (strnicmp(data, "noexec", 6) == 0) ||
1013 (strnicmp(data, "nodev", 5) == 0) ||
1014 (strnicmp(data, "noauto", 6) == 0) ||
1015 (strnicmp(data, "dev", 3) == 0)) {
1016 /* The mount tool or mount.cifs helper (if present)
1017 uses these opts to set flags, and the flags are read
1018 by the kernel vfs layer before we get here (ie
1019 before read super) so there is no point trying to
1020 parse these options again and set anything and it
1021 is ok to just ignore them */
1023 } else if (strnicmp(data, "ro", 2) == 0) {
1025 } else if (strnicmp(data, "hard", 4) == 0) {
1027 } else if (strnicmp(data, "soft", 4) == 0) {
1029 } else if (strnicmp(data, "perm", 4) == 0) {
1031 } else if (strnicmp(data, "noperm", 6) == 0) {
1033 } else if (strnicmp(data, "mapchars", 8) == 0) {
1035 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1037 } else if (strnicmp(data, "sfu", 3) == 0) {
1039 } else if (strnicmp(data, "nosfu", 5) == 0) {
1041 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1042 vol->posix_paths = 1;
1043 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1044 vol->posix_paths = 0;
1045 } else if (strnicmp(data, "nocase", 6) == 0) {
1047 } else if (strnicmp(data, "brl", 3) == 0) {
1049 } else if (strnicmp(data, "nobrl", 5) == 0) {
1051 /* turn off mandatory locking in mode
1052 if remote locking is turned off since the
1053 local vfs will do advisory */
1054 if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1055 vol->file_mode = S_IALLUGO;
1056 } else if (strnicmp(data, "setuids", 7) == 0) {
1058 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1060 } else if (strnicmp(data, "nohard", 6) == 0) {
1062 } else if (strnicmp(data, "nosoft", 6) == 0) {
1064 } else if (strnicmp(data, "nointr", 6) == 0) {
1066 } else if (strnicmp(data, "intr", 4) == 0) {
1068 } else if (strnicmp(data, "serverino",7) == 0) {
1069 vol->server_ino = 1;
1070 } else if (strnicmp(data, "noserverino",9) == 0) {
1071 vol->server_ino = 0;
1072 } else if (strnicmp(data, "acl",3) == 0) {
1073 vol->no_psx_acl = 0;
1074 } else if (strnicmp(data, "noacl",5) == 0) {
1075 vol->no_psx_acl = 1;
1076 } else if (strnicmp(data, "direct",6) == 0) {
1078 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1080 } else if (strnicmp(data, "in6_addr",8) == 0) {
1081 if (!value || !*value) {
1082 vol->in6_addr = NULL;
1083 } else if (strnlen(value, 49) == 48) {
1084 vol->in6_addr = value;
1086 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1089 } else if (strnicmp(data, "noac", 4) == 0) {
1090 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1092 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1094 if (vol->UNC == NULL) {
1095 if(devname == NULL) {
1096 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1099 if ((temp_len = strnlen(devname, 300)) < 300) {
1100 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1101 if(vol->UNC == NULL)
1103 strcpy(vol->UNC,devname);
1104 if (strncmp(vol->UNC, "//", 2) == 0) {
1107 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1108 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1112 printk(KERN_WARNING "CIFS: UNC name too long\n");
1116 if(vol->UNCip == NULL)
1117 vol->UNCip = &vol->UNC[2];
1122 static struct cifsSesInfo *
1123 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1124 struct in6_addr *target_ip6_addr,
1125 char *userName, struct TCP_Server_Info **psrvTcp)
1127 struct list_head *tmp;
1128 struct cifsSesInfo *ses;
1130 read_lock(&GlobalSMBSeslock);
1132 list_for_each(tmp, &GlobalSMBSessionList) {
1133 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1135 if((target_ip_addr &&
1136 (ses->server->addr.sockAddr.sin_addr.s_addr
1137 == target_ip_addr->s_addr)) || (target_ip6_addr
1138 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1139 target_ip6_addr,sizeof(*target_ip6_addr)))){
1140 /* BB lock server and tcp session and increment use count here?? */
1141 *psrvTcp = ses->server; /* found a match on the TCP session */
1142 /* BB check if reconnection needed */
1144 (ses->userName, userName,
1145 MAX_USERNAME_SIZE) == 0){
1146 read_unlock(&GlobalSMBSeslock);
1147 return ses; /* found exact match on both tcp and SMB sessions */
1151 /* else tcp and smb sessions need reconnection */
1153 read_unlock(&GlobalSMBSeslock);
1157 static struct cifsTconInfo *
1158 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1160 struct list_head *tmp;
1161 struct cifsTconInfo *tcon;
1163 read_lock(&GlobalSMBSeslock);
1164 list_for_each(tmp, &GlobalTreeConnectionList) {
1165 cFYI(1, ("Next tcon - "));
1166 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1168 if (tcon->ses->server) {
1170 (" old ip addr: %x == new ip %x ?",
1171 tcon->ses->server->addr.sockAddr.sin_addr.
1172 s_addr, new_target_ip_addr));
1173 if (tcon->ses->server->addr.sockAddr.sin_addr.
1174 s_addr == new_target_ip_addr) {
1175 /* BB lock tcon and server and tcp session and increment use count here? */
1176 /* found a match on the TCP session */
1177 /* BB check if reconnection needed */
1178 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1179 tcon->treeName, uncName));
1181 (tcon->treeName, uncName,
1182 MAX_TREE_SIZE) == 0) {
1184 ("Matched UNC, old user: %s == new: %s ?",
1185 tcon->treeName, uncName));
1187 (tcon->ses->userName,
1189 MAX_USERNAME_SIZE) == 0) {
1190 read_unlock(&GlobalSMBSeslock);
1191 return tcon;/* also matched user (smb session)*/
1198 read_unlock(&GlobalSMBSeslock);
1203 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1204 const char *old_path, const struct nls_table *nls_codepage,
1207 unsigned char *referrals = NULL;
1208 unsigned int num_referrals;
1211 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1212 &num_referrals, &referrals, remap);
1214 /* BB Add in code to: if valid refrl, if not ip address contact
1215 the helper that resolves tcp names, mount to it, try to
1216 tcon to it unmount it if fail */
1225 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1226 const char *old_path, const struct nls_table *nls_codepage,
1227 unsigned int *pnum_referrals,
1228 unsigned char ** preferrals, int remap)
1233 *pnum_referrals = 0;
1235 if (pSesInfo->ipc_tid == 0) {
1236 temp_unc = kmalloc(2 /* for slashes */ +
1237 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1238 + 1 + 4 /* slash IPC$ */ + 2,
1240 if (temp_unc == NULL)
1244 strcpy(temp_unc + 2, pSesInfo->serverName);
1245 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1246 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1248 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1252 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1253 pnum_referrals, nls_codepage, remap);
1258 /* See RFC1001 section 14 on representation of Netbios names */
1259 static void rfc1002mangle(char * target,char * source, unsigned int length)
1263 for(i=0,j=0;i<(length);i++) {
1264 /* mask a nibble at a time and encode */
1265 target[j] = 'A' + (0x0F & (source[i] >> 4));
1266 target[j+1] = 'A' + (0x0F & source[i]);
1274 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1275 char * netbios_name)
1279 __be16 orig_port = 0;
1281 if(*csocket == NULL) {
1282 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1284 cERROR(1, ("Error %d creating socket",rc));
1288 /* BB other socket options to set KEEPALIVE, NODELAY? */
1289 cFYI(1,("Socket created"));
1290 (*csocket)->sk->sk_allocation = GFP_NOFS;
1294 psin_server->sin_family = AF_INET;
1295 if(psin_server->sin_port) { /* user overrode default port */
1296 rc = (*csocket)->ops->connect(*csocket,
1297 (struct sockaddr *) psin_server,
1298 sizeof (struct sockaddr_in),0);
1304 /* save original port so we can retry user specified port
1305 later if fall back ports fail this time */
1306 orig_port = psin_server->sin_port;
1308 /* do not retry on the same port we just failed on */
1309 if(psin_server->sin_port != htons(CIFS_PORT)) {
1310 psin_server->sin_port = htons(CIFS_PORT);
1312 rc = (*csocket)->ops->connect(*csocket,
1313 (struct sockaddr *) psin_server,
1314 sizeof (struct sockaddr_in),0);
1320 psin_server->sin_port = htons(RFC1001_PORT);
1321 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1322 psin_server, sizeof (struct sockaddr_in),0);
1327 /* give up here - unless we want to retry on different
1328 protocol families some day */
1331 psin_server->sin_port = orig_port;
1332 cFYI(1,("Error %d connecting to server via ipv4",rc));
1333 sock_release(*csocket);
1337 /* Eventually check for other socket options to change from
1338 the default. sock_setsockopt not used because it expects
1339 user space buffer */
1340 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1342 /* send RFC1001 sessinit */
1344 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1345 /* some servers require RFC1001 sessinit before sending
1346 negprot - BB check reconnection in case where second
1347 sessinit is sent but no second negprot */
1348 struct rfc1002_session_packet * ses_init_buf;
1349 struct smb_hdr * smb_buf;
1350 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1352 ses_init_buf->trailer.session_req.called_len = 32;
1353 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1354 DEFAULT_CIFS_CALLED_NAME,16);
1355 ses_init_buf->trailer.session_req.calling_len = 32;
1356 /* calling name ends in null (byte 16) from old smb
1358 if(netbios_name && (netbios_name[0] !=0)) {
1359 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1362 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1363 "LINUX_CIFS_CLNT",16);
1365 ses_init_buf->trailer.session_req.scope1 = 0;
1366 ses_init_buf->trailer.session_req.scope2 = 0;
1367 smb_buf = (struct smb_hdr *)ses_init_buf;
1368 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1369 smb_buf->smb_buf_length = 0x81000044;
1370 rc = smb_send(*csocket, smb_buf, 0x44,
1371 (struct sockaddr *)psin_server);
1372 kfree(ses_init_buf);
1374 /* else the negprot may still work without this
1375 even though malloc failed */
1383 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1387 __be16 orig_port = 0;
1389 if(*csocket == NULL) {
1390 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1392 cERROR(1, ("Error %d creating ipv6 socket",rc));
1396 /* BB other socket options to set KEEPALIVE, NODELAY? */
1397 cFYI(1,("ipv6 Socket created"));
1398 (*csocket)->sk->sk_allocation = GFP_NOFS;
1402 psin_server->sin6_family = AF_INET6;
1404 if(psin_server->sin6_port) { /* user overrode default port */
1405 rc = (*csocket)->ops->connect(*csocket,
1406 (struct sockaddr *) psin_server,
1407 sizeof (struct sockaddr_in6),0);
1413 /* save original port so we can retry user specified port
1414 later if fall back ports fail this time */
1416 orig_port = psin_server->sin6_port;
1417 /* do not retry on the same port we just failed on */
1418 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1419 psin_server->sin6_port = htons(CIFS_PORT);
1421 rc = (*csocket)->ops->connect(*csocket,
1422 (struct sockaddr *) psin_server,
1423 sizeof (struct sockaddr_in6),0);
1429 psin_server->sin6_port = htons(RFC1001_PORT);
1430 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1431 psin_server, sizeof (struct sockaddr_in6),0);
1436 /* give up here - unless we want to retry on different
1437 protocol families some day */
1440 psin_server->sin6_port = orig_port;
1441 cFYI(1,("Error %d connecting to server via ipv6",rc));
1442 sock_release(*csocket);
1446 /* Eventually check for other socket options to change from
1447 the default. sock_setsockopt not used because it expects
1448 user space buffer */
1449 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1455 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1456 char *mount_data, const char *devname)
1460 int address_type = AF_INET;
1461 struct socket *csocket = NULL;
1462 struct sockaddr_in sin_server;
1463 struct sockaddr_in6 sin_server6;
1464 struct smb_vol volume_info;
1465 struct cifsSesInfo *pSesInfo = NULL;
1466 struct cifsSesInfo *existingCifsSes = NULL;
1467 struct cifsTconInfo *tcon = NULL;
1468 struct TCP_Server_Info *srvTcp = NULL;
1472 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1474 memset(&volume_info,0,sizeof(struct smb_vol));
1475 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1477 kfree(volume_info.UNC);
1478 if(volume_info.password)
1479 kfree(volume_info.password);
1484 if (volume_info.username) {
1485 /* BB fixme parse for domain name here */
1486 cFYI(1, ("Username: %s ", volume_info.username));
1489 cifserror("No username specified ");
1490 /* In userspace mount helper we can get user name from alternate
1491 locations such as env variables and files on disk */
1493 kfree(volume_info.UNC);
1494 if(volume_info.password)
1495 kfree(volume_info.password);
1500 if (volume_info.UNCip && volume_info.UNC) {
1501 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1504 /* not ipv4 address, try ipv6 */
1505 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1507 address_type = AF_INET6;
1509 address_type = AF_INET;
1513 /* we failed translating address */
1515 kfree(volume_info.UNC);
1516 if(volume_info.password)
1517 kfree(volume_info.password);
1522 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1525 } else if (volume_info.UNCip){
1526 /* BB using ip addr as server name connect to the DFS root below */
1527 cERROR(1,("Connecting to DFS root not implemented yet"));
1529 kfree(volume_info.UNC);
1530 if(volume_info.password)
1531 kfree(volume_info.password);
1534 } else /* which servers DFS root would we conect to */ {
1536 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1538 kfree(volume_info.UNC);
1539 if(volume_info.password)
1540 kfree(volume_info.password);
1545 /* this is needed for ASCII cp to Unicode converts */
1546 if(volume_info.iocharset == NULL) {
1547 cifs_sb->local_nls = load_nls_default();
1548 /* load_nls_default can not return null */
1550 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1551 if(cifs_sb->local_nls == NULL) {
1552 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1554 kfree(volume_info.UNC);
1555 if(volume_info.password)
1556 kfree(volume_info.password);
1562 if(address_type == AF_INET)
1563 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1564 NULL /* no ipv6 addr */,
1565 volume_info.username, &srvTcp);
1566 else if(address_type == AF_INET6)
1567 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1568 &sin_server6.sin6_addr,
1569 volume_info.username, &srvTcp);
1572 kfree(volume_info.UNC);
1573 if(volume_info.password)
1574 kfree(volume_info.password);
1581 cFYI(1, ("Existing tcp session with server found "));
1582 } else { /* create socket */
1583 if(volume_info.port)
1584 sin_server.sin_port = htons(volume_info.port);
1586 sin_server.sin_port = 0;
1587 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1590 ("Error connecting to IPv4 socket. Aborting operation"));
1592 sock_release(csocket);
1594 kfree(volume_info.UNC);
1595 if(volume_info.password)
1596 kfree(volume_info.password);
1601 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1602 if (srvTcp == NULL) {
1604 sock_release(csocket);
1606 kfree(volume_info.UNC);
1607 if(volume_info.password)
1608 kfree(volume_info.password);
1612 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1613 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1614 atomic_set(&srvTcp->inFlight,0);
1615 /* BB Add code for ipv6 case too */
1616 srvTcp->ssocket = csocket;
1617 srvTcp->protocolType = IPV4;
1618 init_waitqueue_head(&srvTcp->response_q);
1619 init_waitqueue_head(&srvTcp->request_q);
1620 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1621 /* at this point we are the only ones with the pointer
1622 to the struct since the kernel thread not created yet
1623 so no need to spinlock this init of tcpStatus */
1624 srvTcp->tcpStatus = CifsNew;
1625 init_MUTEX(&srvTcp->tcpSem);
1626 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1627 CLONE_FS | CLONE_FILES | CLONE_VM);
1630 sock_release(csocket);
1632 kfree(volume_info.UNC);
1633 if(volume_info.password)
1634 kfree(volume_info.password);
1638 wait_for_completion(&cifsd_complete);
1640 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1641 srvTcp->sequence_number = 0;
1645 if (existingCifsSes) {
1646 pSesInfo = existingCifsSes;
1647 cFYI(1, ("Existing smb sess found "));
1648 if(volume_info.password)
1649 kfree(volume_info.password);
1650 /* volume_info.UNC freed at end of function */
1652 cFYI(1, ("Existing smb sess not found "));
1653 pSesInfo = sesInfoAlloc();
1654 if (pSesInfo == NULL)
1657 pSesInfo->server = srvTcp;
1658 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1659 NIPQUAD(sin_server.sin_addr.s_addr));
1663 /* volume_info.password freed at unmount */
1664 if (volume_info.password)
1665 pSesInfo->password = volume_info.password;
1666 if (volume_info.username)
1667 strncpy(pSesInfo->userName,
1668 volume_info.username,MAX_USERNAME_SIZE);
1669 if (volume_info.domainname)
1670 strncpy(pSesInfo->domainName,
1671 volume_info.domainname,MAX_USERNAME_SIZE);
1672 pSesInfo->linux_uid = volume_info.linux_uid;
1673 down(&pSesInfo->sesSem);
1674 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1675 up(&pSesInfo->sesSem);
1677 atomic_inc(&srvTcp->socketUseCount);
1679 if(volume_info.password)
1680 kfree(volume_info.password);
1683 /* search for existing tcon to this server share */
1685 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1686 cifs_sb->rsize = volume_info.rsize;
1688 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1689 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1690 cifs_sb->wsize = volume_info.wsize;
1692 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1693 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1694 cifs_sb->rsize = PAGE_CACHE_SIZE;
1695 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1697 cifs_sb->mnt_uid = volume_info.linux_uid;
1698 cifs_sb->mnt_gid = volume_info.linux_gid;
1699 cifs_sb->mnt_file_mode = volume_info.file_mode;
1700 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1701 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1703 if(volume_info.noperm)
1704 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1705 if(volume_info.setuids)
1706 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1707 if(volume_info.server_ino)
1708 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1709 if(volume_info.remap)
1710 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1711 if(volume_info.no_xattr)
1712 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1713 if(volume_info.sfu_emul)
1714 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1715 if(volume_info.nobrl)
1716 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1718 if(volume_info.direct_io) {
1719 cFYI(1,("mounting share using direct i/o"));
1720 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1724 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1725 volume_info.username);
1727 cFYI(1, ("Found match on UNC path "));
1728 /* we can have only one retry value for a connection
1729 to a share so for resources mounted more than once
1730 to the same server share the last value passed in
1731 for the retry flag is used */
1732 tcon->retry = volume_info.retry;
1733 tcon->nocase = volume_info.nocase;
1735 tcon = tconInfoAlloc();
1739 /* check for null share name ie connect to dfs root */
1741 /* BB check if this works for exactly length three strings */
1742 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1743 && (strchr(volume_info.UNC + 3, '/') ==
1745 rc = connect_to_dfs_path(xid, pSesInfo,
1746 "", cifs_sb->local_nls,
1747 cifs_sb->mnt_cifs_flags &
1748 CIFS_MOUNT_MAP_SPECIAL_CHR);
1750 kfree(volume_info.UNC);
1754 rc = CIFSTCon(xid, pSesInfo,
1756 tcon, cifs_sb->local_nls);
1757 cFYI(1, ("CIFS Tcon rc = %d", rc));
1760 atomic_inc(&pSesInfo->inUse);
1761 tcon->retry = volume_info.retry;
1762 tcon->nocase = volume_info.nocase;
1768 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1769 sb->s_maxbytes = (u64) 1 << 63;
1771 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1774 sb->s_time_gran = 100;
1776 /* on error free sesinfo and tcon struct if needed */
1778 /* if session setup failed, use count is zero but
1779 we still need to free cifsd thread */
1780 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1781 spin_lock(&GlobalMid_Lock);
1782 srvTcp->tcpStatus = CifsExiting;
1783 spin_unlock(&GlobalMid_Lock);
1785 send_sig(SIGKILL,srvTcp->tsk,1);
1786 wait_for_completion(&cifsd_complete);
1789 /* If find_unc succeeded then rc == 0 so we can not end */
1790 if (tcon) /* up accidently freeing someone elses tcon struct */
1792 if (existingCifsSes == NULL) {
1794 if ((pSesInfo->server) &&
1795 (pSesInfo->status == CifsGood)) {
1797 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1798 /* if the socketUseCount is now zero */
1799 if((temp_rc == -ESHUTDOWN) &&
1800 (pSesInfo->server->tsk)) {
1801 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1802 wait_for_completion(&cifsd_complete);
1805 cFYI(1, ("No session or bad tcon"));
1806 sesInfoFree(pSesInfo);
1807 /* pSesInfo = NULL; */
1811 atomic_inc(&tcon->useCount);
1812 cifs_sb->tcon = tcon;
1813 tcon->ses = pSesInfo;
1815 /* do not care if following two calls succeed - informational only */
1816 CIFSSMBQFSDeviceInfo(xid, tcon);
1817 CIFSSMBQFSAttributeInfo(xid, tcon);
1818 if (tcon->ses->capabilities & CAP_UNIX) {
1819 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1820 if(!volume_info.no_psx_acl) {
1821 if(CIFS_UNIX_POSIX_ACL_CAP &
1822 le64_to_cpu(tcon->fsUnixInfo.Capability))
1823 cFYI(1,("server negotiated posix acl support"));
1824 sb->s_flags |= MS_POSIXACL;
1827 /* Try and negotiate POSIX pathnames if we can. */
1828 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
1829 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1830 if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
1831 cFYI(1,("negotiated posix pathnames support"));
1832 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
1834 cFYI(1,("posix pathnames support requested but not supported"));
1841 /* volume_info.password is freed above when existing session found
1842 (in which case it is not needed anymore) but when new sesion is created
1843 the password ptr is put in the new session structure (in which case the
1844 password will be freed at unmount time) */
1846 kfree(volume_info.UNC);
1852 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1853 char session_key[CIFS_SESSION_KEY_SIZE],
1854 const struct nls_table *nls_codepage)
1856 struct smb_hdr *smb_buffer;
1857 struct smb_hdr *smb_buffer_response;
1858 SESSION_SETUP_ANDX *pSMB;
1859 SESSION_SETUP_ANDX *pSMBr;
1864 int remaining_words = 0;
1865 int bytes_returned = 0;
1870 cFYI(1, ("In sesssetup "));
1873 user = ses->userName;
1874 domain = ses->domainName;
1875 smb_buffer = cifs_buf_get();
1876 if (smb_buffer == NULL) {
1879 smb_buffer_response = smb_buffer;
1880 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1882 /* send SMBsessionSetup here */
1883 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1884 NULL /* no tCon exists yet */ , 13 /* wct */ );
1886 smb_buffer->Mid = GetNextMid(ses->server);
1887 pSMB->req_no_secext.AndXCommand = 0xFF;
1888 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1889 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1891 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1892 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1894 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1895 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1896 if (ses->capabilities & CAP_UNICODE) {
1897 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1898 capabilities |= CAP_UNICODE;
1900 if (ses->capabilities & CAP_STATUS32) {
1901 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1902 capabilities |= CAP_STATUS32;
1904 if (ses->capabilities & CAP_DFS) {
1905 smb_buffer->Flags2 |= SMBFLG2_DFS;
1906 capabilities |= CAP_DFS;
1908 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1910 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1911 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1913 pSMB->req_no_secext.CaseSensitivePasswordLength =
1914 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1915 bcc_ptr = pByteArea(smb_buffer);
1916 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1917 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1918 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1919 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1921 if (ses->capabilities & CAP_UNICODE) {
1922 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1927 bytes_returned = 0; /* skill null user */
1930 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1932 /* convert number of 16 bit words to bytes */
1933 bcc_ptr += 2 * bytes_returned;
1934 bcc_ptr += 2; /* trailing null */
1937 cifs_strtoUCS((wchar_t *) bcc_ptr,
1938 "CIFS_LINUX_DOM", 32, nls_codepage);
1941 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1943 bcc_ptr += 2 * bytes_returned;
1946 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1948 bcc_ptr += 2 * bytes_returned;
1950 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1952 bcc_ptr += 2 * bytes_returned;
1955 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1957 bcc_ptr += 2 * bytes_returned;
1961 strncpy(bcc_ptr, user, 200);
1962 bcc_ptr += strnlen(user, 200);
1966 if (domain == NULL) {
1967 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1968 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1970 strncpy(bcc_ptr, domain, 64);
1971 bcc_ptr += strnlen(domain, 64);
1975 strcpy(bcc_ptr, "Linux version ");
1976 bcc_ptr += strlen("Linux version ");
1977 strcpy(bcc_ptr, system_utsname.release);
1978 bcc_ptr += strlen(system_utsname.release) + 1;
1979 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1980 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1982 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1983 smb_buffer->smb_buf_length += count;
1984 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1986 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1987 &bytes_returned, 1);
1989 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1990 } else if ((smb_buffer_response->WordCount == 3)
1991 || (smb_buffer_response->WordCount == 4)) {
1992 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1993 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1994 if (action & GUEST_LOGIN)
1995 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1996 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1997 cFYI(1, ("UID = %d ", ses->Suid));
1998 /* response can have either 3 or 4 word count - Samba sends 3 */
1999 bcc_ptr = pByteArea(smb_buffer_response);
2000 if ((pSMBr->resp.hdr.WordCount == 3)
2001 || ((pSMBr->resp.hdr.WordCount == 4)
2002 && (blob_len < pSMBr->resp.ByteCount))) {
2003 if (pSMBr->resp.hdr.WordCount == 4)
2004 bcc_ptr += blob_len;
2006 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2007 if ((long) (bcc_ptr) % 2) {
2009 (BCC(smb_buffer_response) - 1) /2;
2010 bcc_ptr++; /* Unicode strings must be word aligned */
2013 BCC(smb_buffer_response) / 2;
2016 UniStrnlen((wchar_t *) bcc_ptr,
2017 remaining_words - 1);
2018 /* We look for obvious messed up bcc or strings in response so we do not go off
2019 the end since (at least) WIN2K and Windows XP have a major bug in not null
2020 terminating last Unicode string in response */
2021 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2022 if(ses->serverOS == NULL)
2023 goto sesssetup_nomem;
2024 cifs_strfromUCS_le(ses->serverOS,
2025 (wchar_t *)bcc_ptr, len,nls_codepage);
2026 bcc_ptr += 2 * (len + 1);
2027 remaining_words -= len + 1;
2028 ses->serverOS[2 * len] = 0;
2029 ses->serverOS[1 + (2 * len)] = 0;
2030 if (remaining_words > 0) {
2031 len = UniStrnlen((wchar_t *)bcc_ptr,
2033 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
2034 if(ses->serverNOS == NULL)
2035 goto sesssetup_nomem;
2036 cifs_strfromUCS_le(ses->serverNOS,
2037 (wchar_t *)bcc_ptr,len,nls_codepage);
2038 bcc_ptr += 2 * (len + 1);
2039 ses->serverNOS[2 * len] = 0;
2040 ses->serverNOS[1 + (2 * len)] = 0;
2041 if(strncmp(ses->serverNOS,
2042 "NT LAN Manager 4",16) == 0) {
2043 cFYI(1,("NT4 server"));
2044 ses->flags |= CIFS_SES_NT4;
2046 remaining_words -= len + 1;
2047 if (remaining_words > 0) {
2048 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2049 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2051 kcalloc(1, 2*(len+1),GFP_KERNEL);
2052 if(ses->serverDomain == NULL)
2053 goto sesssetup_nomem;
2054 cifs_strfromUCS_le(ses->serverDomain,
2055 (wchar_t *)bcc_ptr,len,nls_codepage);
2056 bcc_ptr += 2 * (len + 1);
2057 ses->serverDomain[2*len] = 0;
2058 ses->serverDomain[1+(2*len)] = 0;
2059 } /* else no more room so create dummy domain string */
2062 kcalloc(1, 2, GFP_KERNEL);
2063 } else { /* no room so create dummy domain and NOS string */
2064 /* if these kcallocs fail not much we
2065 can do, but better to not fail the
2068 kcalloc(1, 2, GFP_KERNEL);
2070 kcalloc(1, 2, GFP_KERNEL);
2072 } else { /* ASCII */
2073 len = strnlen(bcc_ptr, 1024);
2074 if (((long) bcc_ptr + len) - (long)
2075 pByteArea(smb_buffer_response)
2076 <= BCC(smb_buffer_response)) {
2077 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2078 if(ses->serverOS == NULL)
2079 goto sesssetup_nomem;
2080 strncpy(ses->serverOS,bcc_ptr, len);
2083 bcc_ptr[0] = 0; /* null terminate the string */
2086 len = strnlen(bcc_ptr, 1024);
2087 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2088 if(ses->serverNOS == NULL)
2089 goto sesssetup_nomem;
2090 strncpy(ses->serverNOS, bcc_ptr, len);
2095 len = strnlen(bcc_ptr, 1024);
2096 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2097 if(ses->serverDomain == NULL)
2098 goto sesssetup_nomem;
2099 strncpy(ses->serverDomain, bcc_ptr, len);
2105 ("Variable field of length %d extends beyond end of smb ",
2110 (" Security Blob Length extends beyond end of SMB"));
2114 (" Invalid Word count %d: ",
2115 smb_buffer_response->WordCount));
2118 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2119 since that could make reconnection harder, and
2120 reconnection might be needed to free memory */
2122 cifs_buf_release(smb_buffer);
2128 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2129 char *SecurityBlob,int SecurityBlobLength,
2130 const struct nls_table *nls_codepage)
2132 struct smb_hdr *smb_buffer;
2133 struct smb_hdr *smb_buffer_response;
2134 SESSION_SETUP_ANDX *pSMB;
2135 SESSION_SETUP_ANDX *pSMBr;
2140 int remaining_words = 0;
2141 int bytes_returned = 0;
2146 cFYI(1, ("In spnego sesssetup "));
2149 user = ses->userName;
2150 domain = ses->domainName;
2152 smb_buffer = cifs_buf_get();
2153 if (smb_buffer == NULL) {
2156 smb_buffer_response = smb_buffer;
2157 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2159 /* send SMBsessionSetup here */
2160 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2161 NULL /* no tCon exists yet */ , 12 /* wct */ );
2163 smb_buffer->Mid = GetNextMid(ses->server);
2164 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2165 pSMB->req.AndXCommand = 0xFF;
2166 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2167 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2169 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2170 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2172 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2173 CAP_EXTENDED_SECURITY;
2174 if (ses->capabilities & CAP_UNICODE) {
2175 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2176 capabilities |= CAP_UNICODE;
2178 if (ses->capabilities & CAP_STATUS32) {
2179 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2180 capabilities |= CAP_STATUS32;
2182 if (ses->capabilities & CAP_DFS) {
2183 smb_buffer->Flags2 |= SMBFLG2_DFS;
2184 capabilities |= CAP_DFS;
2186 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2188 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2189 bcc_ptr = pByteArea(smb_buffer);
2190 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2191 bcc_ptr += SecurityBlobLength;
2193 if (ses->capabilities & CAP_UNICODE) {
2194 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2199 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
2200 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2201 bcc_ptr += 2; /* trailing null */
2204 cifs_strtoUCS((wchar_t *) bcc_ptr,
2205 "CIFS_LINUX_DOM", 32, nls_codepage);
2208 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2210 bcc_ptr += 2 * bytes_returned;
2213 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2215 bcc_ptr += 2 * bytes_returned;
2217 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2219 bcc_ptr += 2 * bytes_returned;
2222 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2224 bcc_ptr += 2 * bytes_returned;
2227 strncpy(bcc_ptr, user, 200);
2228 bcc_ptr += strnlen(user, 200);
2231 if (domain == NULL) {
2232 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2233 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2235 strncpy(bcc_ptr, domain, 64);
2236 bcc_ptr += strnlen(domain, 64);
2240 strcpy(bcc_ptr, "Linux version ");
2241 bcc_ptr += strlen("Linux version ");
2242 strcpy(bcc_ptr, system_utsname.release);
2243 bcc_ptr += strlen(system_utsname.release) + 1;
2244 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2245 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2247 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2248 smb_buffer->smb_buf_length += count;
2249 pSMB->req.ByteCount = cpu_to_le16(count);
2251 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2252 &bytes_returned, 1);
2254 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2255 } else if ((smb_buffer_response->WordCount == 3)
2256 || (smb_buffer_response->WordCount == 4)) {
2257 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2259 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2260 if (action & GUEST_LOGIN)
2261 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2263 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2264 cFYI(1, ("UID = %d ", ses->Suid));
2265 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2267 /* BB Fix below to make endian neutral !! */
2269 if ((pSMBr->resp.hdr.WordCount == 3)
2270 || ((pSMBr->resp.hdr.WordCount == 4)
2272 pSMBr->resp.ByteCount))) {
2273 if (pSMBr->resp.hdr.WordCount == 4) {
2277 ("Security Blob Length %d ",
2281 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2282 if ((long) (bcc_ptr) % 2) {
2284 (BCC(smb_buffer_response)
2286 bcc_ptr++; /* Unicode strings must be word aligned */
2290 (smb_buffer_response) / 2;
2293 UniStrnlen((wchar_t *) bcc_ptr,
2294 remaining_words - 1);
2295 /* We look for obvious messed up bcc or strings in response so we do not go off
2296 the end since (at least) WIN2K and Windows XP have a major bug in not null
2297 terminating last Unicode string in response */
2299 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2300 cifs_strfromUCS_le(ses->serverOS,
2304 bcc_ptr += 2 * (len + 1);
2305 remaining_words -= len + 1;
2306 ses->serverOS[2 * len] = 0;
2307 ses->serverOS[1 + (2 * len)] = 0;
2308 if (remaining_words > 0) {
2309 len = UniStrnlen((wchar_t *)bcc_ptr,
2313 kcalloc(1, 2 * (len + 1),
2315 cifs_strfromUCS_le(ses->serverNOS,
2319 bcc_ptr += 2 * (len + 1);
2320 ses->serverNOS[2 * len] = 0;
2321 ses->serverNOS[1 + (2 * len)] = 0;
2322 remaining_words -= len + 1;
2323 if (remaining_words > 0) {
2324 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2325 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2326 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2327 cifs_strfromUCS_le(ses->serverDomain,
2331 bcc_ptr += 2*(len+1);
2332 ses->serverDomain[2*len] = 0;
2333 ses->serverDomain[1+(2*len)] = 0;
2334 } /* else no more room so create dummy domain string */
2337 kcalloc(1, 2,GFP_KERNEL);
2338 } else { /* no room so create dummy domain and NOS string */
2339 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2340 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2342 } else { /* ASCII */
2344 len = strnlen(bcc_ptr, 1024);
2345 if (((long) bcc_ptr + len) - (long)
2346 pByteArea(smb_buffer_response)
2347 <= BCC(smb_buffer_response)) {
2348 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2349 strncpy(ses->serverOS, bcc_ptr, len);
2352 bcc_ptr[0] = 0; /* null terminate the string */
2355 len = strnlen(bcc_ptr, 1024);
2356 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2357 strncpy(ses->serverNOS, bcc_ptr, len);
2362 len = strnlen(bcc_ptr, 1024);
2363 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2364 strncpy(ses->serverDomain, bcc_ptr, len);
2370 ("Variable field of length %d extends beyond end of smb ",
2375 (" Security Blob Length extends beyond end of SMB"));
2378 cERROR(1, ("No session structure passed in."));
2382 (" Invalid Word count %d: ",
2383 smb_buffer_response->WordCount));
2388 cifs_buf_release(smb_buffer);
2394 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2395 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2396 const struct nls_table *nls_codepage)
2398 struct smb_hdr *smb_buffer;
2399 struct smb_hdr *smb_buffer_response;
2400 SESSION_SETUP_ANDX *pSMB;
2401 SESSION_SETUP_ANDX *pSMBr;
2405 int remaining_words = 0;
2406 int bytes_returned = 0;
2408 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2409 PNEGOTIATE_MESSAGE SecurityBlob;
2410 PCHALLENGE_MESSAGE SecurityBlob2;
2411 __u32 negotiate_flags, capabilities;
2414 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2417 domain = ses->domainName;
2418 *pNTLMv2_flag = FALSE;
2419 smb_buffer = cifs_buf_get();
2420 if (smb_buffer == NULL) {
2423 smb_buffer_response = smb_buffer;
2424 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2425 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2427 /* send SMBsessionSetup here */
2428 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2429 NULL /* no tCon exists yet */ , 12 /* wct */ );
2431 smb_buffer->Mid = GetNextMid(ses->server);
2432 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2433 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2435 pSMB->req.AndXCommand = 0xFF;
2436 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2437 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2439 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2440 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2442 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2443 CAP_EXTENDED_SECURITY;
2444 if (ses->capabilities & CAP_UNICODE) {
2445 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2446 capabilities |= CAP_UNICODE;
2448 if (ses->capabilities & CAP_STATUS32) {
2449 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2450 capabilities |= CAP_STATUS32;
2452 if (ses->capabilities & CAP_DFS) {
2453 smb_buffer->Flags2 |= SMBFLG2_DFS;
2454 capabilities |= CAP_DFS;
2456 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2458 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2459 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2460 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2461 SecurityBlob->MessageType = NtLmNegotiate;
2463 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2464 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2465 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2467 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2469 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2470 /* setup pointers to domain name and workstation name */
2471 bcc_ptr += SecurityBlobLength;
2473 SecurityBlob->WorkstationName.Buffer = 0;
2474 SecurityBlob->WorkstationName.Length = 0;
2475 SecurityBlob->WorkstationName.MaximumLength = 0;
2477 if (domain == NULL) {
2478 SecurityBlob->DomainName.Buffer = 0;
2479 SecurityBlob->DomainName.Length = 0;
2480 SecurityBlob->DomainName.MaximumLength = 0;
2483 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2484 strncpy(bcc_ptr, domain, 63);
2485 len = strnlen(domain, 64);
2486 SecurityBlob->DomainName.MaximumLength =
2488 SecurityBlob->DomainName.Buffer =
2489 cpu_to_le32((long) &SecurityBlob->
2491 (long) &SecurityBlob->Signature);
2493 SecurityBlobLength += len;
2494 SecurityBlob->DomainName.Length =
2497 if (ses->capabilities & CAP_UNICODE) {
2498 if ((long) bcc_ptr % 2) {
2504 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2506 bcc_ptr += 2 * bytes_returned;
2508 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2510 bcc_ptr += 2 * bytes_returned;
2511 bcc_ptr += 2; /* null terminate Linux version */
2513 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2515 bcc_ptr += 2 * bytes_returned;
2518 bcc_ptr += 2; /* null terminate network opsys string */
2521 bcc_ptr += 2; /* null domain */
2522 } else { /* ASCII */
2523 strcpy(bcc_ptr, "Linux version ");
2524 bcc_ptr += strlen("Linux version ");
2525 strcpy(bcc_ptr, system_utsname.release);
2526 bcc_ptr += strlen(system_utsname.release) + 1;
2527 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2528 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2529 bcc_ptr++; /* empty domain field */
2532 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2533 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2534 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2535 smb_buffer->smb_buf_length += count;
2536 pSMB->req.ByteCount = cpu_to_le16(count);
2538 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2539 &bytes_returned, 1);
2541 if (smb_buffer_response->Status.CifsError ==
2542 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2546 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2547 } else if ((smb_buffer_response->WordCount == 3)
2548 || (smb_buffer_response->WordCount == 4)) {
2549 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2550 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2552 if (action & GUEST_LOGIN)
2553 cFYI(1, (" Guest login"));
2554 /* Do we want to set anything in SesInfo struct when guest login? */
2556 bcc_ptr = pByteArea(smb_buffer_response);
2557 /* response can have either 3 or 4 word count - Samba sends 3 */
2559 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2560 if (SecurityBlob2->MessageType != NtLmChallenge) {
2562 ("Unexpected NTLMSSP message type received %d",
2563 SecurityBlob2->MessageType));
2565 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2566 cFYI(1, ("UID = %d ", ses->Suid));
2567 if ((pSMBr->resp.hdr.WordCount == 3)
2568 || ((pSMBr->resp.hdr.WordCount == 4)
2570 pSMBr->resp.ByteCount))) {
2572 if (pSMBr->resp.hdr.WordCount == 4) {
2573 bcc_ptr += blob_len;
2575 ("Security Blob Length %d ",
2579 cFYI(1, ("NTLMSSP Challenge rcvd "));
2581 memcpy(ses->server->cryptKey,
2582 SecurityBlob2->Challenge,
2583 CIFS_CRYPTO_KEY_SIZE);
2584 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2585 *pNTLMv2_flag = TRUE;
2587 if((SecurityBlob2->NegotiateFlags &
2588 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2589 || (sign_CIFS_PDUs > 1))
2590 ses->server->secMode |=
2591 SECMODE_SIGN_REQUIRED;
2592 if ((SecurityBlob2->NegotiateFlags &
2593 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2594 ses->server->secMode |=
2595 SECMODE_SIGN_ENABLED;
2597 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2598 if ((long) (bcc_ptr) % 2) {
2600 (BCC(smb_buffer_response)
2602 bcc_ptr++; /* Unicode strings must be word aligned */
2606 (smb_buffer_response) / 2;
2609 UniStrnlen((wchar_t *) bcc_ptr,
2610 remaining_words - 1);
2611 /* We look for obvious messed up bcc or strings in response so we do not go off
2612 the end since (at least) WIN2K and Windows XP have a major bug in not null
2613 terminating last Unicode string in response */
2615 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2616 cifs_strfromUCS_le(ses->serverOS,
2620 bcc_ptr += 2 * (len + 1);
2621 remaining_words -= len + 1;
2622 ses->serverOS[2 * len] = 0;
2623 ses->serverOS[1 + (2 * len)] = 0;
2624 if (remaining_words > 0) {
2625 len = UniStrnlen((wchar_t *)
2630 kcalloc(1, 2 * (len + 1),
2632 cifs_strfromUCS_le(ses->
2638 bcc_ptr += 2 * (len + 1);
2639 ses->serverNOS[2 * len] = 0;
2642 remaining_words -= len + 1;
2643 if (remaining_words > 0) {
2644 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2645 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2670 } /* else no more room so create dummy domain string */
2675 } else { /* no room so create dummy domain and NOS string */
2677 kcalloc(1, 2, GFP_KERNEL);
2679 kcalloc(1, 2, GFP_KERNEL);
2681 } else { /* ASCII */
2682 len = strnlen(bcc_ptr, 1024);
2683 if (((long) bcc_ptr + len) - (long)
2684 pByteArea(smb_buffer_response)
2685 <= BCC(smb_buffer_response)) {
2689 strncpy(ses->serverOS,
2693 bcc_ptr[0] = 0; /* null terminate string */
2696 len = strnlen(bcc_ptr, 1024);
2700 strncpy(ses->serverNOS, bcc_ptr, len);
2705 len = strnlen(bcc_ptr, 1024);
2709 strncpy(ses->serverDomain, bcc_ptr, len);
2715 ("Variable field of length %d extends beyond end of smb ",
2720 (" Security Blob Length extends beyond end of SMB"));
2723 cERROR(1, ("No session structure passed in."));
2727 (" Invalid Word count %d: ",
2728 smb_buffer_response->WordCount));
2733 cifs_buf_release(smb_buffer);
2738 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2739 char *ntlm_session_key, int ntlmv2_flag,
2740 const struct nls_table *nls_codepage)
2742 struct smb_hdr *smb_buffer;
2743 struct smb_hdr *smb_buffer_response;
2744 SESSION_SETUP_ANDX *pSMB;
2745 SESSION_SETUP_ANDX *pSMBr;
2750 int remaining_words = 0;
2751 int bytes_returned = 0;
2753 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2754 PAUTHENTICATE_MESSAGE SecurityBlob;
2755 __u32 negotiate_flags, capabilities;
2758 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2761 user = ses->userName;
2762 domain = ses->domainName;
2763 smb_buffer = cifs_buf_get();
2764 if (smb_buffer == NULL) {
2767 smb_buffer_response = smb_buffer;
2768 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2769 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2771 /* send SMBsessionSetup here */
2772 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2773 NULL /* no tCon exists yet */ , 12 /* wct */ );
2775 smb_buffer->Mid = GetNextMid(ses->server);
2776 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2777 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2778 pSMB->req.AndXCommand = 0xFF;
2779 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2780 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2782 pSMB->req.hdr.Uid = ses->Suid;
2784 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2785 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2787 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2788 CAP_EXTENDED_SECURITY;
2789 if (ses->capabilities & CAP_UNICODE) {
2790 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2791 capabilities |= CAP_UNICODE;
2793 if (ses->capabilities & CAP_STATUS32) {
2794 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2795 capabilities |= CAP_STATUS32;
2797 if (ses->capabilities & CAP_DFS) {
2798 smb_buffer->Flags2 |= SMBFLG2_DFS;
2799 capabilities |= CAP_DFS;
2801 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2803 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2804 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2805 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2806 SecurityBlob->MessageType = NtLmAuthenticate;
2807 bcc_ptr += SecurityBlobLength;
2809 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2810 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2811 0x80000000 | NTLMSSP_NEGOTIATE_128;
2813 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2815 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2817 /* setup pointers to domain name and workstation name */
2819 SecurityBlob->WorkstationName.Buffer = 0;
2820 SecurityBlob->WorkstationName.Length = 0;
2821 SecurityBlob->WorkstationName.MaximumLength = 0;
2822 SecurityBlob->SessionKey.Length = 0;
2823 SecurityBlob->SessionKey.MaximumLength = 0;
2824 SecurityBlob->SessionKey.Buffer = 0;
2826 SecurityBlob->LmChallengeResponse.Length = 0;
2827 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2828 SecurityBlob->LmChallengeResponse.Buffer = 0;
2830 SecurityBlob->NtChallengeResponse.Length =
2831 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2832 SecurityBlob->NtChallengeResponse.MaximumLength =
2833 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2834 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2835 SecurityBlob->NtChallengeResponse.Buffer =
2836 cpu_to_le32(SecurityBlobLength);
2837 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2838 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2840 if (ses->capabilities & CAP_UNICODE) {
2841 if (domain == NULL) {
2842 SecurityBlob->DomainName.Buffer = 0;
2843 SecurityBlob->DomainName.Length = 0;
2844 SecurityBlob->DomainName.MaximumLength = 0;
2847 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2850 SecurityBlob->DomainName.MaximumLength =
2852 SecurityBlob->DomainName.Buffer =
2853 cpu_to_le32(SecurityBlobLength);
2855 SecurityBlobLength += len;
2856 SecurityBlob->DomainName.Length =
2860 SecurityBlob->UserName.Buffer = 0;
2861 SecurityBlob->UserName.Length = 0;
2862 SecurityBlob->UserName.MaximumLength = 0;
2865 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2868 SecurityBlob->UserName.MaximumLength =
2870 SecurityBlob->UserName.Buffer =
2871 cpu_to_le32(SecurityBlobLength);
2873 SecurityBlobLength += len;
2874 SecurityBlob->UserName.Length =
2878 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2879 SecurityBlob->WorkstationName.Length *= 2;
2880 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2881 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2882 bcc_ptr += SecurityBlob->WorkstationName.Length;
2883 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2884 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2886 if ((long) bcc_ptr % 2) {
2891 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2893 bcc_ptr += 2 * bytes_returned;
2895 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2897 bcc_ptr += 2 * bytes_returned;
2898 bcc_ptr += 2; /* null term version string */
2900 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2902 bcc_ptr += 2 * bytes_returned;
2905 bcc_ptr += 2; /* null terminate network opsys string */
2908 bcc_ptr += 2; /* null domain */
2909 } else { /* ASCII */
2910 if (domain == NULL) {
2911 SecurityBlob->DomainName.Buffer = 0;
2912 SecurityBlob->DomainName.Length = 0;
2913 SecurityBlob->DomainName.MaximumLength = 0;
2916 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2917 strncpy(bcc_ptr, domain, 63);
2918 len = strnlen(domain, 64);
2919 SecurityBlob->DomainName.MaximumLength =
2921 SecurityBlob->DomainName.Buffer =
2922 cpu_to_le32(SecurityBlobLength);
2924 SecurityBlobLength += len;
2925 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2928 SecurityBlob->UserName.Buffer = 0;
2929 SecurityBlob->UserName.Length = 0;
2930 SecurityBlob->UserName.MaximumLength = 0;
2933 strncpy(bcc_ptr, user, 63);
2934 len = strnlen(user, 64);
2935 SecurityBlob->UserName.MaximumLength =
2937 SecurityBlob->UserName.Buffer =
2938 cpu_to_le32(SecurityBlobLength);
2940 SecurityBlobLength += len;
2941 SecurityBlob->UserName.Length = cpu_to_le16(len);
2943 /* BB fill in our workstation name if known BB */
2945 strcpy(bcc_ptr, "Linux version ");
2946 bcc_ptr += strlen("Linux version ");
2947 strcpy(bcc_ptr, system_utsname.release);
2948 bcc_ptr += strlen(system_utsname.release) + 1;
2949 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2950 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2951 bcc_ptr++; /* null domain */
2954 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2955 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2956 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2957 smb_buffer->smb_buf_length += count;
2958 pSMB->req.ByteCount = cpu_to_le16(count);
2960 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2961 &bytes_returned, 1);
2963 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2964 } else if ((smb_buffer_response->WordCount == 3)
2965 || (smb_buffer_response->WordCount == 4)) {
2966 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2968 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2969 if (action & GUEST_LOGIN)
2970 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2971 /* if(SecurityBlob2->MessageType != NtLm??){
2972 cFYI("Unexpected message type on auth response is %d "));
2976 ("Does UID on challenge %d match auth response UID %d ",
2977 ses->Suid, smb_buffer_response->Uid));
2978 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2979 bcc_ptr = pByteArea(smb_buffer_response);
2980 /* response can have either 3 or 4 word count - Samba sends 3 */
2981 if ((pSMBr->resp.hdr.WordCount == 3)
2982 || ((pSMBr->resp.hdr.WordCount == 4)
2984 pSMBr->resp.ByteCount))) {
2985 if (pSMBr->resp.hdr.WordCount == 4) {
2989 ("Security Blob Length %d ",
2994 ("NTLMSSP response to Authenticate "));
2996 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2997 if ((long) (bcc_ptr) % 2) {
2999 (BCC(smb_buffer_response)
3001 bcc_ptr++; /* Unicode strings must be word aligned */
3003 remaining_words = BCC(smb_buffer_response) / 2;
3006 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
3007 /* We look for obvious messed up bcc or strings in response so we do not go off
3008 the end since (at least) WIN2K and Windows XP have a major bug in not null
3009 terminating last Unicode string in response */
3011 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
3012 cifs_strfromUCS_le(ses->serverOS,
3016 bcc_ptr += 2 * (len + 1);
3017 remaining_words -= len + 1;
3018 ses->serverOS[2 * len] = 0;
3019 ses->serverOS[1 + (2 * len)] = 0;
3020 if (remaining_words > 0) {
3021 len = UniStrnlen((wchar_t *)
3026 kcalloc(1, 2 * (len + 1),
3028 cifs_strfromUCS_le(ses->
3034 bcc_ptr += 2 * (len + 1);
3035 ses->serverNOS[2 * len] = 0;
3036 ses->serverNOS[1+(2*len)] = 0;
3037 remaining_words -= len + 1;
3038 if (remaining_words > 0) {
3039 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3040 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3065 } /* else no more room so create dummy domain string */
3067 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
3068 } else { /* no room so create dummy domain and NOS string */
3069 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
3070 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
3072 } else { /* ASCII */
3073 len = strnlen(bcc_ptr, 1024);
3074 if (((long) bcc_ptr + len) -
3075 (long) pByteArea(smb_buffer_response)
3076 <= BCC(smb_buffer_response)) {
3077 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
3078 strncpy(ses->serverOS,bcc_ptr, len);
3081 bcc_ptr[0] = 0; /* null terminate the string */
3084 len = strnlen(bcc_ptr, 1024);
3085 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
3086 strncpy(ses->serverNOS, bcc_ptr, len);
3091 len = strnlen(bcc_ptr, 1024);
3092 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
3093 strncpy(ses->serverDomain, bcc_ptr, len);
3099 ("Variable field of length %d extends beyond end of smb ",
3104 (" Security Blob Length extends beyond end of SMB"));
3107 cERROR(1, ("No session structure passed in."));
3111 (" Invalid Word count %d: ",
3112 smb_buffer_response->WordCount));
3117 cifs_buf_release(smb_buffer);
3123 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3124 const char *tree, struct cifsTconInfo *tcon,
3125 const struct nls_table *nls_codepage)
3127 struct smb_hdr *smb_buffer;
3128 struct smb_hdr *smb_buffer_response;
3131 unsigned char *bcc_ptr;
3139 smb_buffer = cifs_buf_get();
3140 if (smb_buffer == NULL) {
3143 smb_buffer_response = smb_buffer;
3145 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3146 NULL /*no tid */ , 4 /*wct */ );
3148 smb_buffer->Mid = GetNextMid(ses->server);
3149 smb_buffer->Uid = ses->Suid;
3150 pSMB = (TCONX_REQ *) smb_buffer;
3151 pSMBr = (TCONX_RSP *) smb_buffer_response;
3153 pSMB->AndXCommand = 0xFF;
3154 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3155 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3156 bcc_ptr = &pSMB->Password[0];
3157 bcc_ptr++; /* skip password */
3159 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3160 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3162 if (ses->capabilities & CAP_STATUS32) {
3163 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3165 if (ses->capabilities & CAP_DFS) {
3166 smb_buffer->Flags2 |= SMBFLG2_DFS;
3168 if (ses->capabilities & CAP_UNICODE) {
3169 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3171 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
3172 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3173 bcc_ptr += 2; /* skip trailing null */
3174 } else { /* ASCII */
3176 strcpy(bcc_ptr, tree);
3177 bcc_ptr += strlen(tree) + 1;
3179 strcpy(bcc_ptr, "?????");
3180 bcc_ptr += strlen("?????");
3182 count = bcc_ptr - &pSMB->Password[0];
3183 pSMB->hdr.smb_buf_length += count;
3184 pSMB->ByteCount = cpu_to_le16(count);
3186 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3188 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3189 /* above now done in SendReceive */
3190 if ((rc == 0) && (tcon != NULL)) {
3191 tcon->tidStatus = CifsGood;
3192 tcon->tid = smb_buffer_response->Tid;
3193 bcc_ptr = pByteArea(smb_buffer_response);
3194 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3195 /* skip service field (NB: this field is always ASCII) */
3196 bcc_ptr += length + 1;
3197 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3198 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3199 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3200 if ((bcc_ptr + (2 * length)) -
3201 pByteArea(smb_buffer_response) <=
3202 BCC(smb_buffer_response)) {
3203 if(tcon->nativeFileSystem)
3204 kfree(tcon->nativeFileSystem);
3205 tcon->nativeFileSystem =
3206 kcalloc(1, length + 2, GFP_KERNEL);
3207 cifs_strfromUCS_le(tcon->nativeFileSystem,
3208 (wchar_t *) bcc_ptr,
3209 length, nls_codepage);
3210 bcc_ptr += 2 * length;
3211 bcc_ptr[0] = 0; /* null terminate the string */
3215 /* else do not bother copying these informational fields */
3217 length = strnlen(bcc_ptr, 1024);
3218 if ((bcc_ptr + length) -
3219 pByteArea(smb_buffer_response) <=
3220 BCC(smb_buffer_response)) {
3221 if(tcon->nativeFileSystem)
3222 kfree(tcon->nativeFileSystem);
3223 tcon->nativeFileSystem =
3224 kcalloc(1, length + 1, GFP_KERNEL);
3225 strncpy(tcon->nativeFileSystem, bcc_ptr,
3228 /* else do not bother copying these informational fields */
3230 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3231 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3232 } else if ((rc == 0) && tcon == NULL) {
3233 /* all we need to save for IPC$ connection */
3234 ses->ipc_tid = smb_buffer_response->Tid;
3238 cifs_buf_release(smb_buffer);
3243 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3247 struct cifsSesInfo *ses = NULL;
3248 struct task_struct *cifsd_task;
3252 if (cifs_sb->tcon) {
3253 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3254 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3259 tconInfoFree(cifs_sb->tcon);
3260 if ((ses) && (ses->server)) {
3261 /* save off task so we do not refer to ses later */
3262 cifsd_task = ses->server->tsk;
3263 cFYI(1, ("About to do SMBLogoff "));
3264 rc = CIFSSMBLogoff(xid, ses);
3268 } else if (rc == -ESHUTDOWN) {
3269 cFYI(1,("Waking up socket by sending it signal"));
3271 send_sig(SIGKILL,cifsd_task,1);
3272 wait_for_completion(&cifsd_complete);
3275 } /* else - we have an smb session
3276 left on this socket do not kill cifsd */
3278 cFYI(1, ("No session or bad tcon"));
3281 cifs_sb->tcon = NULL;
3283 set_current_state(TASK_INTERRUPTIBLE);
3284 schedule_timeout(HZ / 2);
3290 return rc; /* BB check if we should always return zero here */
3293 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3294 struct nls_table * nls_info)
3297 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3298 int ntlmv2_flag = FALSE;
3301 /* what if server changes its buffer size after dropping the session? */
3302 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3303 rc = CIFSSMBNegotiate(xid, pSesInfo);
3304 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3305 rc = CIFSSMBNegotiate(xid, pSesInfo);
3310 spin_lock(&GlobalMid_Lock);
3311 if(pSesInfo->server->tcpStatus != CifsExiting)
3312 pSesInfo->server->tcpStatus = CifsGood;
3315 spin_unlock(&GlobalMid_Lock);
3321 pSesInfo->capabilities = pSesInfo->server->capabilities;
3322 if(linuxExtEnabled == 0)
3323 pSesInfo->capabilities &= (~CAP_UNIX);
3324 /* pSesInfo->sequence_number = 0;*/
3325 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3326 pSesInfo->server->secMode,
3327 pSesInfo->server->capabilities,
3328 pSesInfo->server->timeZone));
3329 if (extended_security
3330 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3331 && (pSesInfo->server->secType == NTLMSSP)) {
3332 cFYI(1, ("New style sesssetup "));
3333 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3334 NULL /* security blob */,
3335 0 /* blob length */,
3337 } else if (extended_security
3338 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3339 && (pSesInfo->server->secType == RawNTLMSSP)) {
3340 cFYI(1, ("NTLMSSP sesssetup "));
3341 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3348 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3349 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3354 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3356 CalcNTLMv2_response(pSesInfo,v2_response);
3358 cifs_calculate_ntlmv2_mac_key(
3359 pSesInfo->server->mac_signing_key,
3360 response, ntlm_session_key, */
3362 /* BB Put dummy sig in SessSetup PDU? */
3369 SMBNTencrypt(pSesInfo->password,
3370 pSesInfo->server->cryptKey,
3374 cifs_calculate_mac_key(
3375 pSesInfo->server->mac_signing_key,
3377 pSesInfo->password);
3379 /* for better security the weaker lanman hash not sent
3380 in AuthSessSetup so we no longer calculate it */
3382 rc = CIFSNTLMSSPAuthSessSetup(xid,
3388 } else { /* old style NTLM 0.12 session setup */
3389 SMBNTencrypt(pSesInfo->password,
3390 pSesInfo->server->cryptKey,
3394 cifs_calculate_mac_key(
3395 pSesInfo->server->mac_signing_key,
3396 ntlm_session_key, pSesInfo->password);
3398 rc = CIFSSessSetup(xid, pSesInfo,
3399 ntlm_session_key, nls_info);
3402 cERROR(1,("Send error in SessSetup = %d",rc));
3404 cFYI(1,("CIFS Session Established successfully"));
3405 pSesInfo->status = CifsGood;