4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/net.h>
23 #include <linux/string.h>
24 #include <linux/list.h>
25 #include <linux/wait.h>
26 #include <linux/ipv6.h>
27 #include <linux/pagemap.h>
28 #include <linux/ctype.h>
29 #include <linux/utsname.h>
30 #include <linux/mempool.h>
31 #include <linux/delay.h>
32 #include <linux/completion.h>
33 #include <linux/pagevec.h>
34 #include <asm/uaccess.h>
35 #include <asm/processor.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
41 #include "cifs_fs_sb.h"
44 #include "rfc1002pdu.h"
47 #define RFC1001_PORT 139
49 static DECLARE_COMPLETION(cifsd_complete);
51 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
53 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
56 extern mempool_t *cifs_req_poolp;
64 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
65 char *iocharset; /* local code page for mapping to and from Unicode */
66 char source_rfc1001_name[16]; /* netbios name of client */
67 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
77 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
78 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
79 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
81 unsigned remap:1; /* set to remap seven reserved chars in filenames */
82 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
84 unsigned nocase; /* request case insensitive filenames */
85 unsigned nobrl; /* disable sending byte range locks to srv */
89 unsigned short int port;
92 static int ipv4_connect(struct sockaddr_in *psin_server,
93 struct socket **csocket,
95 char * server_netb_name);
96 static int ipv6_connect(struct sockaddr_in6 *psin_server,
97 struct socket **csocket);
101 * cifs tcp session reconnection
103 * mark tcp session as reconnecting so temporarily locked
104 * mark all smb sessions as reconnecting for tcp session
105 * reconnect tcp session
106 * wake up waiters on reconnection? - (not needed currently)
110 cifs_reconnect(struct TCP_Server_Info *server)
113 struct list_head *tmp;
114 struct cifsSesInfo *ses;
115 struct cifsTconInfo *tcon;
116 struct mid_q_entry * mid_entry;
118 spin_lock(&GlobalMid_Lock);
119 if(server->tcpStatus == CifsExiting) {
120 /* the demux thread will exit normally
121 next time through the loop */
122 spin_unlock(&GlobalMid_Lock);
125 server->tcpStatus = CifsNeedReconnect;
126 spin_unlock(&GlobalMid_Lock);
129 cFYI(1, ("Reconnecting tcp session"));
131 /* before reconnecting the tcp session, mark the smb session (uid)
132 and the tid bad so they are not used until reconnected */
133 read_lock(&GlobalSMBSeslock);
134 list_for_each(tmp, &GlobalSMBSessionList) {
135 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
137 if (ses->server == server) {
138 ses->status = CifsNeedReconnect;
142 /* else tcp and smb sessions need reconnection */
144 list_for_each(tmp, &GlobalTreeConnectionList) {
145 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
146 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
147 tcon->tidStatus = CifsNeedReconnect;
150 read_unlock(&GlobalSMBSeslock);
151 /* do not want to be sending data on a socket we are freeing */
152 down(&server->tcpSem);
153 if(server->ssocket) {
154 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
155 server->ssocket->flags));
156 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
157 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
158 server->ssocket->flags));
159 sock_release(server->ssocket);
160 server->ssocket = NULL;
163 spin_lock(&GlobalMid_Lock);
164 list_for_each(tmp, &server->pending_mid_q) {
165 mid_entry = list_entry(tmp, struct
169 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
170 /* Mark other intransit requests as needing
171 retry so we do not immediately mark the
172 session bad again (ie after we reconnect
173 below) as they timeout too */
174 mid_entry->midState = MID_RETRY_NEEDED;
178 spin_unlock(&GlobalMid_Lock);
181 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
183 if(server->protocolType == IPV6) {
184 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
186 rc = ipv4_connect(&server->addr.sockAddr,
188 server->workstation_RFC1001_name,
189 server->server_RFC1001_name);
192 cFYI(1,("reconnect error %d",rc));
195 atomic_inc(&tcpSesReconnectCount);
196 spin_lock(&GlobalMid_Lock);
197 if(server->tcpStatus != CifsExiting)
198 server->tcpStatus = CifsGood;
199 server->sequence_number = 0;
200 spin_unlock(&GlobalMid_Lock);
201 /* atomic_set(&server->inFlight,0);*/
202 wake_up(&server->response_q);
210 0 not a transact2, or all data present
211 >0 transact2 with that much data missing
212 -EINVAL = invalid transact2
215 static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
217 struct smb_t2_rsp * pSMBt;
219 int data_in_this_rsp;
222 if(pSMB->Command != SMB_COM_TRANSACTION2)
225 /* check for plausible wct, bcc and t2 data and parm sizes */
226 /* check for parm and data offset going beyond end of smb */
227 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
228 cFYI(1,("invalid transact2 word count"));
232 pSMBt = (struct smb_t2_rsp *)pSMB;
234 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
235 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
237 remaining = total_data_size - data_in_this_rsp;
241 else if(remaining < 0) {
242 cFYI(1,("total data %d smaller than data in frame %d",
243 total_data_size, data_in_this_rsp));
246 cFYI(1,("missing %d bytes from transact2, check next response",
248 if(total_data_size > maxBufSize) {
249 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
250 total_data_size,maxBufSize));
257 static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
259 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
260 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
265 char * data_area_of_target;
266 char * data_area_of_buf2;
269 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
271 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
272 cFYI(1,("total data sizes of primary and secondary t2 differ"));
275 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
277 remaining = total_data_size - total_in_buf;
282 if(remaining == 0) /* nothing to do, ignore */
285 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
286 if(remaining < total_in_buf2) {
287 cFYI(1,("transact2 2nd response contains too much data"));
290 /* find end of first SMB data area */
291 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
292 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
293 /* validate target area */
295 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
296 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
298 data_area_of_target += total_in_buf;
300 /* copy second buffer into end of first buffer */
301 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
302 total_in_buf += total_in_buf2;
303 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
304 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
305 byte_count += total_in_buf2;
306 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
308 byte_count = pTargetSMB->smb_buf_length;
309 byte_count += total_in_buf2;
311 /* BB also add check that we are not beyond maximum buffer size */
313 pTargetSMB->smb_buf_length = byte_count;
315 if(remaining == total_in_buf2) {
316 cFYI(1,("found the last secondary response"));
317 return 0; /* we are done */
318 } else /* more responses to go */
324 cifs_demultiplex_thread(struct TCP_Server_Info *server)
327 unsigned int pdu_length, total_read;
328 struct smb_hdr *smb_buffer = NULL;
329 struct smb_hdr *bigbuf = NULL;
330 struct smb_hdr *smallbuf = NULL;
331 struct msghdr smb_msg;
333 struct socket *csocket = server->ssocket;
334 struct list_head *tmp;
335 struct cifsSesInfo *ses;
336 struct task_struct *task_to_wake = NULL;
337 struct mid_q_entry *mid_entry;
339 int isLargeBuf = FALSE;
344 allow_signal(SIGKILL);
345 current->flags |= PF_MEMALLOC;
346 server->tsk = current; /* save process info to wake at shutdown */
347 cFYI(1, ("Demultiplex PID: %d", current->pid));
348 write_lock(&GlobalSMBSeslock);
349 atomic_inc(&tcpSesAllocCount);
350 length = tcpSesAllocCount.counter;
351 write_unlock(&GlobalSMBSeslock);
352 complete(&cifsd_complete);
354 mempool_resize(cifs_req_poolp,
355 length + cifs_min_rcv,
359 while (server->tcpStatus != CifsExiting) {
362 if (bigbuf == NULL) {
363 bigbuf = cifs_buf_get();
365 cERROR(1,("No memory for large SMB response"));
367 /* retry will check if exiting */
370 } else if(isLargeBuf) {
371 /* we are reusing a dirtry large buf, clear its start */
372 memset(bigbuf, 0, sizeof (struct smb_hdr));
375 if (smallbuf == NULL) {
376 smallbuf = cifs_small_buf_get();
377 if(smallbuf == NULL) {
378 cERROR(1,("No memory for SMB response"));
380 /* retry will check if exiting */
383 /* beginning of smb buffer is cleared in our buf_get */
384 } else /* if existing small buf clear beginning */
385 memset(smallbuf, 0, sizeof (struct smb_hdr));
389 smb_buffer = smallbuf;
390 iov.iov_base = smb_buffer;
392 smb_msg.msg_control = NULL;
393 smb_msg.msg_controllen = 0;
395 kernel_recvmsg(csocket, &smb_msg,
396 &iov, 1, 4, 0 /* BB see socket.h flags */);
398 if(server->tcpStatus == CifsExiting) {
400 } else if (server->tcpStatus == CifsNeedReconnect) {
401 cFYI(1,("Reconnect after server stopped responding"));
402 cifs_reconnect(server);
403 cFYI(1,("call to reconnect done"));
404 csocket = server->ssocket;
406 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
407 msleep(1); /* minimum sleep to prevent looping
408 allowing socket to clear and app threads to set
409 tcpStatus CifsNeedReconnect if server hung */
411 } else if (length <= 0) {
412 if(server->tcpStatus == CifsNew) {
413 cFYI(1,("tcp session abend after SMBnegprot"));
414 /* some servers kill the TCP session rather than
415 returning an SMB negprot error, in which
416 case reconnecting here is not going to help,
417 and so simply return error to mount */
420 if(length == -EINTR) {
421 cFYI(1,("cifsd thread killed"));
424 cFYI(1,("Reconnect after unexpected peek error %d",
426 cifs_reconnect(server);
427 csocket = server->ssocket;
428 wake_up(&server->response_q);
430 } else if (length < 4) {
432 ("Frame under four bytes received (%d bytes long)",
434 cifs_reconnect(server);
435 csocket = server->ssocket;
436 wake_up(&server->response_q);
440 /* The right amount was read from socket - 4 bytes */
441 /* so we can now interpret the length field */
443 /* the first byte big endian of the length field,
444 is actually not part of the length but the type
445 with the most common, zero, as regular data */
446 temp = *((char *) smb_buffer);
448 /* Note that FC 1001 length is big endian on the wire,
449 but we convert it here so it is always manipulated
450 as host byte order */
451 pdu_length = ntohl(smb_buffer->smb_buf_length);
452 smb_buffer->smb_buf_length = pdu_length;
454 cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
456 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
458 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
459 cFYI(1,("Good RFC 1002 session rsp"));
461 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
462 /* we get this from Windows 98 instead of
463 an error on SMB negprot response */
464 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
466 if(server->tcpStatus == CifsNew) {
467 /* if nack on negprot (rather than
468 ret of smb negprot error) reconnecting
469 not going to help, ret error to mount */
472 /* give server a second to
473 clean up before reconnect attempt */
475 /* always try 445 first on reconnect
476 since we get NACK on some if we ever
477 connected to port 139 (the NACK is
478 since we do not begin with RFC1001
479 session initialize frame) */
480 server->addr.sockAddr.sin_port =
482 cifs_reconnect(server);
483 csocket = server->ssocket;
484 wake_up(&server->response_q);
487 } else if (temp != (char) 0) {
488 cERROR(1,("Unknown RFC 1002 frame"));
489 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
491 cifs_reconnect(server);
492 csocket = server->ssocket;
496 /* else we have an SMB response */
497 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
498 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
499 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
500 length, pdu_length+4));
501 cifs_reconnect(server);
502 csocket = server->ssocket;
503 wake_up(&server->response_q);
510 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
512 memcpy(bigbuf, smallbuf, 4);
516 iov.iov_base = 4 + (char *)smb_buffer;
517 iov.iov_len = pdu_length;
518 for (total_read = 0; total_read < pdu_length;
519 total_read += length) {
520 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
521 pdu_length - total_read, 0);
522 if((server->tcpStatus == CifsExiting) ||
523 (length == -EINTR)) {
527 } else if (server->tcpStatus == CifsNeedReconnect) {
528 cifs_reconnect(server);
529 csocket = server->ssocket;
530 /* Reconnect wakes up rspns q */
531 /* Now we will reread sock */
534 } else if ((length == -ERESTARTSYS) ||
535 (length == -EAGAIN)) {
536 msleep(1); /* minimum sleep to prevent looping,
537 allowing socket to clear and app
538 threads to set tcpStatus
539 CifsNeedReconnect if server hung*/
541 } else if (length <= 0) {
542 cERROR(1,("Received no data, expecting %d",
543 pdu_length - total_read));
544 cifs_reconnect(server);
545 csocket = server->ssocket;
552 else if(reconnect == 1)
555 length += 4; /* account for rfc1002 hdr */
558 dump_smb(smb_buffer, length);
559 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
560 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
566 spin_lock(&GlobalMid_Lock);
567 list_for_each(tmp, &server->pending_mid_q) {
568 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
570 if ((mid_entry->mid == smb_buffer->Mid) &&
571 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
572 (mid_entry->command == smb_buffer->Command)) {
573 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
574 /* We have a multipart transact2 resp */
576 if(mid_entry->resp_buf) {
577 /* merge response - fix up 1st*/
578 if(coalesce_t2(smb_buffer,
579 mid_entry->resp_buf)) {
582 /* all parts received */
587 cERROR(1,("1st trans2 resp needs bigbuf"));
588 /* BB maybe we can fix this up, switch
589 to already allocated large buffer? */
591 /* Have first buffer */
592 mid_entry->resp_buf =
594 mid_entry->largeBuf = 1;
600 mid_entry->resp_buf = smb_buffer;
602 mid_entry->largeBuf = 1;
604 mid_entry->largeBuf = 0;
606 task_to_wake = mid_entry->tsk;
607 mid_entry->midState = MID_RESPONSE_RECEIVED;
608 #ifdef CONFIG_CIFS_STATS2
609 mid_entry->when_received = jiffies;
614 spin_unlock(&GlobalMid_Lock);
616 /* Was previous buf put in mpx struct for multi-rsp? */
618 /* smb buffer will be freed by user thread */
624 wake_up_process(task_to_wake);
625 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
626 && (isMultiRsp == FALSE)) {
627 cERROR(1, ("No task to wake, unknown frame rcvd!"));
628 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
629 sizeof(struct smb_hdr));
631 } /* end while !EXITING */
633 spin_lock(&GlobalMid_Lock);
634 server->tcpStatus = CifsExiting;
636 /* check if we have blocked requests that need to free */
637 /* Note that cifs_max_pending is normally 50, but
638 can be set at module install time to as little as two */
639 if(atomic_read(&server->inFlight) >= cifs_max_pending)
640 atomic_set(&server->inFlight, cifs_max_pending - 1);
641 /* We do not want to set the max_pending too low or we
642 could end up with the counter going negative */
643 spin_unlock(&GlobalMid_Lock);
644 /* Although there should not be any requests blocked on
645 this queue it can not hurt to be paranoid and try to wake up requests
646 that may haven been blocked when more than 50 at time were on the wire
647 to the same server - they now will see the session is in exit state
648 and get out of SendReceive. */
649 wake_up_all(&server->request_q);
650 /* give those requests time to exit */
653 if(server->ssocket) {
654 sock_release(csocket);
655 server->ssocket = NULL;
657 /* buffer usuallly freed in free_mid - need to free it here on exit */
659 cifs_buf_release(bigbuf);
660 if (smallbuf != NULL)
661 cifs_small_buf_release(smallbuf);
663 read_lock(&GlobalSMBSeslock);
664 if (list_empty(&server->pending_mid_q)) {
665 /* loop through server session structures attached to this and
667 list_for_each(tmp, &GlobalSMBSessionList) {
669 list_entry(tmp, struct cifsSesInfo,
671 if (ses->server == server) {
672 ses->status = CifsExiting;
676 read_unlock(&GlobalSMBSeslock);
678 /* although we can not zero the server struct pointer yet,
679 since there are active requests which may depnd on them,
680 mark the corresponding SMB sessions as exiting too */
681 list_for_each(tmp, &GlobalSMBSessionList) {
682 ses = list_entry(tmp, struct cifsSesInfo,
684 if (ses->server == server) {
685 ses->status = CifsExiting;
689 spin_lock(&GlobalMid_Lock);
690 list_for_each(tmp, &server->pending_mid_q) {
691 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
692 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
694 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
695 task_to_wake = mid_entry->tsk;
697 wake_up_process(task_to_wake);
701 spin_unlock(&GlobalMid_Lock);
702 read_unlock(&GlobalSMBSeslock);
703 /* 1/8th of sec is more than enough time for them to exit */
707 if (!list_empty(&server->pending_mid_q)) {
708 /* mpx threads have not exited yet give them
709 at least the smb send timeout time for long ops */
710 /* due to delays on oplock break requests, we need
711 to wait at least 45 seconds before giving up
712 on a request getting a response and going ahead
714 cFYI(1, ("Wait for exit from demultiplex thread"));
716 /* if threads still have not exited they are probably never
717 coming home not much else we can do but free the memory */
720 write_lock(&GlobalSMBSeslock);
721 atomic_dec(&tcpSesAllocCount);
722 length = tcpSesAllocCount.counter;
724 /* last chance to mark ses pointers invalid
725 if there are any pointing to this (e.g
726 if a crazy root user tried to kill cifsd
727 kernel thread explicitly this might happen) */
728 list_for_each(tmp, &GlobalSMBSessionList) {
729 ses = list_entry(tmp, struct cifsSesInfo,
731 if (ses->server == server) {
735 write_unlock(&GlobalSMBSeslock);
739 mempool_resize(cifs_req_poolp,
740 length + cifs_min_rcv,
744 complete_and_exit(&cifsd_complete, 0);
749 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
753 unsigned int temp_len, i, j;
759 memset(vol->source_rfc1001_name,0x20,15);
760 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
761 /* does not have to be a perfect mapping since the field is
762 informational, only used for servers that do not support
763 port 445 and it can be overridden at mount time */
764 vol->source_rfc1001_name[i] =
765 toupper(system_utsname.nodename[i]);
767 vol->source_rfc1001_name[15] = 0;
768 /* null target name indicates to use *SMBSERVR default called name
769 if we end up sending RFC1001 session initialize */
770 vol->target_rfc1001_name[0] = 0;
771 vol->linux_uid = current->uid; /* current->euid instead? */
772 vol->linux_gid = current->gid;
773 vol->dir_mode = S_IRWXUGO;
774 /* 2767 perms indicate mandatory locking support */
775 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
777 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
780 /* default is always to request posix paths. */
781 vol->posix_paths = 1;
786 if(strncmp(options,"sep=",4) == 0) {
787 if(options[4] != 0) {
788 separator[0] = options[4];
791 cFYI(1,("Null separator not allowed"));
795 while ((data = strsep(&options, separator)) != NULL) {
798 if ((value = strchr(data, '=')) != NULL)
801 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
803 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
805 } else if (strnicmp(data, "user", 4) == 0) {
806 if (!value || !*value) {
808 "CIFS: invalid or missing username\n");
809 return 1; /* needs_arg; */
811 if (strnlen(value, 200) < 200) {
812 vol->username = value;
814 printk(KERN_WARNING "CIFS: username too long\n");
817 } else if (strnicmp(data, "pass", 4) == 0) {
819 vol->password = NULL;
821 } else if(value[0] == 0) {
822 /* check if string begins with double comma
823 since that would mean the password really
824 does start with a comma, and would not
825 indicate an empty string */
826 if(value[1] != separator[0]) {
827 vol->password = NULL;
831 temp_len = strlen(value);
832 /* removed password length check, NTLM passwords
833 can be arbitrarily long */
835 /* if comma in password, the string will be
836 prematurely null terminated. Commas in password are
837 specified across the cifs mount interface by a double
838 comma ie ,, and a comma used as in other cases ie ','
839 as a parameter delimiter/separator is single and due
840 to the strsep above is temporarily zeroed. */
842 /* NB: password legally can have multiple commas and
843 the only illegal character in a password is null */
845 if ((value[temp_len] == 0) &&
846 (value[temp_len+1] == separator[0])) {
848 value[temp_len] = separator[0];
849 temp_len+=2; /* move after the second comma */
850 while(value[temp_len] != 0) {
851 if (value[temp_len] == separator[0]) {
852 if (value[temp_len+1] ==
854 /* skip second comma */
857 /* single comma indicating start
864 if(value[temp_len] == 0) {
868 /* point option to start of next parm */
869 options = value + temp_len + 1;
871 /* go from value to value + temp_len condensing
872 double commas to singles. Note that this ends up
873 allocating a few bytes too many, which is ok */
874 vol->password = kzalloc(temp_len, GFP_KERNEL);
875 if(vol->password == NULL) {
876 printk("CIFS: no memory for pass\n");
879 for(i=0,j=0;i<temp_len;i++,j++) {
880 vol->password[j] = value[i];
881 if(value[i] == separator[0]
882 && value[i+1] == separator[0]) {
883 /* skip second comma */
887 vol->password[j] = 0;
889 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
890 if(vol->password == NULL) {
891 printk("CIFS: no memory for pass\n");
894 strcpy(vol->password, value);
896 } else if (strnicmp(data, "ip", 2) == 0) {
897 if (!value || !*value) {
899 } else if (strnlen(value, 35) < 35) {
902 printk(KERN_WARNING "CIFS: ip address too long\n");
905 } else if ((strnicmp(data, "unc", 3) == 0)
906 || (strnicmp(data, "target", 6) == 0)
907 || (strnicmp(data, "path", 4) == 0)) {
908 if (!value || !*value) {
910 "CIFS: invalid path to network resource\n");
911 return 1; /* needs_arg; */
913 if ((temp_len = strnlen(value, 300)) < 300) {
914 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
917 strcpy(vol->UNC,value);
918 if (strncmp(vol->UNC, "//", 2) == 0) {
921 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
923 "CIFS: UNC Path does not begin with // or \\\\ \n");
927 printk(KERN_WARNING "CIFS: UNC name too long\n");
930 } else if ((strnicmp(data, "domain", 3) == 0)
931 || (strnicmp(data, "workgroup", 5) == 0)) {
932 if (!value || !*value) {
933 printk(KERN_WARNING "CIFS: invalid domain name\n");
934 return 1; /* needs_arg; */
936 /* BB are there cases in which a comma can be valid in
937 a domain name and need special handling? */
938 if (strnlen(value, 65) < 65) {
939 vol->domainname = value;
940 cFYI(1, ("Domain name set"));
942 printk(KERN_WARNING "CIFS: domain name too long\n");
945 } else if (strnicmp(data, "iocharset", 9) == 0) {
946 if (!value || !*value) {
947 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
948 return 1; /* needs_arg; */
950 if (strnlen(value, 65) < 65) {
951 if(strnicmp(value,"default",7))
952 vol->iocharset = value;
953 /* if iocharset not set load_nls_default used by caller */
954 cFYI(1, ("iocharset set to %s",value));
956 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
959 } else if (strnicmp(data, "uid", 3) == 0) {
960 if (value && *value) {
962 simple_strtoul(value, &value, 0);
964 } else if (strnicmp(data, "gid", 3) == 0) {
965 if (value && *value) {
967 simple_strtoul(value, &value, 0);
969 } else if (strnicmp(data, "file_mode", 4) == 0) {
970 if (value && *value) {
972 simple_strtoul(value, &value, 0);
974 } else if (strnicmp(data, "dir_mode", 4) == 0) {
975 if (value && *value) {
977 simple_strtoul(value, &value, 0);
979 } else if (strnicmp(data, "dirmode", 4) == 0) {
980 if (value && *value) {
982 simple_strtoul(value, &value, 0);
984 } else if (strnicmp(data, "port", 4) == 0) {
985 if (value && *value) {
987 simple_strtoul(value, &value, 0);
989 } else if (strnicmp(data, "rsize", 5) == 0) {
990 if (value && *value) {
992 simple_strtoul(value, &value, 0);
994 } else if (strnicmp(data, "wsize", 5) == 0) {
995 if (value && *value) {
997 simple_strtoul(value, &value, 0);
999 } else if (strnicmp(data, "sockopt", 5) == 0) {
1000 if (value && *value) {
1002 simple_strtoul(value, &value, 0);
1004 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1005 if (!value || !*value || (*value == ' ')) {
1006 cFYI(1,("invalid (empty) netbiosname specified"));
1008 memset(vol->source_rfc1001_name,0x20,15);
1010 /* BB are there cases in which a comma can be
1011 valid in this workstation netbios name (and need
1012 special handling)? */
1014 /* We do not uppercase netbiosname for user */
1018 vol->source_rfc1001_name[i] = value[i];
1020 /* The string has 16th byte zero still from
1021 set at top of the function */
1022 if((i==15) && (value[i] != 0))
1023 printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
1025 } else if (strnicmp(data, "servern", 7) == 0) {
1026 /* servernetbiosname specified override *SMBSERVER */
1027 if (!value || !*value || (*value == ' ')) {
1028 cFYI(1,("empty server netbiosname specified"));
1030 /* last byte, type, is 0x20 for servr type */
1031 memset(vol->target_rfc1001_name,0x20,16);
1034 /* BB are there cases in which a comma can be
1035 valid in this workstation netbios name (and need
1036 special handling)? */
1038 /* user or mount helper must uppercase netbiosname */
1042 vol->target_rfc1001_name[i] = value[i];
1044 /* The string has 16th byte zero still from
1045 set at top of the function */
1046 if((i==15) && (value[i] != 0))
1047 printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
1049 } else if (strnicmp(data, "credentials", 4) == 0) {
1051 } else if (strnicmp(data, "version", 3) == 0) {
1053 } else if (strnicmp(data, "guest",5) == 0) {
1055 } else if (strnicmp(data, "rw", 2) == 0) {
1057 } else if ((strnicmp(data, "suid", 4) == 0) ||
1058 (strnicmp(data, "nosuid", 6) == 0) ||
1059 (strnicmp(data, "exec", 4) == 0) ||
1060 (strnicmp(data, "noexec", 6) == 0) ||
1061 (strnicmp(data, "nodev", 5) == 0) ||
1062 (strnicmp(data, "noauto", 6) == 0) ||
1063 (strnicmp(data, "dev", 3) == 0)) {
1064 /* The mount tool or mount.cifs helper (if present)
1065 uses these opts to set flags, and the flags are read
1066 by the kernel vfs layer before we get here (ie
1067 before read super) so there is no point trying to
1068 parse these options again and set anything and it
1069 is ok to just ignore them */
1071 } else if (strnicmp(data, "ro", 2) == 0) {
1073 } else if (strnicmp(data, "hard", 4) == 0) {
1075 } else if (strnicmp(data, "soft", 4) == 0) {
1077 } else if (strnicmp(data, "perm", 4) == 0) {
1079 } else if (strnicmp(data, "noperm", 6) == 0) {
1081 } else if (strnicmp(data, "mapchars", 8) == 0) {
1083 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1085 } else if (strnicmp(data, "sfu", 3) == 0) {
1087 } else if (strnicmp(data, "nosfu", 5) == 0) {
1089 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1090 vol->posix_paths = 1;
1091 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1092 vol->posix_paths = 0;
1093 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1094 (strnicmp(data, "ignorecase", 10) == 0)) {
1096 } else if (strnicmp(data, "brl", 3) == 0) {
1098 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1099 (strnicmp(data, "nolock", 6) == 0)) {
1101 /* turn off mandatory locking in mode
1102 if remote locking is turned off since the
1103 local vfs will do advisory */
1104 if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1105 vol->file_mode = S_IALLUGO;
1106 } else if (strnicmp(data, "setuids", 7) == 0) {
1108 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1110 } else if (strnicmp(data, "nohard", 6) == 0) {
1112 } else if (strnicmp(data, "nosoft", 6) == 0) {
1114 } else if (strnicmp(data, "nointr", 6) == 0) {
1116 } else if (strnicmp(data, "intr", 4) == 0) {
1118 } else if (strnicmp(data, "serverino",7) == 0) {
1119 vol->server_ino = 1;
1120 } else if (strnicmp(data, "noserverino",9) == 0) {
1121 vol->server_ino = 0;
1122 } else if (strnicmp(data, "acl",3) == 0) {
1123 vol->no_psx_acl = 0;
1124 } else if (strnicmp(data, "noacl",5) == 0) {
1125 vol->no_psx_acl = 1;
1126 } else if (strnicmp(data, "direct",6) == 0) {
1128 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1130 } else if (strnicmp(data, "in6_addr",8) == 0) {
1131 if (!value || !*value) {
1132 vol->in6_addr = NULL;
1133 } else if (strnlen(value, 49) == 48) {
1134 vol->in6_addr = value;
1136 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1139 } else if (strnicmp(data, "noac", 4) == 0) {
1140 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1142 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1144 if (vol->UNC == NULL) {
1145 if(devname == NULL) {
1146 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1149 if ((temp_len = strnlen(devname, 300)) < 300) {
1150 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1151 if(vol->UNC == NULL)
1153 strcpy(vol->UNC,devname);
1154 if (strncmp(vol->UNC, "//", 2) == 0) {
1157 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1158 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1162 printk(KERN_WARNING "CIFS: UNC name too long\n");
1166 if(vol->UNCip == NULL)
1167 vol->UNCip = &vol->UNC[2];
1172 static struct cifsSesInfo *
1173 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1174 struct in6_addr *target_ip6_addr,
1175 char *userName, struct TCP_Server_Info **psrvTcp)
1177 struct list_head *tmp;
1178 struct cifsSesInfo *ses;
1180 read_lock(&GlobalSMBSeslock);
1182 list_for_each(tmp, &GlobalSMBSessionList) {
1183 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1185 if((target_ip_addr &&
1186 (ses->server->addr.sockAddr.sin_addr.s_addr
1187 == target_ip_addr->s_addr)) || (target_ip6_addr
1188 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1189 target_ip6_addr,sizeof(*target_ip6_addr)))){
1190 /* BB lock server and tcp session and increment use count here?? */
1191 *psrvTcp = ses->server; /* found a match on the TCP session */
1192 /* BB check if reconnection needed */
1194 (ses->userName, userName,
1195 MAX_USERNAME_SIZE) == 0){
1196 read_unlock(&GlobalSMBSeslock);
1197 return ses; /* found exact match on both tcp and SMB sessions */
1201 /* else tcp and smb sessions need reconnection */
1203 read_unlock(&GlobalSMBSeslock);
1207 static struct cifsTconInfo *
1208 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1210 struct list_head *tmp;
1211 struct cifsTconInfo *tcon;
1213 read_lock(&GlobalSMBSeslock);
1214 list_for_each(tmp, &GlobalTreeConnectionList) {
1215 cFYI(1, ("Next tcon - "));
1216 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1218 if (tcon->ses->server) {
1220 (" old ip addr: %x == new ip %x ?",
1221 tcon->ses->server->addr.sockAddr.sin_addr.
1222 s_addr, new_target_ip_addr));
1223 if (tcon->ses->server->addr.sockAddr.sin_addr.
1224 s_addr == new_target_ip_addr) {
1225 /* BB lock tcon and server and tcp session and increment use count here? */
1226 /* found a match on the TCP session */
1227 /* BB check if reconnection needed */
1228 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1229 tcon->treeName, uncName));
1231 (tcon->treeName, uncName,
1232 MAX_TREE_SIZE) == 0) {
1234 ("Matched UNC, old user: %s == new: %s ?",
1235 tcon->treeName, uncName));
1237 (tcon->ses->userName,
1239 MAX_USERNAME_SIZE) == 0) {
1240 read_unlock(&GlobalSMBSeslock);
1241 return tcon;/* also matched user (smb session)*/
1248 read_unlock(&GlobalSMBSeslock);
1253 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1254 const char *old_path, const struct nls_table *nls_codepage,
1257 unsigned char *referrals = NULL;
1258 unsigned int num_referrals;
1261 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1262 &num_referrals, &referrals, remap);
1264 /* BB Add in code to: if valid refrl, if not ip address contact
1265 the helper that resolves tcp names, mount to it, try to
1266 tcon to it unmount it if fail */
1275 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1276 const char *old_path, const struct nls_table *nls_codepage,
1277 unsigned int *pnum_referrals,
1278 unsigned char ** preferrals, int remap)
1283 *pnum_referrals = 0;
1285 if (pSesInfo->ipc_tid == 0) {
1286 temp_unc = kmalloc(2 /* for slashes */ +
1287 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1288 + 1 + 4 /* slash IPC$ */ + 2,
1290 if (temp_unc == NULL)
1294 strcpy(temp_unc + 2, pSesInfo->serverName);
1295 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1296 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1298 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1302 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1303 pnum_referrals, nls_codepage, remap);
1308 /* See RFC1001 section 14 on representation of Netbios names */
1309 static void rfc1002mangle(char * target,char * source, unsigned int length)
1313 for(i=0,j=0;i<(length);i++) {
1314 /* mask a nibble at a time and encode */
1315 target[j] = 'A' + (0x0F & (source[i] >> 4));
1316 target[j+1] = 'A' + (0x0F & source[i]);
1324 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1325 char * netbios_name, char * target_name)
1329 __be16 orig_port = 0;
1331 if(*csocket == NULL) {
1332 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1334 cERROR(1, ("Error %d creating socket",rc));
1338 /* BB other socket options to set KEEPALIVE, NODELAY? */
1339 cFYI(1,("Socket created"));
1340 (*csocket)->sk->sk_allocation = GFP_NOFS;
1344 psin_server->sin_family = AF_INET;
1345 if(psin_server->sin_port) { /* user overrode default port */
1346 rc = (*csocket)->ops->connect(*csocket,
1347 (struct sockaddr *) psin_server,
1348 sizeof (struct sockaddr_in),0);
1354 /* save original port so we can retry user specified port
1355 later if fall back ports fail this time */
1356 orig_port = psin_server->sin_port;
1358 /* do not retry on the same port we just failed on */
1359 if(psin_server->sin_port != htons(CIFS_PORT)) {
1360 psin_server->sin_port = htons(CIFS_PORT);
1362 rc = (*csocket)->ops->connect(*csocket,
1363 (struct sockaddr *) psin_server,
1364 sizeof (struct sockaddr_in),0);
1370 psin_server->sin_port = htons(RFC1001_PORT);
1371 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1372 psin_server, sizeof (struct sockaddr_in),0);
1377 /* give up here - unless we want to retry on different
1378 protocol families some day */
1381 psin_server->sin_port = orig_port;
1382 cFYI(1,("Error %d connecting to server via ipv4",rc));
1383 sock_release(*csocket);
1387 /* Eventually check for other socket options to change from
1388 the default. sock_setsockopt not used because it expects
1389 user space buffer */
1390 cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf,
1391 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1392 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1393 /* make the bufsizes depend on wsize/rsize and max requests */
1394 if((*csocket)->sk->sk_sndbuf < (200 * 1024))
1395 (*csocket)->sk->sk_sndbuf = 200 * 1024;
1396 if((*csocket)->sk->sk_rcvbuf < (140 * 1024))
1397 (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1399 /* send RFC1001 sessinit */
1400 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1401 /* some servers require RFC1001 sessinit before sending
1402 negprot - BB check reconnection in case where second
1403 sessinit is sent but no second negprot */
1404 struct rfc1002_session_packet * ses_init_buf;
1405 struct smb_hdr * smb_buf;
1406 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1408 ses_init_buf->trailer.session_req.called_len = 32;
1409 if(target_name && (target_name[0] != 0)) {
1410 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1413 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1414 DEFAULT_CIFS_CALLED_NAME,16);
1417 ses_init_buf->trailer.session_req.calling_len = 32;
1418 /* calling name ends in null (byte 16) from old smb
1420 if(netbios_name && (netbios_name[0] !=0)) {
1421 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1424 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1425 "LINUX_CIFS_CLNT",16);
1427 ses_init_buf->trailer.session_req.scope1 = 0;
1428 ses_init_buf->trailer.session_req.scope2 = 0;
1429 smb_buf = (struct smb_hdr *)ses_init_buf;
1430 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1431 smb_buf->smb_buf_length = 0x81000044;
1432 rc = smb_send(*csocket, smb_buf, 0x44,
1433 (struct sockaddr *)psin_server);
1434 kfree(ses_init_buf);
1436 /* else the negprot may still work without this
1437 even though malloc failed */
1445 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1449 __be16 orig_port = 0;
1451 if(*csocket == NULL) {
1452 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1454 cERROR(1, ("Error %d creating ipv6 socket",rc));
1458 /* BB other socket options to set KEEPALIVE, NODELAY? */
1459 cFYI(1,("ipv6 Socket created"));
1460 (*csocket)->sk->sk_allocation = GFP_NOFS;
1464 psin_server->sin6_family = AF_INET6;
1466 if(psin_server->sin6_port) { /* user overrode default port */
1467 rc = (*csocket)->ops->connect(*csocket,
1468 (struct sockaddr *) psin_server,
1469 sizeof (struct sockaddr_in6),0);
1475 /* save original port so we can retry user specified port
1476 later if fall back ports fail this time */
1478 orig_port = psin_server->sin6_port;
1479 /* do not retry on the same port we just failed on */
1480 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1481 psin_server->sin6_port = htons(CIFS_PORT);
1483 rc = (*csocket)->ops->connect(*csocket,
1484 (struct sockaddr *) psin_server,
1485 sizeof (struct sockaddr_in6),0);
1491 psin_server->sin6_port = htons(RFC1001_PORT);
1492 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1493 psin_server, sizeof (struct sockaddr_in6),0);
1498 /* give up here - unless we want to retry on different
1499 protocol families some day */
1502 psin_server->sin6_port = orig_port;
1503 cFYI(1,("Error %d connecting to server via ipv6",rc));
1504 sock_release(*csocket);
1508 /* Eventually check for other socket options to change from
1509 the default. sock_setsockopt not used because it expects
1510 user space buffer */
1511 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1517 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1518 char *mount_data, const char *devname)
1522 int address_type = AF_INET;
1523 struct socket *csocket = NULL;
1524 struct sockaddr_in sin_server;
1525 struct sockaddr_in6 sin_server6;
1526 struct smb_vol volume_info;
1527 struct cifsSesInfo *pSesInfo = NULL;
1528 struct cifsSesInfo *existingCifsSes = NULL;
1529 struct cifsTconInfo *tcon = NULL;
1530 struct TCP_Server_Info *srvTcp = NULL;
1534 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1536 memset(&volume_info,0,sizeof(struct smb_vol));
1537 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1539 kfree(volume_info.UNC);
1540 if(volume_info.password)
1541 kfree(volume_info.password);
1546 if (volume_info.username) {
1547 /* BB fixme parse for domain name here */
1548 cFYI(1, ("Username: %s ", volume_info.username));
1551 cifserror("No username specified ");
1552 /* In userspace mount helper we can get user name from alternate
1553 locations such as env variables and files on disk */
1555 kfree(volume_info.UNC);
1556 if(volume_info.password)
1557 kfree(volume_info.password);
1562 if (volume_info.UNCip && volume_info.UNC) {
1563 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1566 /* not ipv4 address, try ipv6 */
1567 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1569 address_type = AF_INET6;
1571 address_type = AF_INET;
1575 /* we failed translating address */
1577 kfree(volume_info.UNC);
1578 if(volume_info.password)
1579 kfree(volume_info.password);
1584 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1587 } else if (volume_info.UNCip){
1588 /* BB using ip addr as server name connect to the DFS root below */
1589 cERROR(1,("Connecting to DFS root not implemented yet"));
1591 kfree(volume_info.UNC);
1592 if(volume_info.password)
1593 kfree(volume_info.password);
1596 } else /* which servers DFS root would we conect to */ {
1598 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1600 kfree(volume_info.UNC);
1601 if(volume_info.password)
1602 kfree(volume_info.password);
1607 /* this is needed for ASCII cp to Unicode converts */
1608 if(volume_info.iocharset == NULL) {
1609 cifs_sb->local_nls = load_nls_default();
1610 /* load_nls_default can not return null */
1612 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1613 if(cifs_sb->local_nls == NULL) {
1614 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1616 kfree(volume_info.UNC);
1617 if(volume_info.password)
1618 kfree(volume_info.password);
1624 if(address_type == AF_INET)
1625 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1626 NULL /* no ipv6 addr */,
1627 volume_info.username, &srvTcp);
1628 else if(address_type == AF_INET6)
1629 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1630 &sin_server6.sin6_addr,
1631 volume_info.username, &srvTcp);
1634 kfree(volume_info.UNC);
1635 if(volume_info.password)
1636 kfree(volume_info.password);
1643 cFYI(1, ("Existing tcp session with server found "));
1644 } else { /* create socket */
1645 if(volume_info.port)
1646 sin_server.sin_port = htons(volume_info.port);
1648 sin_server.sin_port = 0;
1649 rc = ipv4_connect(&sin_server,&csocket,
1650 volume_info.source_rfc1001_name,
1651 volume_info.target_rfc1001_name);
1654 ("Error connecting to IPv4 socket. Aborting operation"));
1656 sock_release(csocket);
1658 kfree(volume_info.UNC);
1659 if(volume_info.password)
1660 kfree(volume_info.password);
1665 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1666 if (srvTcp == NULL) {
1668 sock_release(csocket);
1670 kfree(volume_info.UNC);
1671 if(volume_info.password)
1672 kfree(volume_info.password);
1676 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1677 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1678 atomic_set(&srvTcp->inFlight,0);
1679 /* BB Add code for ipv6 case too */
1680 srvTcp->ssocket = csocket;
1681 srvTcp->protocolType = IPV4;
1682 init_waitqueue_head(&srvTcp->response_q);
1683 init_waitqueue_head(&srvTcp->request_q);
1684 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1685 /* at this point we are the only ones with the pointer
1686 to the struct since the kernel thread not created yet
1687 so no need to spinlock this init of tcpStatus */
1688 srvTcp->tcpStatus = CifsNew;
1689 init_MUTEX(&srvTcp->tcpSem);
1690 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1691 CLONE_FS | CLONE_FILES | CLONE_VM);
1694 sock_release(csocket);
1696 kfree(volume_info.UNC);
1697 if(volume_info.password)
1698 kfree(volume_info.password);
1702 wait_for_completion(&cifsd_complete);
1704 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1705 memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
1706 srvTcp->sequence_number = 0;
1710 if (existingCifsSes) {
1711 pSesInfo = existingCifsSes;
1712 cFYI(1, ("Existing smb sess found "));
1713 if(volume_info.password)
1714 kfree(volume_info.password);
1715 /* volume_info.UNC freed at end of function */
1717 cFYI(1, ("Existing smb sess not found "));
1718 pSesInfo = sesInfoAlloc();
1719 if (pSesInfo == NULL)
1722 pSesInfo->server = srvTcp;
1723 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1724 NIPQUAD(sin_server.sin_addr.s_addr));
1728 /* volume_info.password freed at unmount */
1729 if (volume_info.password)
1730 pSesInfo->password = volume_info.password;
1731 if (volume_info.username)
1732 strncpy(pSesInfo->userName,
1733 volume_info.username,MAX_USERNAME_SIZE);
1734 if (volume_info.domainname)
1735 strncpy(pSesInfo->domainName,
1736 volume_info.domainname,MAX_USERNAME_SIZE);
1737 pSesInfo->linux_uid = volume_info.linux_uid;
1738 down(&pSesInfo->sesSem);
1739 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1740 up(&pSesInfo->sesSem);
1742 atomic_inc(&srvTcp->socketUseCount);
1744 if(volume_info.password)
1745 kfree(volume_info.password);
1748 /* search for existing tcon to this server share */
1750 if(volume_info.rsize > CIFSMaxBufSize) {
1751 cERROR(1,("rsize %d too large, using MaxBufSize",
1752 volume_info.rsize));
1753 cifs_sb->rsize = CIFSMaxBufSize;
1754 } else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1755 cifs_sb->rsize = volume_info.rsize;
1757 cifs_sb->rsize = CIFSMaxBufSize;
1759 if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
1760 cERROR(1,("wsize %d too large using 4096 instead",
1761 volume_info.wsize));
1762 cifs_sb->wsize = 4096;
1763 } else if(volume_info.wsize)
1764 cifs_sb->wsize = volume_info.wsize;
1766 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1767 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1768 cifs_sb->rsize = PAGE_CACHE_SIZE;
1769 /* Windows ME does this */
1770 cFYI(1,("Attempt to set readsize for mount to less than one page (4096)"));
1772 cifs_sb->mnt_uid = volume_info.linux_uid;
1773 cifs_sb->mnt_gid = volume_info.linux_gid;
1774 cifs_sb->mnt_file_mode = volume_info.file_mode;
1775 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1776 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1778 if(volume_info.noperm)
1779 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1780 if(volume_info.setuids)
1781 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1782 if(volume_info.server_ino)
1783 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1784 if(volume_info.remap)
1785 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1786 if(volume_info.no_xattr)
1787 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1788 if(volume_info.sfu_emul)
1789 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1790 if(volume_info.nobrl)
1791 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1793 if(volume_info.direct_io) {
1794 cFYI(1,("mounting share using direct i/o"));
1795 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1799 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1800 volume_info.username);
1802 cFYI(1, ("Found match on UNC path "));
1803 /* we can have only one retry value for a connection
1804 to a share so for resources mounted more than once
1805 to the same server share the last value passed in
1806 for the retry flag is used */
1807 tcon->retry = volume_info.retry;
1808 tcon->nocase = volume_info.nocase;
1810 tcon = tconInfoAlloc();
1814 /* check for null share name ie connect to dfs root */
1816 /* BB check if this works for exactly length three strings */
1817 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1818 && (strchr(volume_info.UNC + 3, '/') ==
1820 rc = connect_to_dfs_path(xid, pSesInfo,
1821 "", cifs_sb->local_nls,
1822 cifs_sb->mnt_cifs_flags &
1823 CIFS_MOUNT_MAP_SPECIAL_CHR);
1825 kfree(volume_info.UNC);
1829 rc = CIFSTCon(xid, pSesInfo,
1831 tcon, cifs_sb->local_nls);
1832 cFYI(1, ("CIFS Tcon rc = %d", rc));
1835 atomic_inc(&pSesInfo->inUse);
1836 tcon->retry = volume_info.retry;
1837 tcon->nocase = volume_info.nocase;
1843 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1844 sb->s_maxbytes = (u64) 1 << 63;
1846 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1849 sb->s_time_gran = 100;
1851 /* on error free sesinfo and tcon struct if needed */
1853 /* if session setup failed, use count is zero but
1854 we still need to free cifsd thread */
1855 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1856 spin_lock(&GlobalMid_Lock);
1857 srvTcp->tcpStatus = CifsExiting;
1858 spin_unlock(&GlobalMid_Lock);
1860 send_sig(SIGKILL,srvTcp->tsk,1);
1861 wait_for_completion(&cifsd_complete);
1864 /* If find_unc succeeded then rc == 0 so we can not end */
1865 if (tcon) /* up accidently freeing someone elses tcon struct */
1867 if (existingCifsSes == NULL) {
1869 if ((pSesInfo->server) &&
1870 (pSesInfo->status == CifsGood)) {
1872 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1873 /* if the socketUseCount is now zero */
1874 if((temp_rc == -ESHUTDOWN) &&
1875 (pSesInfo->server->tsk)) {
1876 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1877 wait_for_completion(&cifsd_complete);
1880 cFYI(1, ("No session or bad tcon"));
1881 sesInfoFree(pSesInfo);
1882 /* pSesInfo = NULL; */
1886 atomic_inc(&tcon->useCount);
1887 cifs_sb->tcon = tcon;
1888 tcon->ses = pSesInfo;
1890 /* do not care if following two calls succeed - informational only */
1891 CIFSSMBQFSDeviceInfo(xid, tcon);
1892 CIFSSMBQFSAttributeInfo(xid, tcon);
1893 if (tcon->ses->capabilities & CAP_UNIX) {
1894 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1895 if(!volume_info.no_psx_acl) {
1896 if(CIFS_UNIX_POSIX_ACL_CAP &
1897 le64_to_cpu(tcon->fsUnixInfo.Capability))
1898 cFYI(1,("server negotiated posix acl support"));
1899 sb->s_flags |= MS_POSIXACL;
1902 /* Try and negotiate POSIX pathnames if we can. */
1903 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
1904 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1905 if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
1906 cFYI(1,("negotiated posix pathnames support"));
1907 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
1909 cFYI(1,("posix pathnames support requested but not supported"));
1914 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
1915 cifs_sb->wsize = min(cifs_sb->wsize,
1916 (tcon->ses->server->maxBuf -
1917 MAX_CIFS_HDR_SIZE));
1918 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
1919 cifs_sb->rsize = min(cifs_sb->rsize,
1920 (tcon->ses->server->maxBuf -
1921 MAX_CIFS_HDR_SIZE));
1924 /* volume_info.password is freed above when existing session found
1925 (in which case it is not needed anymore) but when new sesion is created
1926 the password ptr is put in the new session structure (in which case the
1927 password will be freed at unmount time) */
1929 kfree(volume_info.UNC);
1935 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1936 char session_key[CIFS_SESSION_KEY_SIZE],
1937 const struct nls_table *nls_codepage)
1939 struct smb_hdr *smb_buffer;
1940 struct smb_hdr *smb_buffer_response;
1941 SESSION_SETUP_ANDX *pSMB;
1942 SESSION_SETUP_ANDX *pSMBr;
1947 int remaining_words = 0;
1948 int bytes_returned = 0;
1953 cFYI(1, ("In sesssetup "));
1956 user = ses->userName;
1957 domain = ses->domainName;
1958 smb_buffer = cifs_buf_get();
1959 if (smb_buffer == NULL) {
1962 smb_buffer_response = smb_buffer;
1963 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1965 /* send SMBsessionSetup here */
1966 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1967 NULL /* no tCon exists yet */ , 13 /* wct */ );
1969 smb_buffer->Mid = GetNextMid(ses->server);
1970 pSMB->req_no_secext.AndXCommand = 0xFF;
1971 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1972 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1974 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1975 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1977 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1978 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1979 if (ses->capabilities & CAP_UNICODE) {
1980 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1981 capabilities |= CAP_UNICODE;
1983 if (ses->capabilities & CAP_STATUS32) {
1984 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1985 capabilities |= CAP_STATUS32;
1987 if (ses->capabilities & CAP_DFS) {
1988 smb_buffer->Flags2 |= SMBFLG2_DFS;
1989 capabilities |= CAP_DFS;
1991 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1993 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1994 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1996 pSMB->req_no_secext.CaseSensitivePasswordLength =
1997 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1998 bcc_ptr = pByteArea(smb_buffer);
1999 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
2000 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2001 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
2002 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2004 if (ses->capabilities & CAP_UNICODE) {
2005 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
2010 bytes_returned = 0; /* skill null user */
2013 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
2015 /* convert number of 16 bit words to bytes */
2016 bcc_ptr += 2 * bytes_returned;
2017 bcc_ptr += 2; /* trailing null */
2020 cifs_strtoUCS((wchar_t *) bcc_ptr,
2021 "CIFS_LINUX_DOM", 32, nls_codepage);
2024 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2026 bcc_ptr += 2 * bytes_returned;
2029 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2031 bcc_ptr += 2 * bytes_returned;
2033 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
2035 bcc_ptr += 2 * bytes_returned;
2038 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2040 bcc_ptr += 2 * bytes_returned;
2044 strncpy(bcc_ptr, user, 200);
2045 bcc_ptr += strnlen(user, 200);
2049 if (domain == NULL) {
2050 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2051 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2053 strncpy(bcc_ptr, domain, 64);
2054 bcc_ptr += strnlen(domain, 64);
2058 strcpy(bcc_ptr, "Linux version ");
2059 bcc_ptr += strlen("Linux version ");
2060 strcpy(bcc_ptr, system_utsname.release);
2061 bcc_ptr += strlen(system_utsname.release) + 1;
2062 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2063 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2065 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2066 smb_buffer->smb_buf_length += count;
2067 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2069 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2070 &bytes_returned, 1);
2072 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2073 } else if ((smb_buffer_response->WordCount == 3)
2074 || (smb_buffer_response->WordCount == 4)) {
2075 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2076 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2077 if (action & GUEST_LOGIN)
2078 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
2079 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2080 cFYI(1, ("UID = %d ", ses->Suid));
2081 /* response can have either 3 or 4 word count - Samba sends 3 */
2082 bcc_ptr = pByteArea(smb_buffer_response);
2083 if ((pSMBr->resp.hdr.WordCount == 3)
2084 || ((pSMBr->resp.hdr.WordCount == 4)
2085 && (blob_len < pSMBr->resp.ByteCount))) {
2086 if (pSMBr->resp.hdr.WordCount == 4)
2087 bcc_ptr += blob_len;
2089 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2090 if ((long) (bcc_ptr) % 2) {
2092 (BCC(smb_buffer_response) - 1) /2;
2093 bcc_ptr++; /* Unicode strings must be word aligned */
2096 BCC(smb_buffer_response) / 2;
2099 UniStrnlen((wchar_t *) bcc_ptr,
2100 remaining_words - 1);
2101 /* We look for obvious messed up bcc or strings in response so we do not go off
2102 the end since (at least) WIN2K and Windows XP have a major bug in not null
2103 terminating last Unicode string in response */
2104 ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
2105 if(ses->serverOS == NULL)
2106 goto sesssetup_nomem;
2107 cifs_strfromUCS_le(ses->serverOS,
2108 (wchar_t *)bcc_ptr, len,nls_codepage);
2109 bcc_ptr += 2 * (len + 1);
2110 remaining_words -= len + 1;
2111 ses->serverOS[2 * len] = 0;
2112 ses->serverOS[1 + (2 * len)] = 0;
2113 if (remaining_words > 0) {
2114 len = UniStrnlen((wchar_t *)bcc_ptr,
2116 ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
2117 if(ses->serverNOS == NULL)
2118 goto sesssetup_nomem;
2119 cifs_strfromUCS_le(ses->serverNOS,
2120 (wchar_t *)bcc_ptr,len,nls_codepage);
2121 bcc_ptr += 2 * (len + 1);
2122 ses->serverNOS[2 * len] = 0;
2123 ses->serverNOS[1 + (2 * len)] = 0;
2124 if(strncmp(ses->serverNOS,
2125 "NT LAN Manager 4",16) == 0) {
2126 cFYI(1,("NT4 server"));
2127 ses->flags |= CIFS_SES_NT4;
2129 remaining_words -= len + 1;
2130 if (remaining_words > 0) {
2131 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2132 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2134 kzalloc(2*(len+1),GFP_KERNEL);
2135 if(ses->serverDomain == NULL)
2136 goto sesssetup_nomem;
2137 cifs_strfromUCS_le(ses->serverDomain,
2138 (wchar_t *)bcc_ptr,len,nls_codepage);
2139 bcc_ptr += 2 * (len + 1);
2140 ses->serverDomain[2*len] = 0;
2141 ses->serverDomain[1+(2*len)] = 0;
2142 } /* else no more room so create dummy domain string */
2145 kzalloc(2, GFP_KERNEL);
2146 } else { /* no room so create dummy domain and NOS string */
2147 /* if these kcallocs fail not much we
2148 can do, but better to not fail the
2151 kzalloc(2, GFP_KERNEL);
2153 kzalloc(2, GFP_KERNEL);
2155 } else { /* ASCII */
2156 len = strnlen(bcc_ptr, 1024);
2157 if (((long) bcc_ptr + len) - (long)
2158 pByteArea(smb_buffer_response)
2159 <= BCC(smb_buffer_response)) {
2160 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
2161 if(ses->serverOS == NULL)
2162 goto sesssetup_nomem;
2163 strncpy(ses->serverOS,bcc_ptr, len);
2166 bcc_ptr[0] = 0; /* null terminate the string */
2169 len = strnlen(bcc_ptr, 1024);
2170 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2171 if(ses->serverNOS == NULL)
2172 goto sesssetup_nomem;
2173 strncpy(ses->serverNOS, bcc_ptr, len);
2178 len = strnlen(bcc_ptr, 1024);
2179 ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
2180 if(ses->serverDomain == NULL)
2181 goto sesssetup_nomem;
2182 strncpy(ses->serverDomain, bcc_ptr, len);
2188 ("Variable field of length %d extends beyond end of smb ",
2193 (" Security Blob Length extends beyond end of SMB"));
2197 (" Invalid Word count %d: ",
2198 smb_buffer_response->WordCount));
2201 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2202 since that could make reconnection harder, and
2203 reconnection might be needed to free memory */
2205 cifs_buf_release(smb_buffer);
2211 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2212 char *SecurityBlob,int SecurityBlobLength,
2213 const struct nls_table *nls_codepage)
2215 struct smb_hdr *smb_buffer;
2216 struct smb_hdr *smb_buffer_response;
2217 SESSION_SETUP_ANDX *pSMB;
2218 SESSION_SETUP_ANDX *pSMBr;
2223 int remaining_words = 0;
2224 int bytes_returned = 0;
2229 cFYI(1, ("In spnego sesssetup "));
2232 user = ses->userName;
2233 domain = ses->domainName;
2235 smb_buffer = cifs_buf_get();
2236 if (smb_buffer == NULL) {
2239 smb_buffer_response = smb_buffer;
2240 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2242 /* send SMBsessionSetup here */
2243 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2244 NULL /* no tCon exists yet */ , 12 /* wct */ );
2246 smb_buffer->Mid = GetNextMid(ses->server);
2247 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2248 pSMB->req.AndXCommand = 0xFF;
2249 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2250 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2252 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2253 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2255 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2256 CAP_EXTENDED_SECURITY;
2257 if (ses->capabilities & CAP_UNICODE) {
2258 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2259 capabilities |= CAP_UNICODE;
2261 if (ses->capabilities & CAP_STATUS32) {
2262 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2263 capabilities |= CAP_STATUS32;
2265 if (ses->capabilities & CAP_DFS) {
2266 smb_buffer->Flags2 |= SMBFLG2_DFS;
2267 capabilities |= CAP_DFS;
2269 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2271 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2272 bcc_ptr = pByteArea(smb_buffer);
2273 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2274 bcc_ptr += SecurityBlobLength;
2276 if (ses->capabilities & CAP_UNICODE) {
2277 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2282 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
2283 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2284 bcc_ptr += 2; /* trailing null */
2287 cifs_strtoUCS((wchar_t *) bcc_ptr,
2288 "CIFS_LINUX_DOM", 32, nls_codepage);
2291 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2293 bcc_ptr += 2 * bytes_returned;
2296 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2298 bcc_ptr += 2 * bytes_returned;
2300 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2302 bcc_ptr += 2 * bytes_returned;
2305 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2307 bcc_ptr += 2 * bytes_returned;
2310 strncpy(bcc_ptr, user, 200);
2311 bcc_ptr += strnlen(user, 200);
2314 if (domain == NULL) {
2315 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2316 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2318 strncpy(bcc_ptr, domain, 64);
2319 bcc_ptr += strnlen(domain, 64);
2323 strcpy(bcc_ptr, "Linux version ");
2324 bcc_ptr += strlen("Linux version ");
2325 strcpy(bcc_ptr, system_utsname.release);
2326 bcc_ptr += strlen(system_utsname.release) + 1;
2327 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2328 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2330 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2331 smb_buffer->smb_buf_length += count;
2332 pSMB->req.ByteCount = cpu_to_le16(count);
2334 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2335 &bytes_returned, 1);
2337 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2338 } else if ((smb_buffer_response->WordCount == 3)
2339 || (smb_buffer_response->WordCount == 4)) {
2340 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2342 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2343 if (action & GUEST_LOGIN)
2344 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2346 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2347 cFYI(1, ("UID = %d ", ses->Suid));
2348 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2350 /* BB Fix below to make endian neutral !! */
2352 if ((pSMBr->resp.hdr.WordCount == 3)
2353 || ((pSMBr->resp.hdr.WordCount == 4)
2355 pSMBr->resp.ByteCount))) {
2356 if (pSMBr->resp.hdr.WordCount == 4) {
2360 ("Security Blob Length %d ",
2364 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2365 if ((long) (bcc_ptr) % 2) {
2367 (BCC(smb_buffer_response)
2369 bcc_ptr++; /* Unicode strings must be word aligned */
2373 (smb_buffer_response) / 2;
2376 UniStrnlen((wchar_t *) bcc_ptr,
2377 remaining_words - 1);
2378 /* We look for obvious messed up bcc or strings in response so we do not go off
2379 the end since (at least) WIN2K and Windows XP have a major bug in not null
2380 terminating last Unicode string in response */
2382 kzalloc(2 * (len + 1), GFP_KERNEL);
2383 cifs_strfromUCS_le(ses->serverOS,
2387 bcc_ptr += 2 * (len + 1);
2388 remaining_words -= len + 1;
2389 ses->serverOS[2 * len] = 0;
2390 ses->serverOS[1 + (2 * len)] = 0;
2391 if (remaining_words > 0) {
2392 len = UniStrnlen((wchar_t *)bcc_ptr,
2396 kzalloc(2 * (len + 1),
2398 cifs_strfromUCS_le(ses->serverNOS,
2402 bcc_ptr += 2 * (len + 1);
2403 ses->serverNOS[2 * len] = 0;
2404 ses->serverNOS[1 + (2 * len)] = 0;
2405 remaining_words -= len + 1;
2406 if (remaining_words > 0) {
2407 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2408 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2409 ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
2410 cifs_strfromUCS_le(ses->serverDomain,
2414 bcc_ptr += 2*(len+1);
2415 ses->serverDomain[2*len] = 0;
2416 ses->serverDomain[1+(2*len)] = 0;
2417 } /* else no more room so create dummy domain string */
2420 kzalloc(2,GFP_KERNEL);
2421 } else { /* no room so create dummy domain and NOS string */
2422 ses->serverDomain = kzalloc(2, GFP_KERNEL);
2423 ses->serverNOS = kzalloc(2, GFP_KERNEL);
2425 } else { /* ASCII */
2427 len = strnlen(bcc_ptr, 1024);
2428 if (((long) bcc_ptr + len) - (long)
2429 pByteArea(smb_buffer_response)
2430 <= BCC(smb_buffer_response)) {
2431 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
2432 strncpy(ses->serverOS, bcc_ptr, len);
2435 bcc_ptr[0] = 0; /* null terminate the string */
2438 len = strnlen(bcc_ptr, 1024);
2439 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2440 strncpy(ses->serverNOS, bcc_ptr, len);
2445 len = strnlen(bcc_ptr, 1024);
2446 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
2447 strncpy(ses->serverDomain, bcc_ptr, len);
2453 ("Variable field of length %d extends beyond end of smb ",
2458 (" Security Blob Length extends beyond end of SMB"));
2461 cERROR(1, ("No session structure passed in."));
2465 (" Invalid Word count %d: ",
2466 smb_buffer_response->WordCount));
2471 cifs_buf_release(smb_buffer);
2477 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2478 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2479 const struct nls_table *nls_codepage)
2481 struct smb_hdr *smb_buffer;
2482 struct smb_hdr *smb_buffer_response;
2483 SESSION_SETUP_ANDX *pSMB;
2484 SESSION_SETUP_ANDX *pSMBr;
2488 int remaining_words = 0;
2489 int bytes_returned = 0;
2491 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2492 PNEGOTIATE_MESSAGE SecurityBlob;
2493 PCHALLENGE_MESSAGE SecurityBlob2;
2494 __u32 negotiate_flags, capabilities;
2497 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2500 domain = ses->domainName;
2501 *pNTLMv2_flag = FALSE;
2502 smb_buffer = cifs_buf_get();
2503 if (smb_buffer == NULL) {
2506 smb_buffer_response = smb_buffer;
2507 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2508 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2510 /* send SMBsessionSetup here */
2511 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2512 NULL /* no tCon exists yet */ , 12 /* wct */ );
2514 smb_buffer->Mid = GetNextMid(ses->server);
2515 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2516 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2518 pSMB->req.AndXCommand = 0xFF;
2519 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2520 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2522 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2523 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2525 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2526 CAP_EXTENDED_SECURITY;
2527 if (ses->capabilities & CAP_UNICODE) {
2528 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2529 capabilities |= CAP_UNICODE;
2531 if (ses->capabilities & CAP_STATUS32) {
2532 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2533 capabilities |= CAP_STATUS32;
2535 if (ses->capabilities & CAP_DFS) {
2536 smb_buffer->Flags2 |= SMBFLG2_DFS;
2537 capabilities |= CAP_DFS;
2539 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2541 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2542 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2543 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2544 SecurityBlob->MessageType = NtLmNegotiate;
2546 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2547 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2548 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2550 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2552 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2553 /* setup pointers to domain name and workstation name */
2554 bcc_ptr += SecurityBlobLength;
2556 SecurityBlob->WorkstationName.Buffer = 0;
2557 SecurityBlob->WorkstationName.Length = 0;
2558 SecurityBlob->WorkstationName.MaximumLength = 0;
2560 if (domain == NULL) {
2561 SecurityBlob->DomainName.Buffer = 0;
2562 SecurityBlob->DomainName.Length = 0;
2563 SecurityBlob->DomainName.MaximumLength = 0;
2566 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2567 strncpy(bcc_ptr, domain, 63);
2568 len = strnlen(domain, 64);
2569 SecurityBlob->DomainName.MaximumLength =
2571 SecurityBlob->DomainName.Buffer =
2572 cpu_to_le32((long) &SecurityBlob->
2574 (long) &SecurityBlob->Signature);
2576 SecurityBlobLength += len;
2577 SecurityBlob->DomainName.Length =
2580 if (ses->capabilities & CAP_UNICODE) {
2581 if ((long) bcc_ptr % 2) {
2587 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2589 bcc_ptr += 2 * bytes_returned;
2591 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2593 bcc_ptr += 2 * bytes_returned;
2594 bcc_ptr += 2; /* null terminate Linux version */
2596 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2598 bcc_ptr += 2 * bytes_returned;
2601 bcc_ptr += 2; /* null terminate network opsys string */
2604 bcc_ptr += 2; /* null domain */
2605 } else { /* ASCII */
2606 strcpy(bcc_ptr, "Linux version ");
2607 bcc_ptr += strlen("Linux version ");
2608 strcpy(bcc_ptr, system_utsname.release);
2609 bcc_ptr += strlen(system_utsname.release) + 1;
2610 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2611 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2612 bcc_ptr++; /* empty domain field */
2615 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2616 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2617 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2618 smb_buffer->smb_buf_length += count;
2619 pSMB->req.ByteCount = cpu_to_le16(count);
2621 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2622 &bytes_returned, 1);
2624 if (smb_buffer_response->Status.CifsError ==
2625 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2629 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2630 } else if ((smb_buffer_response->WordCount == 3)
2631 || (smb_buffer_response->WordCount == 4)) {
2632 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2633 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2635 if (action & GUEST_LOGIN)
2636 cFYI(1, (" Guest login"));
2637 /* Do we want to set anything in SesInfo struct when guest login? */
2639 bcc_ptr = pByteArea(smb_buffer_response);
2640 /* response can have either 3 or 4 word count - Samba sends 3 */
2642 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2643 if (SecurityBlob2->MessageType != NtLmChallenge) {
2645 ("Unexpected NTLMSSP message type received %d",
2646 SecurityBlob2->MessageType));
2648 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2649 cFYI(1, ("UID = %d ", ses->Suid));
2650 if ((pSMBr->resp.hdr.WordCount == 3)
2651 || ((pSMBr->resp.hdr.WordCount == 4)
2653 pSMBr->resp.ByteCount))) {
2655 if (pSMBr->resp.hdr.WordCount == 4) {
2656 bcc_ptr += blob_len;
2658 ("Security Blob Length %d ",
2662 cFYI(1, ("NTLMSSP Challenge rcvd "));
2664 memcpy(ses->server->cryptKey,
2665 SecurityBlob2->Challenge,
2666 CIFS_CRYPTO_KEY_SIZE);
2667 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2668 *pNTLMv2_flag = TRUE;
2670 if((SecurityBlob2->NegotiateFlags &
2671 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2672 || (sign_CIFS_PDUs > 1))
2673 ses->server->secMode |=
2674 SECMODE_SIGN_REQUIRED;
2675 if ((SecurityBlob2->NegotiateFlags &
2676 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2677 ses->server->secMode |=
2678 SECMODE_SIGN_ENABLED;
2680 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2681 if ((long) (bcc_ptr) % 2) {
2683 (BCC(smb_buffer_response)
2685 bcc_ptr++; /* Unicode strings must be word aligned */
2689 (smb_buffer_response) / 2;
2692 UniStrnlen((wchar_t *) bcc_ptr,
2693 remaining_words - 1);
2694 /* We look for obvious messed up bcc or strings in response so we do not go off
2695 the end since (at least) WIN2K and Windows XP have a major bug in not null
2696 terminating last Unicode string in response */
2698 kzalloc(2 * (len + 1), GFP_KERNEL);
2699 cifs_strfromUCS_le(ses->serverOS,
2703 bcc_ptr += 2 * (len + 1);
2704 remaining_words -= len + 1;
2705 ses->serverOS[2 * len] = 0;
2706 ses->serverOS[1 + (2 * len)] = 0;
2707 if (remaining_words > 0) {
2708 len = UniStrnlen((wchar_t *)
2713 kzalloc(2 * (len + 1),
2715 cifs_strfromUCS_le(ses->
2721 bcc_ptr += 2 * (len + 1);
2722 ses->serverNOS[2 * len] = 0;
2725 remaining_words -= len + 1;
2726 if (remaining_words > 0) {
2727 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2728 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2753 } /* else no more room so create dummy domain string */
2758 } else { /* no room so create dummy domain and NOS string */
2760 kzalloc(2, GFP_KERNEL);
2762 kzalloc(2, GFP_KERNEL);
2764 } else { /* ASCII */
2765 len = strnlen(bcc_ptr, 1024);
2766 if (((long) bcc_ptr + len) - (long)
2767 pByteArea(smb_buffer_response)
2768 <= BCC(smb_buffer_response)) {
2772 strncpy(ses->serverOS,
2776 bcc_ptr[0] = 0; /* null terminate string */
2779 len = strnlen(bcc_ptr, 1024);
2783 strncpy(ses->serverNOS, bcc_ptr, len);
2788 len = strnlen(bcc_ptr, 1024);
2792 strncpy(ses->serverDomain, bcc_ptr, len);
2798 ("Variable field of length %d extends beyond end of smb ",
2803 (" Security Blob Length extends beyond end of SMB"));
2806 cERROR(1, ("No session structure passed in."));
2810 (" Invalid Word count %d: ",
2811 smb_buffer_response->WordCount));
2816 cifs_buf_release(smb_buffer);
2821 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2822 char *ntlm_session_key, int ntlmv2_flag,
2823 const struct nls_table *nls_codepage)
2825 struct smb_hdr *smb_buffer;
2826 struct smb_hdr *smb_buffer_response;
2827 SESSION_SETUP_ANDX *pSMB;
2828 SESSION_SETUP_ANDX *pSMBr;
2833 int remaining_words = 0;
2834 int bytes_returned = 0;
2836 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2837 PAUTHENTICATE_MESSAGE SecurityBlob;
2838 __u32 negotiate_flags, capabilities;
2841 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2844 user = ses->userName;
2845 domain = ses->domainName;
2846 smb_buffer = cifs_buf_get();
2847 if (smb_buffer == NULL) {
2850 smb_buffer_response = smb_buffer;
2851 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2852 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2854 /* send SMBsessionSetup here */
2855 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2856 NULL /* no tCon exists yet */ , 12 /* wct */ );
2858 smb_buffer->Mid = GetNextMid(ses->server);
2859 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2860 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2861 pSMB->req.AndXCommand = 0xFF;
2862 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2863 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2865 pSMB->req.hdr.Uid = ses->Suid;
2867 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2868 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2870 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2871 CAP_EXTENDED_SECURITY;
2872 if (ses->capabilities & CAP_UNICODE) {
2873 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2874 capabilities |= CAP_UNICODE;
2876 if (ses->capabilities & CAP_STATUS32) {
2877 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2878 capabilities |= CAP_STATUS32;
2880 if (ses->capabilities & CAP_DFS) {
2881 smb_buffer->Flags2 |= SMBFLG2_DFS;
2882 capabilities |= CAP_DFS;
2884 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2886 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2887 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2888 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2889 SecurityBlob->MessageType = NtLmAuthenticate;
2890 bcc_ptr += SecurityBlobLength;
2892 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2893 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2894 0x80000000 | NTLMSSP_NEGOTIATE_128;
2896 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2898 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2900 /* setup pointers to domain name and workstation name */
2902 SecurityBlob->WorkstationName.Buffer = 0;
2903 SecurityBlob->WorkstationName.Length = 0;
2904 SecurityBlob->WorkstationName.MaximumLength = 0;
2905 SecurityBlob->SessionKey.Length = 0;
2906 SecurityBlob->SessionKey.MaximumLength = 0;
2907 SecurityBlob->SessionKey.Buffer = 0;
2909 SecurityBlob->LmChallengeResponse.Length = 0;
2910 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2911 SecurityBlob->LmChallengeResponse.Buffer = 0;
2913 SecurityBlob->NtChallengeResponse.Length =
2914 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2915 SecurityBlob->NtChallengeResponse.MaximumLength =
2916 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2917 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2918 SecurityBlob->NtChallengeResponse.Buffer =
2919 cpu_to_le32(SecurityBlobLength);
2920 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2921 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2923 if (ses->capabilities & CAP_UNICODE) {
2924 if (domain == NULL) {
2925 SecurityBlob->DomainName.Buffer = 0;
2926 SecurityBlob->DomainName.Length = 0;
2927 SecurityBlob->DomainName.MaximumLength = 0;
2930 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2933 SecurityBlob->DomainName.MaximumLength =
2935 SecurityBlob->DomainName.Buffer =
2936 cpu_to_le32(SecurityBlobLength);
2938 SecurityBlobLength += len;
2939 SecurityBlob->DomainName.Length =
2943 SecurityBlob->UserName.Buffer = 0;
2944 SecurityBlob->UserName.Length = 0;
2945 SecurityBlob->UserName.MaximumLength = 0;
2948 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2951 SecurityBlob->UserName.MaximumLength =
2953 SecurityBlob->UserName.Buffer =
2954 cpu_to_le32(SecurityBlobLength);
2956 SecurityBlobLength += len;
2957 SecurityBlob->UserName.Length =
2961 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2962 SecurityBlob->WorkstationName.Length *= 2;
2963 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2964 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2965 bcc_ptr += SecurityBlob->WorkstationName.Length;
2966 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2967 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2969 if ((long) bcc_ptr % 2) {
2974 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2976 bcc_ptr += 2 * bytes_returned;
2978 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2980 bcc_ptr += 2 * bytes_returned;
2981 bcc_ptr += 2; /* null term version string */
2983 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2985 bcc_ptr += 2 * bytes_returned;
2988 bcc_ptr += 2; /* null terminate network opsys string */
2991 bcc_ptr += 2; /* null domain */
2992 } else { /* ASCII */
2993 if (domain == NULL) {
2994 SecurityBlob->DomainName.Buffer = 0;
2995 SecurityBlob->DomainName.Length = 0;
2996 SecurityBlob->DomainName.MaximumLength = 0;
2999 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3000 strncpy(bcc_ptr, domain, 63);
3001 len = strnlen(domain, 64);
3002 SecurityBlob->DomainName.MaximumLength =
3004 SecurityBlob->DomainName.Buffer =
3005 cpu_to_le32(SecurityBlobLength);
3007 SecurityBlobLength += len;
3008 SecurityBlob->DomainName.Length = cpu_to_le16(len);
3011 SecurityBlob->UserName.Buffer = 0;
3012 SecurityBlob->UserName.Length = 0;
3013 SecurityBlob->UserName.MaximumLength = 0;
3016 strncpy(bcc_ptr, user, 63);
3017 len = strnlen(user, 64);
3018 SecurityBlob->UserName.MaximumLength =
3020 SecurityBlob->UserName.Buffer =
3021 cpu_to_le32(SecurityBlobLength);
3023 SecurityBlobLength += len;
3024 SecurityBlob->UserName.Length = cpu_to_le16(len);
3026 /* BB fill in our workstation name if known BB */
3028 strcpy(bcc_ptr, "Linux version ");
3029 bcc_ptr += strlen("Linux version ");
3030 strcpy(bcc_ptr, system_utsname.release);
3031 bcc_ptr += strlen(system_utsname.release) + 1;
3032 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3033 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3034 bcc_ptr++; /* null domain */
3037 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3038 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3039 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3040 smb_buffer->smb_buf_length += count;
3041 pSMB->req.ByteCount = cpu_to_le16(count);
3043 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3044 &bytes_returned, 1);
3046 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
3047 } else if ((smb_buffer_response->WordCount == 3)
3048 || (smb_buffer_response->WordCount == 4)) {
3049 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3051 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3052 if (action & GUEST_LOGIN)
3053 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
3054 /* if(SecurityBlob2->MessageType != NtLm??){
3055 cFYI("Unexpected message type on auth response is %d "));
3059 ("Does UID on challenge %d match auth response UID %d ",
3060 ses->Suid, smb_buffer_response->Uid));
3061 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
3062 bcc_ptr = pByteArea(smb_buffer_response);
3063 /* response can have either 3 or 4 word count - Samba sends 3 */
3064 if ((pSMBr->resp.hdr.WordCount == 3)
3065 || ((pSMBr->resp.hdr.WordCount == 4)
3067 pSMBr->resp.ByteCount))) {
3068 if (pSMBr->resp.hdr.WordCount == 4) {
3072 ("Security Blob Length %d ",
3077 ("NTLMSSP response to Authenticate "));
3079 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3080 if ((long) (bcc_ptr) % 2) {
3082 (BCC(smb_buffer_response)
3084 bcc_ptr++; /* Unicode strings must be word aligned */
3086 remaining_words = BCC(smb_buffer_response) / 2;
3089 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
3090 /* We look for obvious messed up bcc or strings in response so we do not go off
3091 the end since (at least) WIN2K and Windows XP have a major bug in not null
3092 terminating last Unicode string in response */
3094 kzalloc(2 * (len + 1), GFP_KERNEL);
3095 cifs_strfromUCS_le(ses->serverOS,
3099 bcc_ptr += 2 * (len + 1);
3100 remaining_words -= len + 1;
3101 ses->serverOS[2 * len] = 0;
3102 ses->serverOS[1 + (2 * len)] = 0;
3103 if (remaining_words > 0) {
3104 len = UniStrnlen((wchar_t *)
3109 kzalloc(2 * (len + 1),
3111 cifs_strfromUCS_le(ses->
3117 bcc_ptr += 2 * (len + 1);
3118 ses->serverNOS[2 * len] = 0;
3119 ses->serverNOS[1+(2*len)] = 0;
3120 remaining_words -= len + 1;
3121 if (remaining_words > 0) {
3122 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3123 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3148 } /* else no more room so create dummy domain string */
3150 ses->serverDomain = kzalloc(2,GFP_KERNEL);
3151 } else { /* no room so create dummy domain and NOS string */
3152 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3153 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3155 } else { /* ASCII */
3156 len = strnlen(bcc_ptr, 1024);
3157 if (((long) bcc_ptr + len) -
3158 (long) pByteArea(smb_buffer_response)
3159 <= BCC(smb_buffer_response)) {
3160 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
3161 strncpy(ses->serverOS,bcc_ptr, len);
3164 bcc_ptr[0] = 0; /* null terminate the string */
3167 len = strnlen(bcc_ptr, 1024);
3168 ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
3169 strncpy(ses->serverNOS, bcc_ptr, len);
3174 len = strnlen(bcc_ptr, 1024);
3175 ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
3176 strncpy(ses->serverDomain, bcc_ptr, len);
3182 ("Variable field of length %d extends beyond end of smb ",
3187 (" Security Blob Length extends beyond end of SMB"));
3190 cERROR(1, ("No session structure passed in."));
3194 (" Invalid Word count %d: ",
3195 smb_buffer_response->WordCount));
3200 cifs_buf_release(smb_buffer);
3206 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3207 const char *tree, struct cifsTconInfo *tcon,
3208 const struct nls_table *nls_codepage)
3210 struct smb_hdr *smb_buffer;
3211 struct smb_hdr *smb_buffer_response;
3214 unsigned char *bcc_ptr;
3222 smb_buffer = cifs_buf_get();
3223 if (smb_buffer == NULL) {
3226 smb_buffer_response = smb_buffer;
3228 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3229 NULL /*no tid */ , 4 /*wct */ );
3231 smb_buffer->Mid = GetNextMid(ses->server);
3232 smb_buffer->Uid = ses->Suid;
3233 pSMB = (TCONX_REQ *) smb_buffer;
3234 pSMBr = (TCONX_RSP *) smb_buffer_response;
3236 pSMB->AndXCommand = 0xFF;
3237 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3238 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3239 bcc_ptr = &pSMB->Password[0];
3240 bcc_ptr++; /* skip password */
3242 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3243 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3245 if (ses->capabilities & CAP_STATUS32) {
3246 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3248 if (ses->capabilities & CAP_DFS) {
3249 smb_buffer->Flags2 |= SMBFLG2_DFS;
3251 if (ses->capabilities & CAP_UNICODE) {
3252 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3254 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
3255 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3256 bcc_ptr += 2; /* skip trailing null */
3257 } else { /* ASCII */
3259 strcpy(bcc_ptr, tree);
3260 bcc_ptr += strlen(tree) + 1;
3262 strcpy(bcc_ptr, "?????");
3263 bcc_ptr += strlen("?????");
3265 count = bcc_ptr - &pSMB->Password[0];
3266 pSMB->hdr.smb_buf_length += count;
3267 pSMB->ByteCount = cpu_to_le16(count);
3269 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3271 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3272 /* above now done in SendReceive */
3273 if ((rc == 0) && (tcon != NULL)) {
3274 tcon->tidStatus = CifsGood;
3275 tcon->tid = smb_buffer_response->Tid;
3276 bcc_ptr = pByteArea(smb_buffer_response);
3277 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3278 /* skip service field (NB: this field is always ASCII) */
3279 bcc_ptr += length + 1;
3280 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3281 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3282 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3283 if ((bcc_ptr + (2 * length)) -
3284 pByteArea(smb_buffer_response) <=
3285 BCC(smb_buffer_response)) {
3286 if(tcon->nativeFileSystem)
3287 kfree(tcon->nativeFileSystem);
3288 tcon->nativeFileSystem =
3289 kzalloc(length + 2, GFP_KERNEL);
3290 cifs_strfromUCS_le(tcon->nativeFileSystem,
3291 (wchar_t *) bcc_ptr,
3292 length, nls_codepage);
3293 bcc_ptr += 2 * length;
3294 bcc_ptr[0] = 0; /* null terminate the string */
3298 /* else do not bother copying these informational fields */
3300 length = strnlen(bcc_ptr, 1024);
3301 if ((bcc_ptr + length) -
3302 pByteArea(smb_buffer_response) <=
3303 BCC(smb_buffer_response)) {
3304 if(tcon->nativeFileSystem)
3305 kfree(tcon->nativeFileSystem);
3306 tcon->nativeFileSystem =
3307 kzalloc(length + 1, GFP_KERNEL);
3308 strncpy(tcon->nativeFileSystem, bcc_ptr,
3311 /* else do not bother copying these informational fields */
3313 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3314 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3315 } else if ((rc == 0) && tcon == NULL) {
3316 /* all we need to save for IPC$ connection */
3317 ses->ipc_tid = smb_buffer_response->Tid;
3321 cifs_buf_release(smb_buffer);
3326 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3330 struct cifsSesInfo *ses = NULL;
3331 struct task_struct *cifsd_task;
3335 if (cifs_sb->tcon) {
3336 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3337 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3342 tconInfoFree(cifs_sb->tcon);
3343 if ((ses) && (ses->server)) {
3344 /* save off task so we do not refer to ses later */
3345 cifsd_task = ses->server->tsk;
3346 cFYI(1, ("About to do SMBLogoff "));
3347 rc = CIFSSMBLogoff(xid, ses);
3351 } else if (rc == -ESHUTDOWN) {
3352 cFYI(1,("Waking up socket by sending it signal"));
3354 send_sig(SIGKILL,cifsd_task,1);
3355 wait_for_completion(&cifsd_complete);
3358 } /* else - we have an smb session
3359 left on this socket do not kill cifsd */
3361 cFYI(1, ("No session or bad tcon"));
3364 cifs_sb->tcon = NULL;
3366 schedule_timeout_interruptible(msecs_to_jiffies(500));
3371 return rc; /* BB check if we should always return zero here */
3374 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3375 struct nls_table * nls_info)
3378 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3379 int ntlmv2_flag = FALSE;
3382 /* what if server changes its buffer size after dropping the session? */
3383 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3384 rc = CIFSSMBNegotiate(xid, pSesInfo);
3385 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3386 rc = CIFSSMBNegotiate(xid, pSesInfo);
3391 spin_lock(&GlobalMid_Lock);
3392 if(pSesInfo->server->tcpStatus != CifsExiting)
3393 pSesInfo->server->tcpStatus = CifsGood;
3396 spin_unlock(&GlobalMid_Lock);
3402 pSesInfo->capabilities = pSesInfo->server->capabilities;
3403 if(linuxExtEnabled == 0)
3404 pSesInfo->capabilities &= (~CAP_UNIX);
3405 /* pSesInfo->sequence_number = 0;*/
3406 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3407 pSesInfo->server->secMode,
3408 pSesInfo->server->capabilities,
3409 pSesInfo->server->timeZone));
3410 if (extended_security
3411 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3412 && (pSesInfo->server->secType == NTLMSSP)) {
3413 cFYI(1, ("New style sesssetup "));
3414 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3415 NULL /* security blob */,
3416 0 /* blob length */,
3418 } else if (extended_security
3419 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3420 && (pSesInfo->server->secType == RawNTLMSSP)) {
3421 cFYI(1, ("NTLMSSP sesssetup "));
3422 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3429 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3430 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3435 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3437 CalcNTLMv2_response(pSesInfo,v2_response);
3439 cifs_calculate_ntlmv2_mac_key(
3440 pSesInfo->server->mac_signing_key,
3441 response, ntlm_session_key, */
3443 /* BB Put dummy sig in SessSetup PDU? */
3450 SMBNTencrypt(pSesInfo->password,
3451 pSesInfo->server->cryptKey,
3455 cifs_calculate_mac_key(
3456 pSesInfo->server->mac_signing_key,
3458 pSesInfo->password);
3460 /* for better security the weaker lanman hash not sent
3461 in AuthSessSetup so we no longer calculate it */
3463 rc = CIFSNTLMSSPAuthSessSetup(xid,
3469 } else { /* old style NTLM 0.12 session setup */
3470 SMBNTencrypt(pSesInfo->password,
3471 pSesInfo->server->cryptKey,
3475 cifs_calculate_mac_key(
3476 pSesInfo->server->mac_signing_key,
3477 ntlm_session_key, pSesInfo->password);
3479 rc = CIFSSessSetup(xid, pSesInfo,
3480 ntlm_session_key, nls_info);
3483 cERROR(1,("Send error in SessSetup = %d",rc));
3485 cFYI(1,("CIFS Session Established successfully"));
3486 pSesInfo->status = CifsGood;