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 } else if (strnicmp(data, "setuids", 7) == 0) {
1053 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1055 } else if (strnicmp(data, "nohard", 6) == 0) {
1057 } else if (strnicmp(data, "nosoft", 6) == 0) {
1059 } else if (strnicmp(data, "nointr", 6) == 0) {
1061 } else if (strnicmp(data, "intr", 4) == 0) {
1063 } else if (strnicmp(data, "serverino",7) == 0) {
1064 vol->server_ino = 1;
1065 } else if (strnicmp(data, "noserverino",9) == 0) {
1066 vol->server_ino = 0;
1067 } else if (strnicmp(data, "acl",3) == 0) {
1068 vol->no_psx_acl = 0;
1069 } else if (strnicmp(data, "noacl",5) == 0) {
1070 vol->no_psx_acl = 1;
1071 } else if (strnicmp(data, "direct",6) == 0) {
1073 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1075 } else if (strnicmp(data, "in6_addr",8) == 0) {
1076 if (!value || !*value) {
1077 vol->in6_addr = NULL;
1078 } else if (strnlen(value, 49) == 48) {
1079 vol->in6_addr = value;
1081 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1084 } else if (strnicmp(data, "noac", 4) == 0) {
1085 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1087 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1089 if (vol->UNC == NULL) {
1090 if(devname == NULL) {
1091 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1094 if ((temp_len = strnlen(devname, 300)) < 300) {
1095 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1096 if(vol->UNC == NULL)
1098 strcpy(vol->UNC,devname);
1099 if (strncmp(vol->UNC, "//", 2) == 0) {
1102 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1103 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1107 printk(KERN_WARNING "CIFS: UNC name too long\n");
1111 if(vol->UNCip == NULL)
1112 vol->UNCip = &vol->UNC[2];
1117 static struct cifsSesInfo *
1118 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1119 struct in6_addr *target_ip6_addr,
1120 char *userName, struct TCP_Server_Info **psrvTcp)
1122 struct list_head *tmp;
1123 struct cifsSesInfo *ses;
1125 read_lock(&GlobalSMBSeslock);
1127 list_for_each(tmp, &GlobalSMBSessionList) {
1128 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1130 if((target_ip_addr &&
1131 (ses->server->addr.sockAddr.sin_addr.s_addr
1132 == target_ip_addr->s_addr)) || (target_ip6_addr
1133 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1134 target_ip6_addr,sizeof(*target_ip6_addr)))){
1135 /* BB lock server and tcp session and increment use count here?? */
1136 *psrvTcp = ses->server; /* found a match on the TCP session */
1137 /* BB check if reconnection needed */
1139 (ses->userName, userName,
1140 MAX_USERNAME_SIZE) == 0){
1141 read_unlock(&GlobalSMBSeslock);
1142 return ses; /* found exact match on both tcp and SMB sessions */
1146 /* else tcp and smb sessions need reconnection */
1148 read_unlock(&GlobalSMBSeslock);
1152 static struct cifsTconInfo *
1153 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1155 struct list_head *tmp;
1156 struct cifsTconInfo *tcon;
1158 read_lock(&GlobalSMBSeslock);
1159 list_for_each(tmp, &GlobalTreeConnectionList) {
1160 cFYI(1, ("Next tcon - "));
1161 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1163 if (tcon->ses->server) {
1165 (" old ip addr: %x == new ip %x ?",
1166 tcon->ses->server->addr.sockAddr.sin_addr.
1167 s_addr, new_target_ip_addr));
1168 if (tcon->ses->server->addr.sockAddr.sin_addr.
1169 s_addr == new_target_ip_addr) {
1170 /* BB lock tcon and server and tcp session and increment use count here? */
1171 /* found a match on the TCP session */
1172 /* BB check if reconnection needed */
1173 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1174 tcon->treeName, uncName));
1176 (tcon->treeName, uncName,
1177 MAX_TREE_SIZE) == 0) {
1179 ("Matched UNC, old user: %s == new: %s ?",
1180 tcon->treeName, uncName));
1182 (tcon->ses->userName,
1184 MAX_USERNAME_SIZE) == 0) {
1185 read_unlock(&GlobalSMBSeslock);
1186 return tcon;/* also matched user (smb session)*/
1193 read_unlock(&GlobalSMBSeslock);
1198 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1199 const char *old_path, const struct nls_table *nls_codepage,
1202 unsigned char *referrals = NULL;
1203 unsigned int num_referrals;
1206 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1207 &num_referrals, &referrals, remap);
1209 /* BB Add in code to: if valid refrl, if not ip address contact
1210 the helper that resolves tcp names, mount to it, try to
1211 tcon to it unmount it if fail */
1220 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1221 const char *old_path, const struct nls_table *nls_codepage,
1222 unsigned int *pnum_referrals,
1223 unsigned char ** preferrals, int remap)
1228 *pnum_referrals = 0;
1230 if (pSesInfo->ipc_tid == 0) {
1231 temp_unc = kmalloc(2 /* for slashes */ +
1232 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1233 + 1 + 4 /* slash IPC$ */ + 2,
1235 if (temp_unc == NULL)
1239 strcpy(temp_unc + 2, pSesInfo->serverName);
1240 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1241 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1243 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1247 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1248 pnum_referrals, nls_codepage, remap);
1253 /* See RFC1001 section 14 on representation of Netbios names */
1254 static void rfc1002mangle(char * target,char * source, unsigned int length)
1258 for(i=0,j=0;i<(length);i++) {
1259 /* mask a nibble at a time and encode */
1260 target[j] = 'A' + (0x0F & (source[i] >> 4));
1261 target[j+1] = 'A' + (0x0F & source[i]);
1269 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1270 char * netbios_name)
1274 __be16 orig_port = 0;
1276 if(*csocket == NULL) {
1277 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1279 cERROR(1, ("Error %d creating socket",rc));
1283 /* BB other socket options to set KEEPALIVE, NODELAY? */
1284 cFYI(1,("Socket created"));
1285 (*csocket)->sk->sk_allocation = GFP_NOFS;
1289 psin_server->sin_family = AF_INET;
1290 if(psin_server->sin_port) { /* user overrode default port */
1291 rc = (*csocket)->ops->connect(*csocket,
1292 (struct sockaddr *) psin_server,
1293 sizeof (struct sockaddr_in),0);
1299 /* save original port so we can retry user specified port
1300 later if fall back ports fail this time */
1301 orig_port = psin_server->sin_port;
1303 /* do not retry on the same port we just failed on */
1304 if(psin_server->sin_port != htons(CIFS_PORT)) {
1305 psin_server->sin_port = htons(CIFS_PORT);
1307 rc = (*csocket)->ops->connect(*csocket,
1308 (struct sockaddr *) psin_server,
1309 sizeof (struct sockaddr_in),0);
1315 psin_server->sin_port = htons(RFC1001_PORT);
1316 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1317 psin_server, sizeof (struct sockaddr_in),0);
1322 /* give up here - unless we want to retry on different
1323 protocol families some day */
1326 psin_server->sin_port = orig_port;
1327 cFYI(1,("Error %d connecting to server via ipv4",rc));
1328 sock_release(*csocket);
1332 /* Eventually check for other socket options to change from
1333 the default. sock_setsockopt not used because it expects
1334 user space buffer */
1335 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1337 /* send RFC1001 sessinit */
1339 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1340 /* some servers require RFC1001 sessinit before sending
1341 negprot - BB check reconnection in case where second
1342 sessinit is sent but no second negprot */
1343 struct rfc1002_session_packet * ses_init_buf;
1344 struct smb_hdr * smb_buf;
1345 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1347 ses_init_buf->trailer.session_req.called_len = 32;
1348 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1349 DEFAULT_CIFS_CALLED_NAME,16);
1350 ses_init_buf->trailer.session_req.calling_len = 32;
1351 /* calling name ends in null (byte 16) from old smb
1353 if(netbios_name && (netbios_name[0] !=0)) {
1354 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1357 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1358 "LINUX_CIFS_CLNT",16);
1360 ses_init_buf->trailer.session_req.scope1 = 0;
1361 ses_init_buf->trailer.session_req.scope2 = 0;
1362 smb_buf = (struct smb_hdr *)ses_init_buf;
1363 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1364 smb_buf->smb_buf_length = 0x81000044;
1365 rc = smb_send(*csocket, smb_buf, 0x44,
1366 (struct sockaddr *)psin_server);
1367 kfree(ses_init_buf);
1369 /* else the negprot may still work without this
1370 even though malloc failed */
1378 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1382 __be16 orig_port = 0;
1384 if(*csocket == NULL) {
1385 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1387 cERROR(1, ("Error %d creating ipv6 socket",rc));
1391 /* BB other socket options to set KEEPALIVE, NODELAY? */
1392 cFYI(1,("ipv6 Socket created"));
1393 (*csocket)->sk->sk_allocation = GFP_NOFS;
1397 psin_server->sin6_family = AF_INET6;
1399 if(psin_server->sin6_port) { /* user overrode default port */
1400 rc = (*csocket)->ops->connect(*csocket,
1401 (struct sockaddr *) psin_server,
1402 sizeof (struct sockaddr_in6),0);
1408 /* save original port so we can retry user specified port
1409 later if fall back ports fail this time */
1411 orig_port = psin_server->sin6_port;
1412 /* do not retry on the same port we just failed on */
1413 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1414 psin_server->sin6_port = htons(CIFS_PORT);
1416 rc = (*csocket)->ops->connect(*csocket,
1417 (struct sockaddr *) psin_server,
1418 sizeof (struct sockaddr_in6),0);
1424 psin_server->sin6_port = htons(RFC1001_PORT);
1425 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1426 psin_server, sizeof (struct sockaddr_in6),0);
1431 /* give up here - unless we want to retry on different
1432 protocol families some day */
1435 psin_server->sin6_port = orig_port;
1436 cFYI(1,("Error %d connecting to server via ipv6",rc));
1437 sock_release(*csocket);
1441 /* Eventually check for other socket options to change from
1442 the default. sock_setsockopt not used because it expects
1443 user space buffer */
1444 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1450 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1451 char *mount_data, const char *devname)
1455 int address_type = AF_INET;
1456 struct socket *csocket = NULL;
1457 struct sockaddr_in sin_server;
1458 struct sockaddr_in6 sin_server6;
1459 struct smb_vol volume_info;
1460 struct cifsSesInfo *pSesInfo = NULL;
1461 struct cifsSesInfo *existingCifsSes = NULL;
1462 struct cifsTconInfo *tcon = NULL;
1463 struct TCP_Server_Info *srvTcp = NULL;
1467 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1469 memset(&volume_info,0,sizeof(struct smb_vol));
1470 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1472 kfree(volume_info.UNC);
1473 if(volume_info.password)
1474 kfree(volume_info.password);
1479 if (volume_info.username) {
1480 /* BB fixme parse for domain name here */
1481 cFYI(1, ("Username: %s ", volume_info.username));
1484 cifserror("No username specified ");
1485 /* In userspace mount helper we can get user name from alternate
1486 locations such as env variables and files on disk */
1488 kfree(volume_info.UNC);
1489 if(volume_info.password)
1490 kfree(volume_info.password);
1495 if (volume_info.UNCip && volume_info.UNC) {
1496 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1499 /* not ipv4 address, try ipv6 */
1500 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1502 address_type = AF_INET6;
1504 address_type = AF_INET;
1508 /* we failed translating address */
1510 kfree(volume_info.UNC);
1511 if(volume_info.password)
1512 kfree(volume_info.password);
1517 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1520 } else if (volume_info.UNCip){
1521 /* BB using ip addr as server name connect to the DFS root below */
1522 cERROR(1,("Connecting to DFS root not implemented yet"));
1524 kfree(volume_info.UNC);
1525 if(volume_info.password)
1526 kfree(volume_info.password);
1529 } else /* which servers DFS root would we conect to */ {
1531 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1533 kfree(volume_info.UNC);
1534 if(volume_info.password)
1535 kfree(volume_info.password);
1540 /* this is needed for ASCII cp to Unicode converts */
1541 if(volume_info.iocharset == NULL) {
1542 cifs_sb->local_nls = load_nls_default();
1543 /* load_nls_default can not return null */
1545 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1546 if(cifs_sb->local_nls == NULL) {
1547 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1549 kfree(volume_info.UNC);
1550 if(volume_info.password)
1551 kfree(volume_info.password);
1557 if(address_type == AF_INET)
1558 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1559 NULL /* no ipv6 addr */,
1560 volume_info.username, &srvTcp);
1561 else if(address_type == AF_INET6)
1562 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1563 &sin_server6.sin6_addr,
1564 volume_info.username, &srvTcp);
1567 kfree(volume_info.UNC);
1568 if(volume_info.password)
1569 kfree(volume_info.password);
1576 cFYI(1, ("Existing tcp session with server found "));
1577 } else { /* create socket */
1578 if(volume_info.port)
1579 sin_server.sin_port = htons(volume_info.port);
1581 sin_server.sin_port = 0;
1582 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1585 ("Error connecting to IPv4 socket. Aborting operation"));
1587 sock_release(csocket);
1589 kfree(volume_info.UNC);
1590 if(volume_info.password)
1591 kfree(volume_info.password);
1596 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1597 if (srvTcp == NULL) {
1599 sock_release(csocket);
1601 kfree(volume_info.UNC);
1602 if(volume_info.password)
1603 kfree(volume_info.password);
1607 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1608 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1609 atomic_set(&srvTcp->inFlight,0);
1610 /* BB Add code for ipv6 case too */
1611 srvTcp->ssocket = csocket;
1612 srvTcp->protocolType = IPV4;
1613 init_waitqueue_head(&srvTcp->response_q);
1614 init_waitqueue_head(&srvTcp->request_q);
1615 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1616 /* at this point we are the only ones with the pointer
1617 to the struct since the kernel thread not created yet
1618 so no need to spinlock this init of tcpStatus */
1619 srvTcp->tcpStatus = CifsNew;
1620 init_MUTEX(&srvTcp->tcpSem);
1621 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1622 CLONE_FS | CLONE_FILES | CLONE_VM);
1625 sock_release(csocket);
1627 kfree(volume_info.UNC);
1628 if(volume_info.password)
1629 kfree(volume_info.password);
1633 wait_for_completion(&cifsd_complete);
1635 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1636 srvTcp->sequence_number = 0;
1640 if (existingCifsSes) {
1641 pSesInfo = existingCifsSes;
1642 cFYI(1, ("Existing smb sess found "));
1643 if(volume_info.password)
1644 kfree(volume_info.password);
1645 /* volume_info.UNC freed at end of function */
1647 cFYI(1, ("Existing smb sess not found "));
1648 pSesInfo = sesInfoAlloc();
1649 if (pSesInfo == NULL)
1652 pSesInfo->server = srvTcp;
1653 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1654 NIPQUAD(sin_server.sin_addr.s_addr));
1658 /* volume_info.password freed at unmount */
1659 if (volume_info.password)
1660 pSesInfo->password = volume_info.password;
1661 if (volume_info.username)
1662 strncpy(pSesInfo->userName,
1663 volume_info.username,MAX_USERNAME_SIZE);
1664 if (volume_info.domainname)
1665 strncpy(pSesInfo->domainName,
1666 volume_info.domainname,MAX_USERNAME_SIZE);
1667 pSesInfo->linux_uid = volume_info.linux_uid;
1668 down(&pSesInfo->sesSem);
1669 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1670 up(&pSesInfo->sesSem);
1672 atomic_inc(&srvTcp->socketUseCount);
1674 if(volume_info.password)
1675 kfree(volume_info.password);
1678 /* search for existing tcon to this server share */
1680 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1681 cifs_sb->rsize = volume_info.rsize;
1683 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1684 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1685 cifs_sb->wsize = volume_info.wsize;
1687 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1688 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1689 cifs_sb->rsize = PAGE_CACHE_SIZE;
1690 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1692 cifs_sb->mnt_uid = volume_info.linux_uid;
1693 cifs_sb->mnt_gid = volume_info.linux_gid;
1694 cifs_sb->mnt_file_mode = volume_info.file_mode;
1695 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1696 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1698 if(volume_info.noperm)
1699 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1700 if(volume_info.setuids)
1701 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1702 if(volume_info.server_ino)
1703 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1704 if(volume_info.remap)
1705 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1706 if(volume_info.no_xattr)
1707 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1708 if(volume_info.sfu_emul)
1709 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1710 if(volume_info.nocase)
1711 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CASE_INSENS;
1712 if(volume_info.nobrl)
1713 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1715 if(volume_info.direct_io) {
1716 cFYI(1,("mounting share using direct i/o"));
1717 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1721 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1722 volume_info.username);
1724 cFYI(1, ("Found match on UNC path "));
1725 /* we can have only one retry value for a connection
1726 to a share so for resources mounted more than once
1727 to the same server share the last value passed in
1728 for the retry flag is used */
1729 tcon->retry = volume_info.retry;
1731 tcon = tconInfoAlloc();
1735 /* check for null share name ie connect to dfs root */
1737 /* BB check if this works for exactly length three strings */
1738 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1739 && (strchr(volume_info.UNC + 3, '/') ==
1741 rc = connect_to_dfs_path(xid, pSesInfo,
1742 "", cifs_sb->local_nls,
1743 cifs_sb->mnt_cifs_flags &
1744 CIFS_MOUNT_MAP_SPECIAL_CHR);
1746 kfree(volume_info.UNC);
1750 rc = CIFSTCon(xid, pSesInfo,
1752 tcon, cifs_sb->local_nls);
1753 cFYI(1, ("CIFS Tcon rc = %d", rc));
1756 atomic_inc(&pSesInfo->inUse);
1757 tcon->retry = volume_info.retry;
1763 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1764 sb->s_maxbytes = (u64) 1 << 63;
1766 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1769 sb->s_time_gran = 100;
1771 /* on error free sesinfo and tcon struct if needed */
1773 /* if session setup failed, use count is zero but
1774 we still need to free cifsd thread */
1775 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1776 spin_lock(&GlobalMid_Lock);
1777 srvTcp->tcpStatus = CifsExiting;
1778 spin_unlock(&GlobalMid_Lock);
1780 send_sig(SIGKILL,srvTcp->tsk,1);
1781 wait_for_completion(&cifsd_complete);
1784 /* If find_unc succeeded then rc == 0 so we can not end */
1785 if (tcon) /* up accidently freeing someone elses tcon struct */
1787 if (existingCifsSes == NULL) {
1789 if ((pSesInfo->server) &&
1790 (pSesInfo->status == CifsGood)) {
1792 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1793 /* if the socketUseCount is now zero */
1794 if((temp_rc == -ESHUTDOWN) &&
1795 (pSesInfo->server->tsk)) {
1796 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1797 wait_for_completion(&cifsd_complete);
1800 cFYI(1, ("No session or bad tcon"));
1801 sesInfoFree(pSesInfo);
1802 /* pSesInfo = NULL; */
1806 atomic_inc(&tcon->useCount);
1807 cifs_sb->tcon = tcon;
1808 tcon->ses = pSesInfo;
1810 /* do not care if following two calls succeed - informational only */
1811 CIFSSMBQFSDeviceInfo(xid, tcon);
1812 CIFSSMBQFSAttributeInfo(xid, tcon);
1813 if (tcon->ses->capabilities & CAP_UNIX) {
1814 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1815 if(!volume_info.no_psx_acl) {
1816 if(CIFS_UNIX_POSIX_ACL_CAP &
1817 le64_to_cpu(tcon->fsUnixInfo.Capability))
1818 cFYI(1,("server negotiated posix acl support"));
1819 sb->s_flags |= MS_POSIXACL;
1822 /* Try and negotiate POSIX pathnames if we can. */
1823 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
1824 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1825 if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
1826 cFYI(1,("negotiated posix pathnames support"));
1827 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
1829 cFYI(1,("posix pathnames support requested but not supported"));
1836 /* volume_info.password is freed above when existing session found
1837 (in which case it is not needed anymore) but when new sesion is created
1838 the password ptr is put in the new session structure (in which case the
1839 password will be freed at unmount time) */
1841 kfree(volume_info.UNC);
1847 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1848 char session_key[CIFS_SESSION_KEY_SIZE],
1849 const struct nls_table *nls_codepage)
1851 struct smb_hdr *smb_buffer;
1852 struct smb_hdr *smb_buffer_response;
1853 SESSION_SETUP_ANDX *pSMB;
1854 SESSION_SETUP_ANDX *pSMBr;
1859 int remaining_words = 0;
1860 int bytes_returned = 0;
1865 cFYI(1, ("In sesssetup "));
1868 user = ses->userName;
1869 domain = ses->domainName;
1870 smb_buffer = cifs_buf_get();
1871 if (smb_buffer == NULL) {
1874 smb_buffer_response = smb_buffer;
1875 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1877 /* send SMBsessionSetup here */
1878 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1879 NULL /* no tCon exists yet */ , 13 /* wct */ );
1881 smb_buffer->Mid = GetNextMid(ses->server);
1882 pSMB->req_no_secext.AndXCommand = 0xFF;
1883 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1884 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1886 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1887 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1889 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1890 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1891 if (ses->capabilities & CAP_UNICODE) {
1892 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1893 capabilities |= CAP_UNICODE;
1895 if (ses->capabilities & CAP_STATUS32) {
1896 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1897 capabilities |= CAP_STATUS32;
1899 if (ses->capabilities & CAP_DFS) {
1900 smb_buffer->Flags2 |= SMBFLG2_DFS;
1901 capabilities |= CAP_DFS;
1903 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1905 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1906 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1908 pSMB->req_no_secext.CaseSensitivePasswordLength =
1909 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1910 bcc_ptr = pByteArea(smb_buffer);
1911 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1912 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1913 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1914 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1916 if (ses->capabilities & CAP_UNICODE) {
1917 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1922 bytes_returned = 0; /* skill null user */
1925 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1927 /* convert number of 16 bit words to bytes */
1928 bcc_ptr += 2 * bytes_returned;
1929 bcc_ptr += 2; /* trailing null */
1932 cifs_strtoUCS((wchar_t *) bcc_ptr,
1933 "CIFS_LINUX_DOM", 32, nls_codepage);
1936 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1938 bcc_ptr += 2 * bytes_returned;
1941 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1943 bcc_ptr += 2 * bytes_returned;
1945 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1947 bcc_ptr += 2 * bytes_returned;
1950 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1952 bcc_ptr += 2 * bytes_returned;
1956 strncpy(bcc_ptr, user, 200);
1957 bcc_ptr += strnlen(user, 200);
1961 if (domain == NULL) {
1962 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1963 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1965 strncpy(bcc_ptr, domain, 64);
1966 bcc_ptr += strnlen(domain, 64);
1970 strcpy(bcc_ptr, "Linux version ");
1971 bcc_ptr += strlen("Linux version ");
1972 strcpy(bcc_ptr, system_utsname.release);
1973 bcc_ptr += strlen(system_utsname.release) + 1;
1974 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1975 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1977 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1978 smb_buffer->smb_buf_length += count;
1979 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1981 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1982 &bytes_returned, 1);
1984 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1985 } else if ((smb_buffer_response->WordCount == 3)
1986 || (smb_buffer_response->WordCount == 4)) {
1987 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1988 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1989 if (action & GUEST_LOGIN)
1990 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1991 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1992 cFYI(1, ("UID = %d ", ses->Suid));
1993 /* response can have either 3 or 4 word count - Samba sends 3 */
1994 bcc_ptr = pByteArea(smb_buffer_response);
1995 if ((pSMBr->resp.hdr.WordCount == 3)
1996 || ((pSMBr->resp.hdr.WordCount == 4)
1997 && (blob_len < pSMBr->resp.ByteCount))) {
1998 if (pSMBr->resp.hdr.WordCount == 4)
1999 bcc_ptr += blob_len;
2001 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2002 if ((long) (bcc_ptr) % 2) {
2004 (BCC(smb_buffer_response) - 1) /2;
2005 bcc_ptr++; /* Unicode strings must be word aligned */
2008 BCC(smb_buffer_response) / 2;
2011 UniStrnlen((wchar_t *) bcc_ptr,
2012 remaining_words - 1);
2013 /* We look for obvious messed up bcc or strings in response so we do not go off
2014 the end since (at least) WIN2K and Windows XP have a major bug in not null
2015 terminating last Unicode string in response */
2016 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2017 if(ses->serverOS == NULL)
2018 goto sesssetup_nomem;
2019 cifs_strfromUCS_le(ses->serverOS,
2020 (wchar_t *)bcc_ptr, len,nls_codepage);
2021 bcc_ptr += 2 * (len + 1);
2022 remaining_words -= len + 1;
2023 ses->serverOS[2 * len] = 0;
2024 ses->serverOS[1 + (2 * len)] = 0;
2025 if (remaining_words > 0) {
2026 len = UniStrnlen((wchar_t *)bcc_ptr,
2028 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
2029 if(ses->serverNOS == NULL)
2030 goto sesssetup_nomem;
2031 cifs_strfromUCS_le(ses->serverNOS,
2032 (wchar_t *)bcc_ptr,len,nls_codepage);
2033 bcc_ptr += 2 * (len + 1);
2034 ses->serverNOS[2 * len] = 0;
2035 ses->serverNOS[1 + (2 * len)] = 0;
2036 if(strncmp(ses->serverNOS,
2037 "NT LAN Manager 4",16) == 0) {
2038 cFYI(1,("NT4 server"));
2039 ses->flags |= CIFS_SES_NT4;
2041 remaining_words -= len + 1;
2042 if (remaining_words > 0) {
2043 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2044 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2046 kcalloc(1, 2*(len+1),GFP_KERNEL);
2047 if(ses->serverDomain == NULL)
2048 goto sesssetup_nomem;
2049 cifs_strfromUCS_le(ses->serverDomain,
2050 (wchar_t *)bcc_ptr,len,nls_codepage);
2051 bcc_ptr += 2 * (len + 1);
2052 ses->serverDomain[2*len] = 0;
2053 ses->serverDomain[1+(2*len)] = 0;
2054 } /* else no more room so create dummy domain string */
2057 kcalloc(1, 2, GFP_KERNEL);
2058 } else { /* no room so create dummy domain and NOS string */
2059 /* if these kcallocs fail not much we
2060 can do, but better to not fail the
2063 kcalloc(1, 2, GFP_KERNEL);
2065 kcalloc(1, 2, GFP_KERNEL);
2067 } else { /* ASCII */
2068 len = strnlen(bcc_ptr, 1024);
2069 if (((long) bcc_ptr + len) - (long)
2070 pByteArea(smb_buffer_response)
2071 <= BCC(smb_buffer_response)) {
2072 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2073 if(ses->serverOS == NULL)
2074 goto sesssetup_nomem;
2075 strncpy(ses->serverOS,bcc_ptr, len);
2078 bcc_ptr[0] = 0; /* null terminate the string */
2081 len = strnlen(bcc_ptr, 1024);
2082 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2083 if(ses->serverNOS == NULL)
2084 goto sesssetup_nomem;
2085 strncpy(ses->serverNOS, bcc_ptr, len);
2090 len = strnlen(bcc_ptr, 1024);
2091 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2092 if(ses->serverDomain == NULL)
2093 goto sesssetup_nomem;
2094 strncpy(ses->serverDomain, bcc_ptr, len);
2100 ("Variable field of length %d extends beyond end of smb ",
2105 (" Security Blob Length extends beyond end of SMB"));
2109 (" Invalid Word count %d: ",
2110 smb_buffer_response->WordCount));
2113 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2114 since that could make reconnection harder, and
2115 reconnection might be needed to free memory */
2117 cifs_buf_release(smb_buffer);
2123 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2124 char *SecurityBlob,int SecurityBlobLength,
2125 const struct nls_table *nls_codepage)
2127 struct smb_hdr *smb_buffer;
2128 struct smb_hdr *smb_buffer_response;
2129 SESSION_SETUP_ANDX *pSMB;
2130 SESSION_SETUP_ANDX *pSMBr;
2135 int remaining_words = 0;
2136 int bytes_returned = 0;
2141 cFYI(1, ("In spnego sesssetup "));
2144 user = ses->userName;
2145 domain = ses->domainName;
2147 smb_buffer = cifs_buf_get();
2148 if (smb_buffer == NULL) {
2151 smb_buffer_response = smb_buffer;
2152 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2154 /* send SMBsessionSetup here */
2155 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2156 NULL /* no tCon exists yet */ , 12 /* wct */ );
2158 smb_buffer->Mid = GetNextMid(ses->server);
2159 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2160 pSMB->req.AndXCommand = 0xFF;
2161 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2162 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2164 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2165 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2167 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2168 CAP_EXTENDED_SECURITY;
2169 if (ses->capabilities & CAP_UNICODE) {
2170 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2171 capabilities |= CAP_UNICODE;
2173 if (ses->capabilities & CAP_STATUS32) {
2174 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2175 capabilities |= CAP_STATUS32;
2177 if (ses->capabilities & CAP_DFS) {
2178 smb_buffer->Flags2 |= SMBFLG2_DFS;
2179 capabilities |= CAP_DFS;
2181 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2183 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2184 bcc_ptr = pByteArea(smb_buffer);
2185 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2186 bcc_ptr += SecurityBlobLength;
2188 if (ses->capabilities & CAP_UNICODE) {
2189 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2194 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
2195 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2196 bcc_ptr += 2; /* trailing null */
2199 cifs_strtoUCS((wchar_t *) bcc_ptr,
2200 "CIFS_LINUX_DOM", 32, nls_codepage);
2203 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2205 bcc_ptr += 2 * bytes_returned;
2208 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2210 bcc_ptr += 2 * bytes_returned;
2212 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2214 bcc_ptr += 2 * bytes_returned;
2217 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2219 bcc_ptr += 2 * bytes_returned;
2222 strncpy(bcc_ptr, user, 200);
2223 bcc_ptr += strnlen(user, 200);
2226 if (domain == NULL) {
2227 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2228 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2230 strncpy(bcc_ptr, domain, 64);
2231 bcc_ptr += strnlen(domain, 64);
2235 strcpy(bcc_ptr, "Linux version ");
2236 bcc_ptr += strlen("Linux version ");
2237 strcpy(bcc_ptr, system_utsname.release);
2238 bcc_ptr += strlen(system_utsname.release) + 1;
2239 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2240 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2242 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2243 smb_buffer->smb_buf_length += count;
2244 pSMB->req.ByteCount = cpu_to_le16(count);
2246 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2247 &bytes_returned, 1);
2249 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2250 } else if ((smb_buffer_response->WordCount == 3)
2251 || (smb_buffer_response->WordCount == 4)) {
2252 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2254 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2255 if (action & GUEST_LOGIN)
2256 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2258 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2259 cFYI(1, ("UID = %d ", ses->Suid));
2260 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2262 /* BB Fix below to make endian neutral !! */
2264 if ((pSMBr->resp.hdr.WordCount == 3)
2265 || ((pSMBr->resp.hdr.WordCount == 4)
2267 pSMBr->resp.ByteCount))) {
2268 if (pSMBr->resp.hdr.WordCount == 4) {
2272 ("Security Blob Length %d ",
2276 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2277 if ((long) (bcc_ptr) % 2) {
2279 (BCC(smb_buffer_response)
2281 bcc_ptr++; /* Unicode strings must be word aligned */
2285 (smb_buffer_response) / 2;
2288 UniStrnlen((wchar_t *) bcc_ptr,
2289 remaining_words - 1);
2290 /* We look for obvious messed up bcc or strings in response so we do not go off
2291 the end since (at least) WIN2K and Windows XP have a major bug in not null
2292 terminating last Unicode string in response */
2294 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2295 cifs_strfromUCS_le(ses->serverOS,
2299 bcc_ptr += 2 * (len + 1);
2300 remaining_words -= len + 1;
2301 ses->serverOS[2 * len] = 0;
2302 ses->serverOS[1 + (2 * len)] = 0;
2303 if (remaining_words > 0) {
2304 len = UniStrnlen((wchar_t *)bcc_ptr,
2308 kcalloc(1, 2 * (len + 1),
2310 cifs_strfromUCS_le(ses->serverNOS,
2314 bcc_ptr += 2 * (len + 1);
2315 ses->serverNOS[2 * len] = 0;
2316 ses->serverNOS[1 + (2 * len)] = 0;
2317 remaining_words -= len + 1;
2318 if (remaining_words > 0) {
2319 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2320 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2321 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2322 cifs_strfromUCS_le(ses->serverDomain,
2326 bcc_ptr += 2*(len+1);
2327 ses->serverDomain[2*len] = 0;
2328 ses->serverDomain[1+(2*len)] = 0;
2329 } /* else no more room so create dummy domain string */
2332 kcalloc(1, 2,GFP_KERNEL);
2333 } else { /* no room so create dummy domain and NOS string */
2334 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2335 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2337 } else { /* ASCII */
2339 len = strnlen(bcc_ptr, 1024);
2340 if (((long) bcc_ptr + len) - (long)
2341 pByteArea(smb_buffer_response)
2342 <= BCC(smb_buffer_response)) {
2343 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2344 strncpy(ses->serverOS, bcc_ptr, len);
2347 bcc_ptr[0] = 0; /* null terminate the string */
2350 len = strnlen(bcc_ptr, 1024);
2351 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2352 strncpy(ses->serverNOS, bcc_ptr, len);
2357 len = strnlen(bcc_ptr, 1024);
2358 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2359 strncpy(ses->serverDomain, bcc_ptr, len);
2365 ("Variable field of length %d extends beyond end of smb ",
2370 (" Security Blob Length extends beyond end of SMB"));
2373 cERROR(1, ("No session structure passed in."));
2377 (" Invalid Word count %d: ",
2378 smb_buffer_response->WordCount));
2383 cifs_buf_release(smb_buffer);
2389 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2390 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2391 const struct nls_table *nls_codepage)
2393 struct smb_hdr *smb_buffer;
2394 struct smb_hdr *smb_buffer_response;
2395 SESSION_SETUP_ANDX *pSMB;
2396 SESSION_SETUP_ANDX *pSMBr;
2400 int remaining_words = 0;
2401 int bytes_returned = 0;
2403 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2404 PNEGOTIATE_MESSAGE SecurityBlob;
2405 PCHALLENGE_MESSAGE SecurityBlob2;
2406 __u32 negotiate_flags, capabilities;
2409 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2412 domain = ses->domainName;
2413 *pNTLMv2_flag = FALSE;
2414 smb_buffer = cifs_buf_get();
2415 if (smb_buffer == NULL) {
2418 smb_buffer_response = smb_buffer;
2419 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2420 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2422 /* send SMBsessionSetup here */
2423 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2424 NULL /* no tCon exists yet */ , 12 /* wct */ );
2426 smb_buffer->Mid = GetNextMid(ses->server);
2427 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2428 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2430 pSMB->req.AndXCommand = 0xFF;
2431 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2432 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2434 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2435 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2437 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2438 CAP_EXTENDED_SECURITY;
2439 if (ses->capabilities & CAP_UNICODE) {
2440 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2441 capabilities |= CAP_UNICODE;
2443 if (ses->capabilities & CAP_STATUS32) {
2444 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2445 capabilities |= CAP_STATUS32;
2447 if (ses->capabilities & CAP_DFS) {
2448 smb_buffer->Flags2 |= SMBFLG2_DFS;
2449 capabilities |= CAP_DFS;
2451 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2453 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2454 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2455 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2456 SecurityBlob->MessageType = NtLmNegotiate;
2458 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2459 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2460 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2462 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2464 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2465 /* setup pointers to domain name and workstation name */
2466 bcc_ptr += SecurityBlobLength;
2468 SecurityBlob->WorkstationName.Buffer = 0;
2469 SecurityBlob->WorkstationName.Length = 0;
2470 SecurityBlob->WorkstationName.MaximumLength = 0;
2472 if (domain == NULL) {
2473 SecurityBlob->DomainName.Buffer = 0;
2474 SecurityBlob->DomainName.Length = 0;
2475 SecurityBlob->DomainName.MaximumLength = 0;
2478 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2479 strncpy(bcc_ptr, domain, 63);
2480 len = strnlen(domain, 64);
2481 SecurityBlob->DomainName.MaximumLength =
2483 SecurityBlob->DomainName.Buffer =
2484 cpu_to_le32((long) &SecurityBlob->
2486 (long) &SecurityBlob->Signature);
2488 SecurityBlobLength += len;
2489 SecurityBlob->DomainName.Length =
2492 if (ses->capabilities & CAP_UNICODE) {
2493 if ((long) bcc_ptr % 2) {
2499 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2501 bcc_ptr += 2 * bytes_returned;
2503 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2505 bcc_ptr += 2 * bytes_returned;
2506 bcc_ptr += 2; /* null terminate Linux version */
2508 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2510 bcc_ptr += 2 * bytes_returned;
2513 bcc_ptr += 2; /* null terminate network opsys string */
2516 bcc_ptr += 2; /* null domain */
2517 } else { /* ASCII */
2518 strcpy(bcc_ptr, "Linux version ");
2519 bcc_ptr += strlen("Linux version ");
2520 strcpy(bcc_ptr, system_utsname.release);
2521 bcc_ptr += strlen(system_utsname.release) + 1;
2522 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2523 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2524 bcc_ptr++; /* empty domain field */
2527 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2528 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2529 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2530 smb_buffer->smb_buf_length += count;
2531 pSMB->req.ByteCount = cpu_to_le16(count);
2533 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2534 &bytes_returned, 1);
2536 if (smb_buffer_response->Status.CifsError ==
2537 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2541 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2542 } else if ((smb_buffer_response->WordCount == 3)
2543 || (smb_buffer_response->WordCount == 4)) {
2544 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2545 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2547 if (action & GUEST_LOGIN)
2548 cFYI(1, (" Guest login"));
2549 /* Do we want to set anything in SesInfo struct when guest login? */
2551 bcc_ptr = pByteArea(smb_buffer_response);
2552 /* response can have either 3 or 4 word count - Samba sends 3 */
2554 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2555 if (SecurityBlob2->MessageType != NtLmChallenge) {
2557 ("Unexpected NTLMSSP message type received %d",
2558 SecurityBlob2->MessageType));
2560 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2561 cFYI(1, ("UID = %d ", ses->Suid));
2562 if ((pSMBr->resp.hdr.WordCount == 3)
2563 || ((pSMBr->resp.hdr.WordCount == 4)
2565 pSMBr->resp.ByteCount))) {
2567 if (pSMBr->resp.hdr.WordCount == 4) {
2568 bcc_ptr += blob_len;
2570 ("Security Blob Length %d ",
2574 cFYI(1, ("NTLMSSP Challenge rcvd "));
2576 memcpy(ses->server->cryptKey,
2577 SecurityBlob2->Challenge,
2578 CIFS_CRYPTO_KEY_SIZE);
2579 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2580 *pNTLMv2_flag = TRUE;
2582 if((SecurityBlob2->NegotiateFlags &
2583 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2584 || (sign_CIFS_PDUs > 1))
2585 ses->server->secMode |=
2586 SECMODE_SIGN_REQUIRED;
2587 if ((SecurityBlob2->NegotiateFlags &
2588 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2589 ses->server->secMode |=
2590 SECMODE_SIGN_ENABLED;
2592 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2593 if ((long) (bcc_ptr) % 2) {
2595 (BCC(smb_buffer_response)
2597 bcc_ptr++; /* Unicode strings must be word aligned */
2601 (smb_buffer_response) / 2;
2604 UniStrnlen((wchar_t *) bcc_ptr,
2605 remaining_words - 1);
2606 /* We look for obvious messed up bcc or strings in response so we do not go off
2607 the end since (at least) WIN2K and Windows XP have a major bug in not null
2608 terminating last Unicode string in response */
2610 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2611 cifs_strfromUCS_le(ses->serverOS,
2615 bcc_ptr += 2 * (len + 1);
2616 remaining_words -= len + 1;
2617 ses->serverOS[2 * len] = 0;
2618 ses->serverOS[1 + (2 * len)] = 0;
2619 if (remaining_words > 0) {
2620 len = UniStrnlen((wchar_t *)
2625 kcalloc(1, 2 * (len + 1),
2627 cifs_strfromUCS_le(ses->
2633 bcc_ptr += 2 * (len + 1);
2634 ses->serverNOS[2 * len] = 0;
2637 remaining_words -= len + 1;
2638 if (remaining_words > 0) {
2639 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2640 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2665 } /* else no more room so create dummy domain string */
2670 } else { /* no room so create dummy domain and NOS string */
2672 kcalloc(1, 2, GFP_KERNEL);
2674 kcalloc(1, 2, GFP_KERNEL);
2676 } else { /* ASCII */
2677 len = strnlen(bcc_ptr, 1024);
2678 if (((long) bcc_ptr + len) - (long)
2679 pByteArea(smb_buffer_response)
2680 <= BCC(smb_buffer_response)) {
2684 strncpy(ses->serverOS,
2688 bcc_ptr[0] = 0; /* null terminate string */
2691 len = strnlen(bcc_ptr, 1024);
2695 strncpy(ses->serverNOS, bcc_ptr, len);
2700 len = strnlen(bcc_ptr, 1024);
2704 strncpy(ses->serverDomain, bcc_ptr, len);
2710 ("Variable field of length %d extends beyond end of smb ",
2715 (" Security Blob Length extends beyond end of SMB"));
2718 cERROR(1, ("No session structure passed in."));
2722 (" Invalid Word count %d: ",
2723 smb_buffer_response->WordCount));
2728 cifs_buf_release(smb_buffer);
2733 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2734 char *ntlm_session_key, int ntlmv2_flag,
2735 const struct nls_table *nls_codepage)
2737 struct smb_hdr *smb_buffer;
2738 struct smb_hdr *smb_buffer_response;
2739 SESSION_SETUP_ANDX *pSMB;
2740 SESSION_SETUP_ANDX *pSMBr;
2745 int remaining_words = 0;
2746 int bytes_returned = 0;
2748 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2749 PAUTHENTICATE_MESSAGE SecurityBlob;
2750 __u32 negotiate_flags, capabilities;
2753 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2756 user = ses->userName;
2757 domain = ses->domainName;
2758 smb_buffer = cifs_buf_get();
2759 if (smb_buffer == NULL) {
2762 smb_buffer_response = smb_buffer;
2763 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2764 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2766 /* send SMBsessionSetup here */
2767 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2768 NULL /* no tCon exists yet */ , 12 /* wct */ );
2770 smb_buffer->Mid = GetNextMid(ses->server);
2771 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2772 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2773 pSMB->req.AndXCommand = 0xFF;
2774 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2775 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2777 pSMB->req.hdr.Uid = ses->Suid;
2779 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2780 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2782 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2783 CAP_EXTENDED_SECURITY;
2784 if (ses->capabilities & CAP_UNICODE) {
2785 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2786 capabilities |= CAP_UNICODE;
2788 if (ses->capabilities & CAP_STATUS32) {
2789 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2790 capabilities |= CAP_STATUS32;
2792 if (ses->capabilities & CAP_DFS) {
2793 smb_buffer->Flags2 |= SMBFLG2_DFS;
2794 capabilities |= CAP_DFS;
2796 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2798 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2799 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2800 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2801 SecurityBlob->MessageType = NtLmAuthenticate;
2802 bcc_ptr += SecurityBlobLength;
2804 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2805 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2806 0x80000000 | NTLMSSP_NEGOTIATE_128;
2808 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2810 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2812 /* setup pointers to domain name and workstation name */
2814 SecurityBlob->WorkstationName.Buffer = 0;
2815 SecurityBlob->WorkstationName.Length = 0;
2816 SecurityBlob->WorkstationName.MaximumLength = 0;
2817 SecurityBlob->SessionKey.Length = 0;
2818 SecurityBlob->SessionKey.MaximumLength = 0;
2819 SecurityBlob->SessionKey.Buffer = 0;
2821 SecurityBlob->LmChallengeResponse.Length = 0;
2822 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2823 SecurityBlob->LmChallengeResponse.Buffer = 0;
2825 SecurityBlob->NtChallengeResponse.Length =
2826 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2827 SecurityBlob->NtChallengeResponse.MaximumLength =
2828 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2829 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2830 SecurityBlob->NtChallengeResponse.Buffer =
2831 cpu_to_le32(SecurityBlobLength);
2832 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2833 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2835 if (ses->capabilities & CAP_UNICODE) {
2836 if (domain == NULL) {
2837 SecurityBlob->DomainName.Buffer = 0;
2838 SecurityBlob->DomainName.Length = 0;
2839 SecurityBlob->DomainName.MaximumLength = 0;
2842 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2845 SecurityBlob->DomainName.MaximumLength =
2847 SecurityBlob->DomainName.Buffer =
2848 cpu_to_le32(SecurityBlobLength);
2850 SecurityBlobLength += len;
2851 SecurityBlob->DomainName.Length =
2855 SecurityBlob->UserName.Buffer = 0;
2856 SecurityBlob->UserName.Length = 0;
2857 SecurityBlob->UserName.MaximumLength = 0;
2860 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2863 SecurityBlob->UserName.MaximumLength =
2865 SecurityBlob->UserName.Buffer =
2866 cpu_to_le32(SecurityBlobLength);
2868 SecurityBlobLength += len;
2869 SecurityBlob->UserName.Length =
2873 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2874 SecurityBlob->WorkstationName.Length *= 2;
2875 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2876 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2877 bcc_ptr += SecurityBlob->WorkstationName.Length;
2878 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2879 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2881 if ((long) bcc_ptr % 2) {
2886 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2888 bcc_ptr += 2 * bytes_returned;
2890 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2892 bcc_ptr += 2 * bytes_returned;
2893 bcc_ptr += 2; /* null term version string */
2895 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2897 bcc_ptr += 2 * bytes_returned;
2900 bcc_ptr += 2; /* null terminate network opsys string */
2903 bcc_ptr += 2; /* null domain */
2904 } else { /* ASCII */
2905 if (domain == NULL) {
2906 SecurityBlob->DomainName.Buffer = 0;
2907 SecurityBlob->DomainName.Length = 0;
2908 SecurityBlob->DomainName.MaximumLength = 0;
2911 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2912 strncpy(bcc_ptr, domain, 63);
2913 len = strnlen(domain, 64);
2914 SecurityBlob->DomainName.MaximumLength =
2916 SecurityBlob->DomainName.Buffer =
2917 cpu_to_le32(SecurityBlobLength);
2919 SecurityBlobLength += len;
2920 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2923 SecurityBlob->UserName.Buffer = 0;
2924 SecurityBlob->UserName.Length = 0;
2925 SecurityBlob->UserName.MaximumLength = 0;
2928 strncpy(bcc_ptr, user, 63);
2929 len = strnlen(user, 64);
2930 SecurityBlob->UserName.MaximumLength =
2932 SecurityBlob->UserName.Buffer =
2933 cpu_to_le32(SecurityBlobLength);
2935 SecurityBlobLength += len;
2936 SecurityBlob->UserName.Length = cpu_to_le16(len);
2938 /* BB fill in our workstation name if known BB */
2940 strcpy(bcc_ptr, "Linux version ");
2941 bcc_ptr += strlen("Linux version ");
2942 strcpy(bcc_ptr, system_utsname.release);
2943 bcc_ptr += strlen(system_utsname.release) + 1;
2944 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2945 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2946 bcc_ptr++; /* null domain */
2949 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2950 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2951 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2952 smb_buffer->smb_buf_length += count;
2953 pSMB->req.ByteCount = cpu_to_le16(count);
2955 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2956 &bytes_returned, 1);
2958 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2959 } else if ((smb_buffer_response->WordCount == 3)
2960 || (smb_buffer_response->WordCount == 4)) {
2961 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2963 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2964 if (action & GUEST_LOGIN)
2965 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2966 /* if(SecurityBlob2->MessageType != NtLm??){
2967 cFYI("Unexpected message type on auth response is %d "));
2971 ("Does UID on challenge %d match auth response UID %d ",
2972 ses->Suid, smb_buffer_response->Uid));
2973 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2974 bcc_ptr = pByteArea(smb_buffer_response);
2975 /* response can have either 3 or 4 word count - Samba sends 3 */
2976 if ((pSMBr->resp.hdr.WordCount == 3)
2977 || ((pSMBr->resp.hdr.WordCount == 4)
2979 pSMBr->resp.ByteCount))) {
2980 if (pSMBr->resp.hdr.WordCount == 4) {
2984 ("Security Blob Length %d ",
2989 ("NTLMSSP response to Authenticate "));
2991 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2992 if ((long) (bcc_ptr) % 2) {
2994 (BCC(smb_buffer_response)
2996 bcc_ptr++; /* Unicode strings must be word aligned */
2998 remaining_words = BCC(smb_buffer_response) / 2;
3001 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
3002 /* We look for obvious messed up bcc or strings in response so we do not go off
3003 the end since (at least) WIN2K and Windows XP have a major bug in not null
3004 terminating last Unicode string in response */
3006 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
3007 cifs_strfromUCS_le(ses->serverOS,
3011 bcc_ptr += 2 * (len + 1);
3012 remaining_words -= len + 1;
3013 ses->serverOS[2 * len] = 0;
3014 ses->serverOS[1 + (2 * len)] = 0;
3015 if (remaining_words > 0) {
3016 len = UniStrnlen((wchar_t *)
3021 kcalloc(1, 2 * (len + 1),
3023 cifs_strfromUCS_le(ses->
3029 bcc_ptr += 2 * (len + 1);
3030 ses->serverNOS[2 * len] = 0;
3031 ses->serverNOS[1+(2*len)] = 0;
3032 remaining_words -= len + 1;
3033 if (remaining_words > 0) {
3034 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3035 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3060 } /* else no more room so create dummy domain string */
3062 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
3063 } else { /* no room so create dummy domain and NOS string */
3064 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
3065 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
3067 } else { /* ASCII */
3068 len = strnlen(bcc_ptr, 1024);
3069 if (((long) bcc_ptr + len) -
3070 (long) pByteArea(smb_buffer_response)
3071 <= BCC(smb_buffer_response)) {
3072 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
3073 strncpy(ses->serverOS,bcc_ptr, len);
3076 bcc_ptr[0] = 0; /* null terminate the string */
3079 len = strnlen(bcc_ptr, 1024);
3080 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
3081 strncpy(ses->serverNOS, bcc_ptr, len);
3086 len = strnlen(bcc_ptr, 1024);
3087 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
3088 strncpy(ses->serverDomain, bcc_ptr, len);
3094 ("Variable field of length %d extends beyond end of smb ",
3099 (" Security Blob Length extends beyond end of SMB"));
3102 cERROR(1, ("No session structure passed in."));
3106 (" Invalid Word count %d: ",
3107 smb_buffer_response->WordCount));
3112 cifs_buf_release(smb_buffer);
3118 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3119 const char *tree, struct cifsTconInfo *tcon,
3120 const struct nls_table *nls_codepage)
3122 struct smb_hdr *smb_buffer;
3123 struct smb_hdr *smb_buffer_response;
3126 unsigned char *bcc_ptr;
3134 smb_buffer = cifs_buf_get();
3135 if (smb_buffer == NULL) {
3138 smb_buffer_response = smb_buffer;
3140 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3141 NULL /*no tid */ , 4 /*wct */ );
3143 smb_buffer->Mid = GetNextMid(ses->server);
3144 smb_buffer->Uid = ses->Suid;
3145 pSMB = (TCONX_REQ *) smb_buffer;
3146 pSMBr = (TCONX_RSP *) smb_buffer_response;
3148 pSMB->AndXCommand = 0xFF;
3149 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3150 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3151 bcc_ptr = &pSMB->Password[0];
3152 bcc_ptr++; /* skip password */
3154 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3155 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3157 if (ses->capabilities & CAP_STATUS32) {
3158 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3160 if (ses->capabilities & CAP_DFS) {
3161 smb_buffer->Flags2 |= SMBFLG2_DFS;
3163 if (ses->capabilities & CAP_UNICODE) {
3164 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3166 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
3167 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3168 bcc_ptr += 2; /* skip trailing null */
3169 } else { /* ASCII */
3171 strcpy(bcc_ptr, tree);
3172 bcc_ptr += strlen(tree) + 1;
3174 strcpy(bcc_ptr, "?????");
3175 bcc_ptr += strlen("?????");
3177 count = bcc_ptr - &pSMB->Password[0];
3178 pSMB->hdr.smb_buf_length += count;
3179 pSMB->ByteCount = cpu_to_le16(count);
3181 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3183 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3184 /* above now done in SendReceive */
3185 if ((rc == 0) && (tcon != NULL)) {
3186 tcon->tidStatus = CifsGood;
3187 tcon->tid = smb_buffer_response->Tid;
3188 bcc_ptr = pByteArea(smb_buffer_response);
3189 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3190 /* skip service field (NB: this field is always ASCII) */
3191 bcc_ptr += length + 1;
3192 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3193 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3194 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3195 if ((bcc_ptr + (2 * length)) -
3196 pByteArea(smb_buffer_response) <=
3197 BCC(smb_buffer_response)) {
3198 if(tcon->nativeFileSystem)
3199 kfree(tcon->nativeFileSystem);
3200 tcon->nativeFileSystem =
3201 kcalloc(1, length + 2, GFP_KERNEL);
3202 cifs_strfromUCS_le(tcon->nativeFileSystem,
3203 (wchar_t *) bcc_ptr,
3204 length, nls_codepage);
3205 bcc_ptr += 2 * length;
3206 bcc_ptr[0] = 0; /* null terminate the string */
3210 /* else do not bother copying these informational fields */
3212 length = strnlen(bcc_ptr, 1024);
3213 if ((bcc_ptr + length) -
3214 pByteArea(smb_buffer_response) <=
3215 BCC(smb_buffer_response)) {
3216 if(tcon->nativeFileSystem)
3217 kfree(tcon->nativeFileSystem);
3218 tcon->nativeFileSystem =
3219 kcalloc(1, length + 1, GFP_KERNEL);
3220 strncpy(tcon->nativeFileSystem, bcc_ptr,
3223 /* else do not bother copying these informational fields */
3225 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3226 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3227 } else if ((rc == 0) && tcon == NULL) {
3228 /* all we need to save for IPC$ connection */
3229 ses->ipc_tid = smb_buffer_response->Tid;
3233 cifs_buf_release(smb_buffer);
3238 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3242 struct cifsSesInfo *ses = NULL;
3243 struct task_struct *cifsd_task;
3247 if (cifs_sb->tcon) {
3248 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3249 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3254 tconInfoFree(cifs_sb->tcon);
3255 if ((ses) && (ses->server)) {
3256 /* save off task so we do not refer to ses later */
3257 cifsd_task = ses->server->tsk;
3258 cFYI(1, ("About to do SMBLogoff "));
3259 rc = CIFSSMBLogoff(xid, ses);
3263 } else if (rc == -ESHUTDOWN) {
3264 cFYI(1,("Waking up socket by sending it signal"));
3266 send_sig(SIGKILL,cifsd_task,1);
3267 wait_for_completion(&cifsd_complete);
3270 } /* else - we have an smb session
3271 left on this socket do not kill cifsd */
3273 cFYI(1, ("No session or bad tcon"));
3276 cifs_sb->tcon = NULL;
3278 set_current_state(TASK_INTERRUPTIBLE);
3279 schedule_timeout(HZ / 2);
3285 return rc; /* BB check if we should always return zero here */
3288 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3289 struct nls_table * nls_info)
3292 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3293 int ntlmv2_flag = FALSE;
3296 /* what if server changes its buffer size after dropping the session? */
3297 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3298 rc = CIFSSMBNegotiate(xid, pSesInfo);
3299 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3300 rc = CIFSSMBNegotiate(xid, pSesInfo);
3305 spin_lock(&GlobalMid_Lock);
3306 if(pSesInfo->server->tcpStatus != CifsExiting)
3307 pSesInfo->server->tcpStatus = CifsGood;
3310 spin_unlock(&GlobalMid_Lock);
3316 pSesInfo->capabilities = pSesInfo->server->capabilities;
3317 if(linuxExtEnabled == 0)
3318 pSesInfo->capabilities &= (~CAP_UNIX);
3319 /* pSesInfo->sequence_number = 0;*/
3320 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3321 pSesInfo->server->secMode,
3322 pSesInfo->server->capabilities,
3323 pSesInfo->server->timeZone));
3324 if (extended_security
3325 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3326 && (pSesInfo->server->secType == NTLMSSP)) {
3327 cFYI(1, ("New style sesssetup "));
3328 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3329 NULL /* security blob */,
3330 0 /* blob length */,
3332 } else if (extended_security
3333 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3334 && (pSesInfo->server->secType == RawNTLMSSP)) {
3335 cFYI(1, ("NTLMSSP sesssetup "));
3336 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3343 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3344 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3349 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3351 CalcNTLMv2_response(pSesInfo,v2_response);
3353 cifs_calculate_ntlmv2_mac_key(
3354 pSesInfo->server->mac_signing_key,
3355 response, ntlm_session_key, */
3357 /* BB Put dummy sig in SessSetup PDU? */
3364 SMBNTencrypt(pSesInfo->password,
3365 pSesInfo->server->cryptKey,
3369 cifs_calculate_mac_key(
3370 pSesInfo->server->mac_signing_key,
3372 pSesInfo->password);
3374 /* for better security the weaker lanman hash not sent
3375 in AuthSessSetup so we no longer calculate it */
3377 rc = CIFSNTLMSSPAuthSessSetup(xid,
3383 } else { /* old style NTLM 0.12 session setup */
3384 SMBNTencrypt(pSesInfo->password,
3385 pSesInfo->server->cryptKey,
3389 cifs_calculate_mac_key(
3390 pSesInfo->server->mac_signing_key,
3391 ntlm_session_key, pSesInfo->password);
3393 rc = CIFSSessSetup(xid, pSesInfo,
3394 ntlm_session_key, nls_info);
3397 cERROR(1,("Send error in SessSetup = %d",rc));
3399 cFYI(1,("CIFS Session Established successfully"));
3400 pSesInfo->status = CifsGood;