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 <asm/uaccess.h>
33 #include <asm/processor.h>
36 #include "cifsproto.h"
37 #include "cifs_unicode.h"
38 #include "cifs_debug.h"
39 #include "cifs_fs_sb.h"
42 #include "rfc1002pdu.h"
45 #define RFC1001_PORT 139
47 extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
49 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
52 extern mempool_t *cifs_req_poolp;
60 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
61 char *iocharset; /* local code page for mapping to and from Unicode */
62 char source_rfc1001_name[16]; /* netbios name of client */
72 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
73 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
74 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
76 unsigned remap:1; /* set to remap seven reserved chars in filenames */
77 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
82 unsigned short int port;
85 static int ipv4_connect(struct sockaddr_in *psin_server,
86 struct socket **csocket,
88 static int ipv6_connect(struct sockaddr_in6 *psin_server,
89 struct socket **csocket);
93 * cifs tcp session reconnection
95 * mark tcp session as reconnecting so temporarily locked
96 * mark all smb sessions as reconnecting for tcp session
97 * reconnect tcp session
98 * wake up waiters on reconnection? - (not needed currently)
102 cifs_reconnect(struct TCP_Server_Info *server)
105 struct list_head *tmp;
106 struct cifsSesInfo *ses;
107 struct cifsTconInfo *tcon;
108 struct mid_q_entry * mid_entry;
110 spin_lock(&GlobalMid_Lock);
111 if(server->tcpStatus == CifsExiting) {
112 /* the demux thread will exit normally
113 next time through the loop */
114 spin_unlock(&GlobalMid_Lock);
117 server->tcpStatus = CifsNeedReconnect;
118 spin_unlock(&GlobalMid_Lock);
121 cFYI(1, ("Reconnecting tcp session"));
123 /* before reconnecting the tcp session, mark the smb session (uid)
124 and the tid bad so they are not used until reconnected */
125 read_lock(&GlobalSMBSeslock);
126 list_for_each(tmp, &GlobalSMBSessionList) {
127 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
129 if (ses->server == server) {
130 ses->status = CifsNeedReconnect;
134 /* else tcp and smb sessions need reconnection */
136 list_for_each(tmp, &GlobalTreeConnectionList) {
137 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
138 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
139 tcon->tidStatus = CifsNeedReconnect;
142 read_unlock(&GlobalSMBSeslock);
143 /* do not want to be sending data on a socket we are freeing */
144 down(&server->tcpSem);
145 if(server->ssocket) {
146 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
147 server->ssocket->flags));
148 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
149 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
150 server->ssocket->flags));
151 sock_release(server->ssocket);
152 server->ssocket = NULL;
155 spin_lock(&GlobalMid_Lock);
156 list_for_each(tmp, &server->pending_mid_q) {
157 mid_entry = list_entry(tmp, struct
161 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
162 /* Mark other intransit requests as needing
163 retry so we do not immediately mark the
164 session bad again (ie after we reconnect
165 below) as they timeout too */
166 mid_entry->midState = MID_RETRY_NEEDED;
170 spin_unlock(&GlobalMid_Lock);
173 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
175 if(server->protocolType == IPV6) {
176 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
178 rc = ipv4_connect(&server->addr.sockAddr,
180 server->workstation_RFC1001_name);
185 atomic_inc(&tcpSesReconnectCount);
186 spin_lock(&GlobalMid_Lock);
187 if(server->tcpStatus != CifsExiting)
188 server->tcpStatus = CifsGood;
189 server->sequence_number = 0;
190 spin_unlock(&GlobalMid_Lock);
191 /* atomic_set(&server->inFlight,0);*/
192 wake_up(&server->response_q);
200 0 not a transact2, or all data present
201 >0 transact2 with that much data missing
202 -EINVAL = invalid transact2
205 static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
207 struct smb_t2_rsp * pSMBt;
209 int data_in_this_rsp;
212 if(pSMB->Command != SMB_COM_TRANSACTION2)
215 /* check for plausible wct, bcc and t2 data and parm sizes */
216 /* check for parm and data offset going beyond end of smb */
217 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
218 cFYI(1,("invalid transact2 word count"));
222 pSMBt = (struct smb_t2_rsp *)pSMB;
224 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
225 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
227 remaining = total_data_size - data_in_this_rsp;
231 else if(remaining < 0) {
232 cFYI(1,("total data %d smaller than data in frame %d",
233 total_data_size, data_in_this_rsp));
236 cFYI(1,("missing %d bytes from transact2, check next response",
238 if(total_data_size > maxBufSize) {
239 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
240 total_data_size,maxBufSize));
247 static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
249 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
250 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
255 char * data_area_of_target;
256 char * data_area_of_buf2;
259 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
261 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
262 cFYI(1,("total data sizes of primary and secondary t2 differ"));
265 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
267 remaining = total_data_size - total_in_buf;
272 if(remaining == 0) /* nothing to do, ignore */
275 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
276 if(remaining < total_in_buf2) {
277 cFYI(1,("transact2 2nd response contains too much data"));
280 /* find end of first SMB data area */
281 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
282 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
283 /* validate target area */
285 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
286 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
288 data_area_of_target += total_in_buf;
290 /* copy second buffer into end of first buffer */
291 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
292 total_in_buf += total_in_buf2;
293 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
294 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
295 byte_count += total_in_buf2;
296 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
298 byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
299 byte_count += total_in_buf2;
301 /* BB also add check that we are not beyond maximum buffer size */
303 pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
305 if(remaining == total_in_buf2) {
306 cFYI(1,("found the last secondary response"));
307 return 0; /* we are done */
308 } else /* more responses to go */
314 cifs_demultiplex_thread(struct TCP_Server_Info *server)
317 unsigned int pdu_length, total_read;
318 struct smb_hdr *smb_buffer = NULL;
319 struct smb_hdr *bigbuf = NULL;
320 struct smb_hdr *smallbuf = NULL;
321 struct msghdr smb_msg;
323 struct socket *csocket = server->ssocket;
324 struct list_head *tmp;
325 struct cifsSesInfo *ses;
326 struct task_struct *task_to_wake = NULL;
327 struct mid_q_entry *mid_entry;
329 int isLargeBuf = FALSE;
334 allow_signal(SIGKILL);
335 current->flags |= PF_MEMALLOC;
336 server->tsk = current; /* save process info to wake at shutdown */
337 cFYI(1, ("Demultiplex PID: %d", current->pid));
338 write_lock(&GlobalSMBSeslock);
339 atomic_inc(&tcpSesAllocCount);
340 length = tcpSesAllocCount.counter;
341 write_unlock(&GlobalSMBSeslock);
343 mempool_resize(cifs_req_poolp,
344 length + cifs_min_rcv,
348 while (server->tcpStatus != CifsExiting) {
349 if (bigbuf == NULL) {
350 bigbuf = cifs_buf_get();
352 cERROR(1,("No memory for large SMB response"));
354 /* retry will check if exiting */
357 } else if(isLargeBuf) {
358 /* we are reusing a dirtry large buf, clear its start */
359 memset(bigbuf, 0, sizeof (struct smb_hdr));
362 if (smallbuf == NULL) {
363 smallbuf = cifs_small_buf_get();
364 if(smallbuf == NULL) {
365 cERROR(1,("No memory for SMB response"));
367 /* retry will check if exiting */
370 /* beginning of smb buffer is cleared in our buf_get */
371 } else /* if existing small buf clear beginning */
372 memset(smallbuf, 0, sizeof (struct smb_hdr));
376 smb_buffer = smallbuf;
377 iov.iov_base = smb_buffer;
379 smb_msg.msg_control = NULL;
380 smb_msg.msg_controllen = 0;
382 kernel_recvmsg(csocket, &smb_msg,
383 &iov, 1, 4, 0 /* BB see socket.h flags */);
385 if(server->tcpStatus == CifsExiting) {
387 } else if (server->tcpStatus == CifsNeedReconnect) {
388 cFYI(1,("Reconnect after server stopped responding"));
389 cifs_reconnect(server);
390 cFYI(1,("call to reconnect done"));
391 csocket = server->ssocket;
393 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
394 msleep(1); /* minimum sleep to prevent looping
395 allowing socket to clear and app threads to set
396 tcpStatus CifsNeedReconnect if server hung */
398 } else if (length <= 0) {
399 if(server->tcpStatus == CifsNew) {
400 cFYI(1,("tcp session abend after SMBnegprot"));
401 /* some servers kill the TCP session rather than
402 returning an SMB negprot error, in which
403 case reconnecting here is not going to help,
404 and so simply return error to mount */
407 if(length == -EINTR) {
408 cFYI(1,("cifsd thread killed"));
411 cFYI(1,("Reconnect after unexpected peek error %d",
413 cifs_reconnect(server);
414 csocket = server->ssocket;
415 wake_up(&server->response_q);
417 } else if (length < 4) {
419 ("Frame under four bytes received (%d bytes long)",
421 cifs_reconnect(server);
422 csocket = server->ssocket;
423 wake_up(&server->response_q);
427 /* the right amount was read from socket - 4 bytes */
429 pdu_length = ntohl(smb_buffer->smb_buf_length);
430 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
432 temp = (char *) smb_buffer;
433 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
435 } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
436 cFYI(1,("Good RFC 1002 session rsp"));
438 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
439 /* we get this from Windows 98 instead of
440 an error on SMB negprot response */
441 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
443 if(server->tcpStatus == CifsNew) {
444 /* if nack on negprot (rather than
445 ret of smb negprot error) reconnecting
446 not going to help, ret error to mount */
449 /* give server a second to
450 clean up before reconnect attempt */
452 /* always try 445 first on reconnect
453 since we get NACK on some if we ever
454 connected to port 139 (the NACK is
455 since we do not begin with RFC1001
456 session initialize frame) */
457 server->addr.sockAddr.sin_port =
459 cifs_reconnect(server);
460 csocket = server->ssocket;
461 wake_up(&server->response_q);
464 } else if (temp[0] != (char) 0) {
465 cERROR(1,("Unknown RFC 1002 frame"));
466 cifs_dump_mem(" Received Data: ", temp, length);
467 cifs_reconnect(server);
468 csocket = server->ssocket;
472 /* else we have an SMB response */
473 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
474 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
475 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
476 length, pdu_length+4));
477 cifs_reconnect(server);
478 csocket = server->ssocket;
479 wake_up(&server->response_q);
486 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
488 memcpy(bigbuf, smallbuf, 4);
492 iov.iov_base = 4 + (char *)smb_buffer;
493 iov.iov_len = pdu_length;
494 for (total_read = 0; total_read < pdu_length;
495 total_read += length) {
496 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
497 pdu_length - total_read, 0);
498 if((server->tcpStatus == CifsExiting) ||
499 (length == -EINTR)) {
503 } else if (server->tcpStatus == CifsNeedReconnect) {
504 cifs_reconnect(server);
505 csocket = server->ssocket;
506 /* Reconnect wakes up rspns q */
507 /* Now we will reread sock */
510 } else if ((length == -ERESTARTSYS) ||
511 (length == -EAGAIN)) {
512 msleep(1); /* minimum sleep to prevent looping,
513 allowing socket to clear and app
514 threads to set tcpStatus
515 CifsNeedReconnect if server hung*/
517 } else if (length <= 0) {
518 cERROR(1,("Received no data, expecting %d",
519 pdu_length - total_read));
520 cifs_reconnect(server);
521 csocket = server->ssocket;
528 else if(reconnect == 1)
531 length += 4; /* account for rfc1002 hdr */
534 dump_smb(smb_buffer, length);
535 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
536 cERROR(1, ("Bad SMB Received "));
542 spin_lock(&GlobalMid_Lock);
543 list_for_each(tmp, &server->pending_mid_q) {
544 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
546 if ((mid_entry->mid == smb_buffer->Mid) &&
547 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
548 (mid_entry->command == smb_buffer->Command)) {
549 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
550 /* We have a multipart transact2 resp */
552 if(mid_entry->resp_buf) {
553 /* merge response - fix up 1st*/
554 if(coalesce_t2(smb_buffer,
555 mid_entry->resp_buf)) {
558 /* all parts received */
563 cERROR(1,("1st trans2 resp needs bigbuf"));
564 /* BB maybe we can fix this up, switch
565 to already allocated large buffer? */
567 /* Have first buffer */
568 mid_entry->resp_buf =
570 mid_entry->largeBuf = 1;
576 mid_entry->resp_buf = smb_buffer;
578 mid_entry->largeBuf = 1;
580 mid_entry->largeBuf = 0;
582 task_to_wake = mid_entry->tsk;
583 mid_entry->midState = MID_RESPONSE_RECEIVED;
587 spin_unlock(&GlobalMid_Lock);
589 /* Was previous buf put in mpx struct for multi-rsp? */
591 /* smb buffer will be freed by user thread */
597 wake_up_process(task_to_wake);
598 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
599 && (isMultiRsp == FALSE)) {
600 cERROR(1, ("No task to wake, unknown frame rcvd!"));
601 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
603 } /* end while !EXITING */
605 spin_lock(&GlobalMid_Lock);
606 server->tcpStatus = CifsExiting;
608 /* check if we have blocked requests that need to free */
609 /* Note that cifs_max_pending is normally 50, but
610 can be set at module install time to as little as two */
611 if(atomic_read(&server->inFlight) >= cifs_max_pending)
612 atomic_set(&server->inFlight, cifs_max_pending - 1);
613 /* We do not want to set the max_pending too low or we
614 could end up with the counter going negative */
615 spin_unlock(&GlobalMid_Lock);
616 /* Although there should not be any requests blocked on
617 this queue it can not hurt to be paranoid and try to wake up requests
618 that may haven been blocked when more than 50 at time were on the wire
619 to the same server - they now will see the session is in exit state
620 and get out of SendReceive. */
621 wake_up_all(&server->request_q);
622 /* give those requests time to exit */
625 if(server->ssocket) {
626 sock_release(csocket);
627 server->ssocket = NULL;
629 /* buffer usuallly freed in free_mid - need to free it here on exit */
631 cifs_buf_release(bigbuf);
632 if (smallbuf != NULL)
633 cifs_small_buf_release(smallbuf);
635 read_lock(&GlobalSMBSeslock);
636 if (list_empty(&server->pending_mid_q)) {
637 /* loop through server session structures attached to this and
639 list_for_each(tmp, &GlobalSMBSessionList) {
641 list_entry(tmp, struct cifsSesInfo,
643 if (ses->server == server) {
644 ses->status = CifsExiting;
648 read_unlock(&GlobalSMBSeslock);
650 /* although we can not zero the server struct pointer yet,
651 since there are active requests which may depnd on them,
652 mark the corresponding SMB sessions as exiting too */
653 list_for_each(tmp, &GlobalSMBSessionList) {
654 ses = list_entry(tmp, struct cifsSesInfo,
656 if (ses->server == server) {
657 ses->status = CifsExiting;
661 spin_lock(&GlobalMid_Lock);
662 list_for_each(tmp, &server->pending_mid_q) {
663 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
664 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
666 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
667 task_to_wake = mid_entry->tsk;
669 wake_up_process(task_to_wake);
673 spin_unlock(&GlobalMid_Lock);
674 read_unlock(&GlobalSMBSeslock);
675 /* 1/8th of sec is more than enough time for them to exit */
679 if (list_empty(&server->pending_mid_q)) {
680 /* mpx threads have not exited yet give them
681 at least the smb send timeout time for long ops */
682 /* due to delays on oplock break requests, we need
683 to wait at least 45 seconds before giving up
684 on a request getting a response and going ahead
686 cFYI(1, ("Wait for exit from demultiplex thread"));
688 /* if threads still have not exited they are probably never
689 coming home not much else we can do but free the memory */
692 write_lock(&GlobalSMBSeslock);
693 atomic_dec(&tcpSesAllocCount);
694 length = tcpSesAllocCount.counter;
696 /* last chance to mark ses pointers invalid
697 if there are any pointing to this (e.g
698 if a crazy root user tried to kill cifsd
699 kernel thread explicitly this might happen) */
700 list_for_each(tmp, &GlobalSMBSessionList) {
701 ses = list_entry(tmp, struct cifsSesInfo,
703 if (ses->server == server) {
707 write_unlock(&GlobalSMBSeslock);
711 mempool_resize(cifs_req_poolp,
712 length + cifs_min_rcv,
721 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
725 unsigned int temp_len, i, j;
731 memset(vol->source_rfc1001_name,0x20,15);
732 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
733 /* does not have to be a perfect mapping since the field is
734 informational, only used for servers that do not support
735 port 445 and it can be overridden at mount time */
736 vol->source_rfc1001_name[i] =
737 toupper(system_utsname.nodename[i]);
739 vol->source_rfc1001_name[15] = 0;
741 vol->linux_uid = current->uid; /* current->euid instead? */
742 vol->linux_gid = current->gid;
743 vol->dir_mode = S_IRWXUGO;
744 /* 2767 perms indicate mandatory locking support */
745 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
747 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
750 /* default is always to request posix paths. */
751 vol->posix_paths = 1;
756 if(strncmp(options,"sep=",4) == 0) {
757 if(options[4] != 0) {
758 separator[0] = options[4];
761 cFYI(1,("Null separator not allowed"));
765 while ((data = strsep(&options, separator)) != NULL) {
768 if ((value = strchr(data, '=')) != NULL)
771 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
773 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
775 } else if (strnicmp(data, "user", 4) == 0) {
776 if (!value || !*value) {
778 "CIFS: invalid or missing username\n");
779 return 1; /* needs_arg; */
781 if (strnlen(value, 200) < 200) {
782 vol->username = value;
784 printk(KERN_WARNING "CIFS: username too long\n");
787 } else if (strnicmp(data, "pass", 4) == 0) {
789 vol->password = NULL;
791 } else if(value[0] == 0) {
792 /* check if string begins with double comma
793 since that would mean the password really
794 does start with a comma, and would not
795 indicate an empty string */
796 if(value[1] != separator[0]) {
797 vol->password = NULL;
801 temp_len = strlen(value);
802 /* removed password length check, NTLM passwords
803 can be arbitrarily long */
805 /* if comma in password, the string will be
806 prematurely null terminated. Commas in password are
807 specified across the cifs mount interface by a double
808 comma ie ,, and a comma used as in other cases ie ','
809 as a parameter delimiter/separator is single and due
810 to the strsep above is temporarily zeroed. */
812 /* NB: password legally can have multiple commas and
813 the only illegal character in a password is null */
815 if ((value[temp_len] == 0) &&
816 (value[temp_len+1] == separator[0])) {
818 value[temp_len] = separator[0];
819 temp_len+=2; /* move after the second comma */
820 while(value[temp_len] != 0) {
821 if (value[temp_len] == separator[0]) {
822 if (value[temp_len+1] ==
824 /* skip second comma */
827 /* single comma indicating start
834 if(value[temp_len] == 0) {
838 /* point option to start of next parm */
839 options = value + temp_len + 1;
841 /* go from value to value + temp_len condensing
842 double commas to singles. Note that this ends up
843 allocating a few bytes too many, which is ok */
844 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
845 if(vol->password == NULL) {
846 printk("CIFS: no memory for pass\n");
849 for(i=0,j=0;i<temp_len;i++,j++) {
850 vol->password[j] = value[i];
851 if(value[i] == separator[0]
852 && value[i+1] == separator[0]) {
853 /* skip second comma */
857 vol->password[j] = 0;
859 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
860 if(vol->password == NULL) {
861 printk("CIFS: no memory for pass\n");
864 strcpy(vol->password, value);
866 } else if (strnicmp(data, "ip", 2) == 0) {
867 if (!value || !*value) {
869 } else if (strnlen(value, 35) < 35) {
872 printk(KERN_WARNING "CIFS: ip address too long\n");
875 } else if ((strnicmp(data, "unc", 3) == 0)
876 || (strnicmp(data, "target", 6) == 0)
877 || (strnicmp(data, "path", 4) == 0)) {
878 if (!value || !*value) {
880 "CIFS: invalid path to network resource\n");
881 return 1; /* needs_arg; */
883 if ((temp_len = strnlen(value, 300)) < 300) {
884 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
887 strcpy(vol->UNC,value);
888 if (strncmp(vol->UNC, "//", 2) == 0) {
891 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
893 "CIFS: UNC Path does not begin with // or \\\\ \n");
897 printk(KERN_WARNING "CIFS: UNC name too long\n");
900 } else if ((strnicmp(data, "domain", 3) == 0)
901 || (strnicmp(data, "workgroup", 5) == 0)) {
902 if (!value || !*value) {
903 printk(KERN_WARNING "CIFS: invalid domain name\n");
904 return 1; /* needs_arg; */
906 /* BB are there cases in which a comma can be valid in
907 a domain name and need special handling? */
908 if (strnlen(value, 65) < 65) {
909 vol->domainname = value;
910 cFYI(1, ("Domain name set"));
912 printk(KERN_WARNING "CIFS: domain name too long\n");
915 } else if (strnicmp(data, "iocharset", 9) == 0) {
916 if (!value || !*value) {
917 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
918 return 1; /* needs_arg; */
920 if (strnlen(value, 65) < 65) {
921 if(strnicmp(value,"default",7))
922 vol->iocharset = value;
923 /* if iocharset not set load_nls_default used by caller */
924 cFYI(1, ("iocharset set to %s",value));
926 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
929 } else if (strnicmp(data, "uid", 3) == 0) {
930 if (value && *value) {
932 simple_strtoul(value, &value, 0);
934 } else if (strnicmp(data, "gid", 3) == 0) {
935 if (value && *value) {
937 simple_strtoul(value, &value, 0);
939 } else if (strnicmp(data, "file_mode", 4) == 0) {
940 if (value && *value) {
942 simple_strtoul(value, &value, 0);
944 } else if (strnicmp(data, "dir_mode", 4) == 0) {
945 if (value && *value) {
947 simple_strtoul(value, &value, 0);
949 } else if (strnicmp(data, "dirmode", 4) == 0) {
950 if (value && *value) {
952 simple_strtoul(value, &value, 0);
954 } else if (strnicmp(data, "port", 4) == 0) {
955 if (value && *value) {
957 simple_strtoul(value, &value, 0);
959 } else if (strnicmp(data, "rsize", 5) == 0) {
960 if (value && *value) {
962 simple_strtoul(value, &value, 0);
964 } else if (strnicmp(data, "wsize", 5) == 0) {
965 if (value && *value) {
967 simple_strtoul(value, &value, 0);
969 } else if (strnicmp(data, "sockopt", 5) == 0) {
970 if (value && *value) {
972 simple_strtoul(value, &value, 0);
974 } else if (strnicmp(data, "netbiosname", 4) == 0) {
975 if (!value || !*value || (*value == ' ')) {
976 cFYI(1,("invalid (empty) netbiosname specified"));
978 memset(vol->source_rfc1001_name,0x20,15);
980 /* BB are there cases in which a comma can be
981 valid in this workstation netbios name (and need
982 special handling)? */
984 /* We do not uppercase netbiosname for user */
988 vol->source_rfc1001_name[i] = value[i];
990 /* The string has 16th byte zero still from
991 set at top of the function */
992 if((i==15) && (value[i] != 0))
993 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
995 } else if (strnicmp(data, "credentials", 4) == 0) {
997 } else if (strnicmp(data, "version", 3) == 0) {
999 } else if (strnicmp(data, "guest",5) == 0) {
1001 } else if (strnicmp(data, "rw", 2) == 0) {
1003 } else if ((strnicmp(data, "suid", 4) == 0) ||
1004 (strnicmp(data, "nosuid", 6) == 0) ||
1005 (strnicmp(data, "exec", 4) == 0) ||
1006 (strnicmp(data, "noexec", 6) == 0) ||
1007 (strnicmp(data, "nodev", 5) == 0) ||
1008 (strnicmp(data, "noauto", 6) == 0) ||
1009 (strnicmp(data, "dev", 3) == 0)) {
1010 /* The mount tool or mount.cifs helper (if present)
1011 uses these opts to set flags, and the flags are read
1012 by the kernel vfs layer before we get here (ie
1013 before read super) so there is no point trying to
1014 parse these options again and set anything and it
1015 is ok to just ignore them */
1017 } else if (strnicmp(data, "ro", 2) == 0) {
1019 } else if (strnicmp(data, "hard", 4) == 0) {
1021 } else if (strnicmp(data, "soft", 4) == 0) {
1023 } else if (strnicmp(data, "perm", 4) == 0) {
1025 } else if (strnicmp(data, "noperm", 6) == 0) {
1027 } else if (strnicmp(data, "mapchars", 8) == 0) {
1029 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1031 } else if (strnicmp(data, "sfu", 3) == 0) {
1033 } else if (strnicmp(data, "nosfu", 5) == 0) {
1035 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1036 vol->posix_paths = 1;
1037 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1038 vol->posix_paths = 0;
1039 } else if (strnicmp(data, "setuids", 7) == 0) {
1041 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1043 } else if (strnicmp(data, "nohard", 6) == 0) {
1045 } else if (strnicmp(data, "nosoft", 6) == 0) {
1047 } else if (strnicmp(data, "nointr", 6) == 0) {
1049 } else if (strnicmp(data, "intr", 4) == 0) {
1051 } else if (strnicmp(data, "serverino",7) == 0) {
1052 vol->server_ino = 1;
1053 } else if (strnicmp(data, "noserverino",9) == 0) {
1054 vol->server_ino = 0;
1055 } else if (strnicmp(data, "acl",3) == 0) {
1056 vol->no_psx_acl = 0;
1057 } else if (strnicmp(data, "noacl",5) == 0) {
1058 vol->no_psx_acl = 1;
1059 } else if (strnicmp(data, "direct",6) == 0) {
1061 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1063 } else if (strnicmp(data, "in6_addr",8) == 0) {
1064 if (!value || !*value) {
1065 vol->in6_addr = NULL;
1066 } else if (strnlen(value, 49) == 48) {
1067 vol->in6_addr = value;
1069 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1072 } else if (strnicmp(data, "noac", 4) == 0) {
1073 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1075 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1077 if (vol->UNC == NULL) {
1078 if(devname == NULL) {
1079 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1082 if ((temp_len = strnlen(devname, 300)) < 300) {
1083 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1084 if(vol->UNC == NULL)
1086 strcpy(vol->UNC,devname);
1087 if (strncmp(vol->UNC, "//", 2) == 0) {
1090 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1091 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1095 printk(KERN_WARNING "CIFS: UNC name too long\n");
1099 if(vol->UNCip == NULL)
1100 vol->UNCip = &vol->UNC[2];
1105 static struct cifsSesInfo *
1106 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1107 struct in6_addr *target_ip6_addr,
1108 char *userName, struct TCP_Server_Info **psrvTcp)
1110 struct list_head *tmp;
1111 struct cifsSesInfo *ses;
1113 read_lock(&GlobalSMBSeslock);
1115 list_for_each(tmp, &GlobalSMBSessionList) {
1116 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1118 if((target_ip_addr &&
1119 (ses->server->addr.sockAddr.sin_addr.s_addr
1120 == target_ip_addr->s_addr)) || (target_ip6_addr
1121 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1122 target_ip6_addr,sizeof(*target_ip6_addr)))){
1123 /* BB lock server and tcp session and increment use count here?? */
1124 *psrvTcp = ses->server; /* found a match on the TCP session */
1125 /* BB check if reconnection needed */
1127 (ses->userName, userName,
1128 MAX_USERNAME_SIZE) == 0){
1129 read_unlock(&GlobalSMBSeslock);
1130 return ses; /* found exact match on both tcp and SMB sessions */
1134 /* else tcp and smb sessions need reconnection */
1136 read_unlock(&GlobalSMBSeslock);
1140 static struct cifsTconInfo *
1141 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1143 struct list_head *tmp;
1144 struct cifsTconInfo *tcon;
1146 read_lock(&GlobalSMBSeslock);
1147 list_for_each(tmp, &GlobalTreeConnectionList) {
1148 cFYI(1, ("Next tcon - "));
1149 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1151 if (tcon->ses->server) {
1153 (" old ip addr: %x == new ip %x ?",
1154 tcon->ses->server->addr.sockAddr.sin_addr.
1155 s_addr, new_target_ip_addr));
1156 if (tcon->ses->server->addr.sockAddr.sin_addr.
1157 s_addr == new_target_ip_addr) {
1158 /* BB lock tcon and server and tcp session and increment use count here? */
1159 /* found a match on the TCP session */
1160 /* BB check if reconnection needed */
1161 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1162 tcon->treeName, uncName));
1164 (tcon->treeName, uncName,
1165 MAX_TREE_SIZE) == 0) {
1167 ("Matched UNC, old user: %s == new: %s ?",
1168 tcon->treeName, uncName));
1170 (tcon->ses->userName,
1172 MAX_USERNAME_SIZE) == 0) {
1173 read_unlock(&GlobalSMBSeslock);
1174 return tcon;/* also matched user (smb session)*/
1181 read_unlock(&GlobalSMBSeslock);
1186 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1187 const char *old_path, const struct nls_table *nls_codepage,
1190 unsigned char *referrals = NULL;
1191 unsigned int num_referrals;
1194 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1195 &num_referrals, &referrals, remap);
1197 /* BB Add in code to: if valid refrl, if not ip address contact
1198 the helper that resolves tcp names, mount to it, try to
1199 tcon to it unmount it if fail */
1208 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1209 const char *old_path, const struct nls_table *nls_codepage,
1210 unsigned int *pnum_referrals,
1211 unsigned char ** preferrals, int remap)
1216 *pnum_referrals = 0;
1218 if (pSesInfo->ipc_tid == 0) {
1219 temp_unc = kmalloc(2 /* for slashes */ +
1220 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1221 + 1 + 4 /* slash IPC$ */ + 2,
1223 if (temp_unc == NULL)
1227 strcpy(temp_unc + 2, pSesInfo->serverName);
1228 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1229 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1231 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1235 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1236 pnum_referrals, nls_codepage, remap);
1241 /* See RFC1001 section 14 on representation of Netbios names */
1242 static void rfc1002mangle(char * target,char * source, unsigned int length)
1246 for(i=0,j=0;i<(length);i++) {
1247 /* mask a nibble at a time and encode */
1248 target[j] = 'A' + (0x0F & (source[i] >> 4));
1249 target[j+1] = 'A' + (0x0F & source[i]);
1257 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1258 char * netbios_name)
1262 __be16 orig_port = 0;
1264 if(*csocket == NULL) {
1265 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1267 cERROR(1, ("Error %d creating socket",rc));
1271 /* BB other socket options to set KEEPALIVE, NODELAY? */
1272 cFYI(1,("Socket created"));
1273 (*csocket)->sk->sk_allocation = GFP_NOFS;
1277 psin_server->sin_family = AF_INET;
1278 if(psin_server->sin_port) { /* user overrode default port */
1279 rc = (*csocket)->ops->connect(*csocket,
1280 (struct sockaddr *) psin_server,
1281 sizeof (struct sockaddr_in),0);
1287 /* save original port so we can retry user specified port
1288 later if fall back ports fail this time */
1289 orig_port = psin_server->sin_port;
1291 /* do not retry on the same port we just failed on */
1292 if(psin_server->sin_port != htons(CIFS_PORT)) {
1293 psin_server->sin_port = htons(CIFS_PORT);
1295 rc = (*csocket)->ops->connect(*csocket,
1296 (struct sockaddr *) psin_server,
1297 sizeof (struct sockaddr_in),0);
1303 psin_server->sin_port = htons(RFC1001_PORT);
1304 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1305 psin_server, sizeof (struct sockaddr_in),0);
1310 /* give up here - unless we want to retry on different
1311 protocol families some day */
1314 psin_server->sin_port = orig_port;
1315 cFYI(1,("Error %d connecting to server via ipv4",rc));
1316 sock_release(*csocket);
1320 /* Eventually check for other socket options to change from
1321 the default. sock_setsockopt not used because it expects
1322 user space buffer */
1323 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1325 /* send RFC1001 sessinit */
1327 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1328 /* some servers require RFC1001 sessinit before sending
1329 negprot - BB check reconnection in case where second
1330 sessinit is sent but no second negprot */
1331 struct rfc1002_session_packet * ses_init_buf;
1332 struct smb_hdr * smb_buf;
1333 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1335 ses_init_buf->trailer.session_req.called_len = 32;
1336 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1337 DEFAULT_CIFS_CALLED_NAME,16);
1338 ses_init_buf->trailer.session_req.calling_len = 32;
1339 /* calling name ends in null (byte 16) from old smb
1341 if(netbios_name && (netbios_name[0] !=0)) {
1342 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1345 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1346 "LINUX_CIFS_CLNT",16);
1348 ses_init_buf->trailer.session_req.scope1 = 0;
1349 ses_init_buf->trailer.session_req.scope2 = 0;
1350 smb_buf = (struct smb_hdr *)ses_init_buf;
1351 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1352 smb_buf->smb_buf_length = 0x81000044;
1353 rc = smb_send(*csocket, smb_buf, 0x44,
1354 (struct sockaddr *)psin_server);
1355 kfree(ses_init_buf);
1357 /* else the negprot may still work without this
1358 even though malloc failed */
1366 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1370 __be16 orig_port = 0;
1372 if(*csocket == NULL) {
1373 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1375 cERROR(1, ("Error %d creating ipv6 socket",rc));
1379 /* BB other socket options to set KEEPALIVE, NODELAY? */
1380 cFYI(1,("ipv6 Socket created"));
1381 (*csocket)->sk->sk_allocation = GFP_NOFS;
1385 psin_server->sin6_family = AF_INET6;
1387 if(psin_server->sin6_port) { /* user overrode default port */
1388 rc = (*csocket)->ops->connect(*csocket,
1389 (struct sockaddr *) psin_server,
1390 sizeof (struct sockaddr_in6),0);
1396 /* save original port so we can retry user specified port
1397 later if fall back ports fail this time */
1399 orig_port = psin_server->sin6_port;
1400 /* do not retry on the same port we just failed on */
1401 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1402 psin_server->sin6_port = htons(CIFS_PORT);
1404 rc = (*csocket)->ops->connect(*csocket,
1405 (struct sockaddr *) psin_server,
1406 sizeof (struct sockaddr_in6),0);
1412 psin_server->sin6_port = htons(RFC1001_PORT);
1413 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1414 psin_server, sizeof (struct sockaddr_in6),0);
1419 /* give up here - unless we want to retry on different
1420 protocol families some day */
1423 psin_server->sin6_port = orig_port;
1424 cFYI(1,("Error %d connecting to server via ipv6",rc));
1425 sock_release(*csocket);
1429 /* Eventually check for other socket options to change from
1430 the default. sock_setsockopt not used because it expects
1431 user space buffer */
1432 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1438 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1439 char *mount_data, const char *devname)
1443 int address_type = AF_INET;
1444 struct socket *csocket = NULL;
1445 struct sockaddr_in sin_server;
1446 struct sockaddr_in6 sin_server6;
1447 struct smb_vol volume_info;
1448 struct cifsSesInfo *pSesInfo = NULL;
1449 struct cifsSesInfo *existingCifsSes = NULL;
1450 struct cifsTconInfo *tcon = NULL;
1451 struct TCP_Server_Info *srvTcp = NULL;
1455 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1457 memset(&volume_info,0,sizeof(struct smb_vol));
1458 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1460 kfree(volume_info.UNC);
1461 if(volume_info.password)
1462 kfree(volume_info.password);
1467 if (volume_info.username) {
1468 /* BB fixme parse for domain name here */
1469 cFYI(1, ("Username: %s ", volume_info.username));
1472 cifserror("No username specified ");
1473 /* In userspace mount helper we can get user name from alternate
1474 locations such as env variables and files on disk */
1476 kfree(volume_info.UNC);
1477 if(volume_info.password)
1478 kfree(volume_info.password);
1483 if (volume_info.UNCip && volume_info.UNC) {
1484 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1487 /* not ipv4 address, try ipv6 */
1488 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1490 address_type = AF_INET6;
1492 address_type = AF_INET;
1496 /* we failed translating address */
1498 kfree(volume_info.UNC);
1499 if(volume_info.password)
1500 kfree(volume_info.password);
1505 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1508 } else if (volume_info.UNCip){
1509 /* BB using ip addr as server name connect to the DFS root below */
1510 cERROR(1,("Connecting to DFS root not implemented yet"));
1512 kfree(volume_info.UNC);
1513 if(volume_info.password)
1514 kfree(volume_info.password);
1517 } else /* which servers DFS root would we conect to */ {
1519 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1521 kfree(volume_info.UNC);
1522 if(volume_info.password)
1523 kfree(volume_info.password);
1528 /* this is needed for ASCII cp to Unicode converts */
1529 if(volume_info.iocharset == NULL) {
1530 cifs_sb->local_nls = load_nls_default();
1531 /* load_nls_default can not return null */
1533 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1534 if(cifs_sb->local_nls == NULL) {
1535 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1537 kfree(volume_info.UNC);
1538 if(volume_info.password)
1539 kfree(volume_info.password);
1545 if(address_type == AF_INET)
1546 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1547 NULL /* no ipv6 addr */,
1548 volume_info.username, &srvTcp);
1549 else if(address_type == AF_INET6)
1550 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1551 &sin_server6.sin6_addr,
1552 volume_info.username, &srvTcp);
1555 kfree(volume_info.UNC);
1556 if(volume_info.password)
1557 kfree(volume_info.password);
1564 cFYI(1, ("Existing tcp session with server found "));
1565 } else { /* create socket */
1566 if(volume_info.port)
1567 sin_server.sin_port = htons(volume_info.port);
1569 sin_server.sin_port = 0;
1570 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1573 ("Error connecting to IPv4 socket. Aborting operation"));
1575 sock_release(csocket);
1577 kfree(volume_info.UNC);
1578 if(volume_info.password)
1579 kfree(volume_info.password);
1584 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1585 if (srvTcp == NULL) {
1587 sock_release(csocket);
1589 kfree(volume_info.UNC);
1590 if(volume_info.password)
1591 kfree(volume_info.password);
1595 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1596 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1597 atomic_set(&srvTcp->inFlight,0);
1598 /* BB Add code for ipv6 case too */
1599 srvTcp->ssocket = csocket;
1600 srvTcp->protocolType = IPV4;
1601 init_waitqueue_head(&srvTcp->response_q);
1602 init_waitqueue_head(&srvTcp->request_q);
1603 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1604 /* at this point we are the only ones with the pointer
1605 to the struct since the kernel thread not created yet
1606 so no need to spinlock this init of tcpStatus */
1607 srvTcp->tcpStatus = CifsNew;
1608 init_MUTEX(&srvTcp->tcpSem);
1609 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1610 CLONE_FS | CLONE_FILES | CLONE_VM);
1613 sock_release(csocket);
1615 kfree(volume_info.UNC);
1616 if(volume_info.password)
1617 kfree(volume_info.password);
1622 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1623 srvTcp->sequence_number = 0;
1627 if (existingCifsSes) {
1628 pSesInfo = existingCifsSes;
1629 cFYI(1, ("Existing smb sess found "));
1630 if(volume_info.password)
1631 kfree(volume_info.password);
1632 /* volume_info.UNC freed at end of function */
1634 cFYI(1, ("Existing smb sess not found "));
1635 pSesInfo = sesInfoAlloc();
1636 if (pSesInfo == NULL)
1639 pSesInfo->server = srvTcp;
1640 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1641 NIPQUAD(sin_server.sin_addr.s_addr));
1645 /* volume_info.password freed at unmount */
1646 if (volume_info.password)
1647 pSesInfo->password = volume_info.password;
1648 if (volume_info.username)
1649 strncpy(pSesInfo->userName,
1650 volume_info.username,MAX_USERNAME_SIZE);
1651 if (volume_info.domainname)
1652 strncpy(pSesInfo->domainName,
1653 volume_info.domainname,MAX_USERNAME_SIZE);
1654 pSesInfo->linux_uid = volume_info.linux_uid;
1655 down(&pSesInfo->sesSem);
1656 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1657 up(&pSesInfo->sesSem);
1659 atomic_inc(&srvTcp->socketUseCount);
1661 if(volume_info.password)
1662 kfree(volume_info.password);
1665 /* search for existing tcon to this server share */
1667 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1668 cifs_sb->rsize = volume_info.rsize;
1670 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1671 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1672 cifs_sb->wsize = volume_info.wsize;
1674 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1675 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1676 cifs_sb->rsize = PAGE_CACHE_SIZE;
1677 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1679 cifs_sb->mnt_uid = volume_info.linux_uid;
1680 cifs_sb->mnt_gid = volume_info.linux_gid;
1681 cifs_sb->mnt_file_mode = volume_info.file_mode;
1682 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1683 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1685 if(volume_info.noperm)
1686 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1687 if(volume_info.setuids)
1688 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1689 if(volume_info.server_ino)
1690 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1691 if(volume_info.remap)
1692 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1693 if(volume_info.no_xattr)
1694 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1695 if(volume_info.sfu_emul)
1696 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1698 if(volume_info.direct_io) {
1699 cERROR(1,("mounting share using direct i/o"));
1700 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1704 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1705 volume_info.username);
1707 cFYI(1, ("Found match on UNC path "));
1708 /* we can have only one retry value for a connection
1709 to a share so for resources mounted more than once
1710 to the same server share the last value passed in
1711 for the retry flag is used */
1712 tcon->retry = volume_info.retry;
1714 tcon = tconInfoAlloc();
1718 /* check for null share name ie connect to dfs root */
1720 /* BB check if this works for exactly length three strings */
1721 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1722 && (strchr(volume_info.UNC + 3, '/') ==
1724 rc = connect_to_dfs_path(xid, pSesInfo,
1725 "", cifs_sb->local_nls,
1726 cifs_sb->mnt_cifs_flags &
1727 CIFS_MOUNT_MAP_SPECIAL_CHR);
1729 kfree(volume_info.UNC);
1733 rc = CIFSTCon(xid, pSesInfo,
1735 tcon, cifs_sb->local_nls);
1736 cFYI(1, ("CIFS Tcon rc = %d", rc));
1739 atomic_inc(&pSesInfo->inUse);
1740 tcon->retry = volume_info.retry;
1746 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1747 sb->s_maxbytes = (u64) 1 << 63;
1749 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1752 sb->s_time_gran = 100;
1754 /* on error free sesinfo and tcon struct if needed */
1756 /* if session setup failed, use count is zero but
1757 we still need to free cifsd thread */
1758 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1759 spin_lock(&GlobalMid_Lock);
1760 srvTcp->tcpStatus = CifsExiting;
1761 spin_unlock(&GlobalMid_Lock);
1763 send_sig(SIGKILL,srvTcp->tsk,1);
1765 /* If find_unc succeeded then rc == 0 so we can not end */
1766 if (tcon) /* up accidently freeing someone elses tcon struct */
1768 if (existingCifsSes == NULL) {
1770 if ((pSesInfo->server) &&
1771 (pSesInfo->status == CifsGood)) {
1773 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1774 /* if the socketUseCount is now zero */
1775 if((temp_rc == -ESHUTDOWN) &&
1776 (pSesInfo->server->tsk))
1777 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1779 cFYI(1, ("No session or bad tcon"));
1780 sesInfoFree(pSesInfo);
1781 /* pSesInfo = NULL; */
1785 atomic_inc(&tcon->useCount);
1786 cifs_sb->tcon = tcon;
1787 tcon->ses = pSesInfo;
1789 /* do not care if following two calls succeed - informational only */
1790 CIFSSMBQFSDeviceInfo(xid, tcon);
1791 CIFSSMBQFSAttributeInfo(xid, tcon);
1792 if (tcon->ses->capabilities & CAP_UNIX) {
1793 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1794 if(!volume_info.no_psx_acl) {
1795 if(CIFS_UNIX_POSIX_ACL_CAP &
1796 le64_to_cpu(tcon->fsUnixInfo.Capability))
1797 cFYI(1,("server negotiated posix acl support"));
1798 sb->s_flags |= MS_POSIXACL;
1801 /* Try and negotiate POSIX pathnames if we can. */
1802 if (volume_info.posix_paths && (CIFS_UNIX_POSIX_PATHNAMES_CAP &
1803 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1804 if (!CIFSSMBSetFSUnixInfo(xid, tcon, CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
1805 cFYI(1,("negotiated posix pathnames support"));
1806 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS;
1808 cFYI(1,("posix pathnames support requested but not supported"));
1815 /* volume_info.password is freed above when existing session found
1816 (in which case it is not needed anymore) but when new sesion is created
1817 the password ptr is put in the new session structure (in which case the
1818 password will be freed at unmount time) */
1820 kfree(volume_info.UNC);
1826 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1827 char session_key[CIFS_SESSION_KEY_SIZE],
1828 const struct nls_table *nls_codepage)
1830 struct smb_hdr *smb_buffer;
1831 struct smb_hdr *smb_buffer_response;
1832 SESSION_SETUP_ANDX *pSMB;
1833 SESSION_SETUP_ANDX *pSMBr;
1838 int remaining_words = 0;
1839 int bytes_returned = 0;
1844 cFYI(1, ("In sesssetup "));
1847 user = ses->userName;
1848 domain = ses->domainName;
1849 smb_buffer = cifs_buf_get();
1850 if (smb_buffer == NULL) {
1853 smb_buffer_response = smb_buffer;
1854 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1856 /* send SMBsessionSetup here */
1857 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1858 NULL /* no tCon exists yet */ , 13 /* wct */ );
1860 smb_buffer->Mid = GetNextMid(ses->server);
1861 pSMB->req_no_secext.AndXCommand = 0xFF;
1862 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1863 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1865 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1866 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1868 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1869 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1870 if (ses->capabilities & CAP_UNICODE) {
1871 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1872 capabilities |= CAP_UNICODE;
1874 if (ses->capabilities & CAP_STATUS32) {
1875 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1876 capabilities |= CAP_STATUS32;
1878 if (ses->capabilities & CAP_DFS) {
1879 smb_buffer->Flags2 |= SMBFLG2_DFS;
1880 capabilities |= CAP_DFS;
1882 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1884 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1885 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1887 pSMB->req_no_secext.CaseSensitivePasswordLength =
1888 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1889 bcc_ptr = pByteArea(smb_buffer);
1890 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1891 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1892 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1893 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1895 if (ses->capabilities & CAP_UNICODE) {
1896 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1901 bytes_returned = 0; /* skill null user */
1904 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1906 /* convert number of 16 bit words to bytes */
1907 bcc_ptr += 2 * bytes_returned;
1908 bcc_ptr += 2; /* trailing null */
1911 cifs_strtoUCS((wchar_t *) bcc_ptr,
1912 "CIFS_LINUX_DOM", 32, nls_codepage);
1915 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1917 bcc_ptr += 2 * bytes_returned;
1920 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1922 bcc_ptr += 2 * bytes_returned;
1924 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1926 bcc_ptr += 2 * bytes_returned;
1929 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1931 bcc_ptr += 2 * bytes_returned;
1935 strncpy(bcc_ptr, user, 200);
1936 bcc_ptr += strnlen(user, 200);
1940 if (domain == NULL) {
1941 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1942 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1944 strncpy(bcc_ptr, domain, 64);
1945 bcc_ptr += strnlen(domain, 64);
1949 strcpy(bcc_ptr, "Linux version ");
1950 bcc_ptr += strlen("Linux version ");
1951 strcpy(bcc_ptr, system_utsname.release);
1952 bcc_ptr += strlen(system_utsname.release) + 1;
1953 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1954 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1956 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1957 smb_buffer->smb_buf_length += count;
1958 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1960 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1961 &bytes_returned, 1);
1963 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1964 } else if ((smb_buffer_response->WordCount == 3)
1965 || (smb_buffer_response->WordCount == 4)) {
1966 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1967 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1968 if (action & GUEST_LOGIN)
1969 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1970 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1971 cFYI(1, ("UID = %d ", ses->Suid));
1972 /* response can have either 3 or 4 word count - Samba sends 3 */
1973 bcc_ptr = pByteArea(smb_buffer_response);
1974 if ((pSMBr->resp.hdr.WordCount == 3)
1975 || ((pSMBr->resp.hdr.WordCount == 4)
1976 && (blob_len < pSMBr->resp.ByteCount))) {
1977 if (pSMBr->resp.hdr.WordCount == 4)
1978 bcc_ptr += blob_len;
1980 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1981 if ((long) (bcc_ptr) % 2) {
1983 (BCC(smb_buffer_response) - 1) /2;
1984 bcc_ptr++; /* Unicode strings must be word aligned */
1987 BCC(smb_buffer_response) / 2;
1990 UniStrnlen((wchar_t *) bcc_ptr,
1991 remaining_words - 1);
1992 /* We look for obvious messed up bcc or strings in response so we do not go off
1993 the end since (at least) WIN2K and Windows XP have a major bug in not null
1994 terminating last Unicode string in response */
1995 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1996 if(ses->serverOS == NULL)
1997 goto sesssetup_nomem;
1998 cifs_strfromUCS_le(ses->serverOS,
1999 (wchar_t *)bcc_ptr, len,nls_codepage);
2000 bcc_ptr += 2 * (len + 1);
2001 remaining_words -= len + 1;
2002 ses->serverOS[2 * len] = 0;
2003 ses->serverOS[1 + (2 * len)] = 0;
2004 if (remaining_words > 0) {
2005 len = UniStrnlen((wchar_t *)bcc_ptr,
2007 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
2008 if(ses->serverNOS == NULL)
2009 goto sesssetup_nomem;
2010 cifs_strfromUCS_le(ses->serverNOS,
2011 (wchar_t *)bcc_ptr,len,nls_codepage);
2012 bcc_ptr += 2 * (len + 1);
2013 ses->serverNOS[2 * len] = 0;
2014 ses->serverNOS[1 + (2 * len)] = 0;
2015 if(strncmp(ses->serverNOS,
2016 "NT LAN Manager 4",16) == 0) {
2017 cFYI(1,("NT4 server"));
2018 ses->flags |= CIFS_SES_NT4;
2020 remaining_words -= len + 1;
2021 if (remaining_words > 0) {
2022 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2023 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2025 kcalloc(1, 2*(len+1),GFP_KERNEL);
2026 if(ses->serverDomain == NULL)
2027 goto sesssetup_nomem;
2028 cifs_strfromUCS_le(ses->serverDomain,
2029 (wchar_t *)bcc_ptr,len,nls_codepage);
2030 bcc_ptr += 2 * (len + 1);
2031 ses->serverDomain[2*len] = 0;
2032 ses->serverDomain[1+(2*len)] = 0;
2033 } /* else no more room so create dummy domain string */
2036 kcalloc(1, 2, GFP_KERNEL);
2037 } else { /* no room so create dummy domain and NOS string */
2038 /* if these kcallocs fail not much we
2039 can do, but better to not fail the
2042 kcalloc(1, 2, GFP_KERNEL);
2044 kcalloc(1, 2, GFP_KERNEL);
2046 } else { /* ASCII */
2047 len = strnlen(bcc_ptr, 1024);
2048 if (((long) bcc_ptr + len) - (long)
2049 pByteArea(smb_buffer_response)
2050 <= BCC(smb_buffer_response)) {
2051 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2052 if(ses->serverOS == NULL)
2053 goto sesssetup_nomem;
2054 strncpy(ses->serverOS,bcc_ptr, len);
2057 bcc_ptr[0] = 0; /* null terminate the string */
2060 len = strnlen(bcc_ptr, 1024);
2061 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2062 if(ses->serverNOS == NULL)
2063 goto sesssetup_nomem;
2064 strncpy(ses->serverNOS, bcc_ptr, len);
2069 len = strnlen(bcc_ptr, 1024);
2070 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2071 if(ses->serverDomain == NULL)
2072 goto sesssetup_nomem;
2073 strncpy(ses->serverDomain, bcc_ptr, len);
2079 ("Variable field of length %d extends beyond end of smb ",
2084 (" Security Blob Length extends beyond end of SMB"));
2088 (" Invalid Word count %d: ",
2089 smb_buffer_response->WordCount));
2092 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2093 since that could make reconnection harder, and
2094 reconnection might be needed to free memory */
2096 cifs_buf_release(smb_buffer);
2102 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2103 char *SecurityBlob,int SecurityBlobLength,
2104 const struct nls_table *nls_codepage)
2106 struct smb_hdr *smb_buffer;
2107 struct smb_hdr *smb_buffer_response;
2108 SESSION_SETUP_ANDX *pSMB;
2109 SESSION_SETUP_ANDX *pSMBr;
2114 int remaining_words = 0;
2115 int bytes_returned = 0;
2120 cFYI(1, ("In spnego sesssetup "));
2123 user = ses->userName;
2124 domain = ses->domainName;
2126 smb_buffer = cifs_buf_get();
2127 if (smb_buffer == NULL) {
2130 smb_buffer_response = smb_buffer;
2131 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2133 /* send SMBsessionSetup here */
2134 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2135 NULL /* no tCon exists yet */ , 12 /* wct */ );
2137 smb_buffer->Mid = GetNextMid(ses->server);
2138 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2139 pSMB->req.AndXCommand = 0xFF;
2140 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2141 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2143 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2144 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2146 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2147 CAP_EXTENDED_SECURITY;
2148 if (ses->capabilities & CAP_UNICODE) {
2149 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2150 capabilities |= CAP_UNICODE;
2152 if (ses->capabilities & CAP_STATUS32) {
2153 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2154 capabilities |= CAP_STATUS32;
2156 if (ses->capabilities & CAP_DFS) {
2157 smb_buffer->Flags2 |= SMBFLG2_DFS;
2158 capabilities |= CAP_DFS;
2160 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2162 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2163 bcc_ptr = pByteArea(smb_buffer);
2164 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2165 bcc_ptr += SecurityBlobLength;
2167 if (ses->capabilities & CAP_UNICODE) {
2168 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2173 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
2174 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2175 bcc_ptr += 2; /* trailing null */
2178 cifs_strtoUCS((wchar_t *) bcc_ptr,
2179 "CIFS_LINUX_DOM", 32, nls_codepage);
2182 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2184 bcc_ptr += 2 * bytes_returned;
2187 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2189 bcc_ptr += 2 * bytes_returned;
2191 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2193 bcc_ptr += 2 * bytes_returned;
2196 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2198 bcc_ptr += 2 * bytes_returned;
2201 strncpy(bcc_ptr, user, 200);
2202 bcc_ptr += strnlen(user, 200);
2205 if (domain == NULL) {
2206 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2207 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2209 strncpy(bcc_ptr, domain, 64);
2210 bcc_ptr += strnlen(domain, 64);
2214 strcpy(bcc_ptr, "Linux version ");
2215 bcc_ptr += strlen("Linux version ");
2216 strcpy(bcc_ptr, system_utsname.release);
2217 bcc_ptr += strlen(system_utsname.release) + 1;
2218 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2219 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2221 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2222 smb_buffer->smb_buf_length += count;
2223 pSMB->req.ByteCount = cpu_to_le16(count);
2225 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2226 &bytes_returned, 1);
2228 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2229 } else if ((smb_buffer_response->WordCount == 3)
2230 || (smb_buffer_response->WordCount == 4)) {
2231 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2233 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2234 if (action & GUEST_LOGIN)
2235 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2237 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2238 cFYI(1, ("UID = %d ", ses->Suid));
2239 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2241 /* BB Fix below to make endian neutral !! */
2243 if ((pSMBr->resp.hdr.WordCount == 3)
2244 || ((pSMBr->resp.hdr.WordCount == 4)
2246 pSMBr->resp.ByteCount))) {
2247 if (pSMBr->resp.hdr.WordCount == 4) {
2251 ("Security Blob Length %d ",
2255 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2256 if ((long) (bcc_ptr) % 2) {
2258 (BCC(smb_buffer_response)
2260 bcc_ptr++; /* Unicode strings must be word aligned */
2264 (smb_buffer_response) / 2;
2267 UniStrnlen((wchar_t *) bcc_ptr,
2268 remaining_words - 1);
2269 /* We look for obvious messed up bcc or strings in response so we do not go off
2270 the end since (at least) WIN2K and Windows XP have a major bug in not null
2271 terminating last Unicode string in response */
2273 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2274 cifs_strfromUCS_le(ses->serverOS,
2278 bcc_ptr += 2 * (len + 1);
2279 remaining_words -= len + 1;
2280 ses->serverOS[2 * len] = 0;
2281 ses->serverOS[1 + (2 * len)] = 0;
2282 if (remaining_words > 0) {
2283 len = UniStrnlen((wchar_t *)bcc_ptr,
2287 kcalloc(1, 2 * (len + 1),
2289 cifs_strfromUCS_le(ses->serverNOS,
2293 bcc_ptr += 2 * (len + 1);
2294 ses->serverNOS[2 * len] = 0;
2295 ses->serverNOS[1 + (2 * len)] = 0;
2296 remaining_words -= len + 1;
2297 if (remaining_words > 0) {
2298 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2299 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2300 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2301 cifs_strfromUCS_le(ses->serverDomain,
2305 bcc_ptr += 2*(len+1);
2306 ses->serverDomain[2*len] = 0;
2307 ses->serverDomain[1+(2*len)] = 0;
2308 } /* else no more room so create dummy domain string */
2311 kcalloc(1, 2,GFP_KERNEL);
2312 } else { /* no room so create dummy domain and NOS string */
2313 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2314 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2316 } else { /* ASCII */
2318 len = strnlen(bcc_ptr, 1024);
2319 if (((long) bcc_ptr + len) - (long)
2320 pByteArea(smb_buffer_response)
2321 <= BCC(smb_buffer_response)) {
2322 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2323 strncpy(ses->serverOS, bcc_ptr, len);
2326 bcc_ptr[0] = 0; /* null terminate the string */
2329 len = strnlen(bcc_ptr, 1024);
2330 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2331 strncpy(ses->serverNOS, bcc_ptr, len);
2336 len = strnlen(bcc_ptr, 1024);
2337 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2338 strncpy(ses->serverDomain, bcc_ptr, len);
2344 ("Variable field of length %d extends beyond end of smb ",
2349 (" Security Blob Length extends beyond end of SMB"));
2352 cERROR(1, ("No session structure passed in."));
2356 (" Invalid Word count %d: ",
2357 smb_buffer_response->WordCount));
2362 cifs_buf_release(smb_buffer);
2368 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2369 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2370 const struct nls_table *nls_codepage)
2372 struct smb_hdr *smb_buffer;
2373 struct smb_hdr *smb_buffer_response;
2374 SESSION_SETUP_ANDX *pSMB;
2375 SESSION_SETUP_ANDX *pSMBr;
2379 int remaining_words = 0;
2380 int bytes_returned = 0;
2382 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2383 PNEGOTIATE_MESSAGE SecurityBlob;
2384 PCHALLENGE_MESSAGE SecurityBlob2;
2385 __u32 negotiate_flags, capabilities;
2388 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2391 domain = ses->domainName;
2392 *pNTLMv2_flag = FALSE;
2393 smb_buffer = cifs_buf_get();
2394 if (smb_buffer == NULL) {
2397 smb_buffer_response = smb_buffer;
2398 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2399 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2401 /* send SMBsessionSetup here */
2402 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2403 NULL /* no tCon exists yet */ , 12 /* wct */ );
2405 smb_buffer->Mid = GetNextMid(ses->server);
2406 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2407 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2409 pSMB->req.AndXCommand = 0xFF;
2410 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2411 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2413 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2414 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2416 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2417 CAP_EXTENDED_SECURITY;
2418 if (ses->capabilities & CAP_UNICODE) {
2419 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2420 capabilities |= CAP_UNICODE;
2422 if (ses->capabilities & CAP_STATUS32) {
2423 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2424 capabilities |= CAP_STATUS32;
2426 if (ses->capabilities & CAP_DFS) {
2427 smb_buffer->Flags2 |= SMBFLG2_DFS;
2428 capabilities |= CAP_DFS;
2430 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2432 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2433 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2434 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2435 SecurityBlob->MessageType = NtLmNegotiate;
2437 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2438 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2439 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2441 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2443 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2444 /* setup pointers to domain name and workstation name */
2445 bcc_ptr += SecurityBlobLength;
2447 SecurityBlob->WorkstationName.Buffer = 0;
2448 SecurityBlob->WorkstationName.Length = 0;
2449 SecurityBlob->WorkstationName.MaximumLength = 0;
2451 if (domain == NULL) {
2452 SecurityBlob->DomainName.Buffer = 0;
2453 SecurityBlob->DomainName.Length = 0;
2454 SecurityBlob->DomainName.MaximumLength = 0;
2457 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2458 strncpy(bcc_ptr, domain, 63);
2459 len = strnlen(domain, 64);
2460 SecurityBlob->DomainName.MaximumLength =
2462 SecurityBlob->DomainName.Buffer =
2463 cpu_to_le32((long) &SecurityBlob->
2465 (long) &SecurityBlob->Signature);
2467 SecurityBlobLength += len;
2468 SecurityBlob->DomainName.Length =
2471 if (ses->capabilities & CAP_UNICODE) {
2472 if ((long) bcc_ptr % 2) {
2478 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2480 bcc_ptr += 2 * bytes_returned;
2482 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2484 bcc_ptr += 2 * bytes_returned;
2485 bcc_ptr += 2; /* null terminate Linux version */
2487 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2489 bcc_ptr += 2 * bytes_returned;
2492 bcc_ptr += 2; /* null terminate network opsys string */
2495 bcc_ptr += 2; /* null domain */
2496 } else { /* ASCII */
2497 strcpy(bcc_ptr, "Linux version ");
2498 bcc_ptr += strlen("Linux version ");
2499 strcpy(bcc_ptr, system_utsname.release);
2500 bcc_ptr += strlen(system_utsname.release) + 1;
2501 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2502 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2503 bcc_ptr++; /* empty domain field */
2506 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2507 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2508 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2509 smb_buffer->smb_buf_length += count;
2510 pSMB->req.ByteCount = cpu_to_le16(count);
2512 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2513 &bytes_returned, 1);
2515 if (smb_buffer_response->Status.CifsError ==
2516 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2520 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2521 } else if ((smb_buffer_response->WordCount == 3)
2522 || (smb_buffer_response->WordCount == 4)) {
2523 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2524 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2526 if (action & GUEST_LOGIN)
2527 cFYI(1, (" Guest login"));
2528 /* Do we want to set anything in SesInfo struct when guest login? */
2530 bcc_ptr = pByteArea(smb_buffer_response);
2531 /* response can have either 3 or 4 word count - Samba sends 3 */
2533 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2534 if (SecurityBlob2->MessageType != NtLmChallenge) {
2536 ("Unexpected NTLMSSP message type received %d",
2537 SecurityBlob2->MessageType));
2539 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2540 cFYI(1, ("UID = %d ", ses->Suid));
2541 if ((pSMBr->resp.hdr.WordCount == 3)
2542 || ((pSMBr->resp.hdr.WordCount == 4)
2544 pSMBr->resp.ByteCount))) {
2546 if (pSMBr->resp.hdr.WordCount == 4) {
2547 bcc_ptr += blob_len;
2549 ("Security Blob Length %d ",
2553 cFYI(1, ("NTLMSSP Challenge rcvd "));
2555 memcpy(ses->server->cryptKey,
2556 SecurityBlob2->Challenge,
2557 CIFS_CRYPTO_KEY_SIZE);
2558 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2559 *pNTLMv2_flag = TRUE;
2561 if((SecurityBlob2->NegotiateFlags &
2562 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2563 || (sign_CIFS_PDUs > 1))
2564 ses->server->secMode |=
2565 SECMODE_SIGN_REQUIRED;
2566 if ((SecurityBlob2->NegotiateFlags &
2567 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2568 ses->server->secMode |=
2569 SECMODE_SIGN_ENABLED;
2571 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2572 if ((long) (bcc_ptr) % 2) {
2574 (BCC(smb_buffer_response)
2576 bcc_ptr++; /* Unicode strings must be word aligned */
2580 (smb_buffer_response) / 2;
2583 UniStrnlen((wchar_t *) bcc_ptr,
2584 remaining_words - 1);
2585 /* We look for obvious messed up bcc or strings in response so we do not go off
2586 the end since (at least) WIN2K and Windows XP have a major bug in not null
2587 terminating last Unicode string in response */
2589 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2590 cifs_strfromUCS_le(ses->serverOS,
2594 bcc_ptr += 2 * (len + 1);
2595 remaining_words -= len + 1;
2596 ses->serverOS[2 * len] = 0;
2597 ses->serverOS[1 + (2 * len)] = 0;
2598 if (remaining_words > 0) {
2599 len = UniStrnlen((wchar_t *)
2604 kcalloc(1, 2 * (len + 1),
2606 cifs_strfromUCS_le(ses->
2612 bcc_ptr += 2 * (len + 1);
2613 ses->serverNOS[2 * len] = 0;
2616 remaining_words -= len + 1;
2617 if (remaining_words > 0) {
2618 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2619 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2644 } /* else no more room so create dummy domain string */
2649 } else { /* no room so create dummy domain and NOS string */
2651 kcalloc(1, 2, GFP_KERNEL);
2653 kcalloc(1, 2, GFP_KERNEL);
2655 } else { /* ASCII */
2656 len = strnlen(bcc_ptr, 1024);
2657 if (((long) bcc_ptr + len) - (long)
2658 pByteArea(smb_buffer_response)
2659 <= BCC(smb_buffer_response)) {
2663 strncpy(ses->serverOS,
2667 bcc_ptr[0] = 0; /* null terminate string */
2670 len = strnlen(bcc_ptr, 1024);
2674 strncpy(ses->serverNOS, bcc_ptr, len);
2679 len = strnlen(bcc_ptr, 1024);
2683 strncpy(ses->serverDomain, bcc_ptr, len);
2689 ("Variable field of length %d extends beyond end of smb ",
2694 (" Security Blob Length extends beyond end of SMB"));
2697 cERROR(1, ("No session structure passed in."));
2701 (" Invalid Word count %d: ",
2702 smb_buffer_response->WordCount));
2707 cifs_buf_release(smb_buffer);
2712 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2713 char *ntlm_session_key, int ntlmv2_flag,
2714 const struct nls_table *nls_codepage)
2716 struct smb_hdr *smb_buffer;
2717 struct smb_hdr *smb_buffer_response;
2718 SESSION_SETUP_ANDX *pSMB;
2719 SESSION_SETUP_ANDX *pSMBr;
2724 int remaining_words = 0;
2725 int bytes_returned = 0;
2727 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2728 PAUTHENTICATE_MESSAGE SecurityBlob;
2729 __u32 negotiate_flags, capabilities;
2732 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2735 user = ses->userName;
2736 domain = ses->domainName;
2737 smb_buffer = cifs_buf_get();
2738 if (smb_buffer == NULL) {
2741 smb_buffer_response = smb_buffer;
2742 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2743 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2745 /* send SMBsessionSetup here */
2746 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2747 NULL /* no tCon exists yet */ , 12 /* wct */ );
2749 smb_buffer->Mid = GetNextMid(ses->server);
2750 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2751 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2752 pSMB->req.AndXCommand = 0xFF;
2753 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2754 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2756 pSMB->req.hdr.Uid = ses->Suid;
2758 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2759 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2761 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2762 CAP_EXTENDED_SECURITY;
2763 if (ses->capabilities & CAP_UNICODE) {
2764 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2765 capabilities |= CAP_UNICODE;
2767 if (ses->capabilities & CAP_STATUS32) {
2768 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2769 capabilities |= CAP_STATUS32;
2771 if (ses->capabilities & CAP_DFS) {
2772 smb_buffer->Flags2 |= SMBFLG2_DFS;
2773 capabilities |= CAP_DFS;
2775 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2777 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2778 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2779 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2780 SecurityBlob->MessageType = NtLmAuthenticate;
2781 bcc_ptr += SecurityBlobLength;
2783 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2784 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2785 0x80000000 | NTLMSSP_NEGOTIATE_128;
2787 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2789 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2791 /* setup pointers to domain name and workstation name */
2793 SecurityBlob->WorkstationName.Buffer = 0;
2794 SecurityBlob->WorkstationName.Length = 0;
2795 SecurityBlob->WorkstationName.MaximumLength = 0;
2796 SecurityBlob->SessionKey.Length = 0;
2797 SecurityBlob->SessionKey.MaximumLength = 0;
2798 SecurityBlob->SessionKey.Buffer = 0;
2800 SecurityBlob->LmChallengeResponse.Length = 0;
2801 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2802 SecurityBlob->LmChallengeResponse.Buffer = 0;
2804 SecurityBlob->NtChallengeResponse.Length =
2805 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2806 SecurityBlob->NtChallengeResponse.MaximumLength =
2807 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2808 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2809 SecurityBlob->NtChallengeResponse.Buffer =
2810 cpu_to_le32(SecurityBlobLength);
2811 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2812 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2814 if (ses->capabilities & CAP_UNICODE) {
2815 if (domain == NULL) {
2816 SecurityBlob->DomainName.Buffer = 0;
2817 SecurityBlob->DomainName.Length = 0;
2818 SecurityBlob->DomainName.MaximumLength = 0;
2821 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2824 SecurityBlob->DomainName.MaximumLength =
2826 SecurityBlob->DomainName.Buffer =
2827 cpu_to_le32(SecurityBlobLength);
2829 SecurityBlobLength += len;
2830 SecurityBlob->DomainName.Length =
2834 SecurityBlob->UserName.Buffer = 0;
2835 SecurityBlob->UserName.Length = 0;
2836 SecurityBlob->UserName.MaximumLength = 0;
2839 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2842 SecurityBlob->UserName.MaximumLength =
2844 SecurityBlob->UserName.Buffer =
2845 cpu_to_le32(SecurityBlobLength);
2847 SecurityBlobLength += len;
2848 SecurityBlob->UserName.Length =
2852 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2853 SecurityBlob->WorkstationName.Length *= 2;
2854 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2855 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2856 bcc_ptr += SecurityBlob->WorkstationName.Length;
2857 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2858 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2860 if ((long) bcc_ptr % 2) {
2865 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2867 bcc_ptr += 2 * bytes_returned;
2869 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2871 bcc_ptr += 2 * bytes_returned;
2872 bcc_ptr += 2; /* null term version string */
2874 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2876 bcc_ptr += 2 * bytes_returned;
2879 bcc_ptr += 2; /* null terminate network opsys string */
2882 bcc_ptr += 2; /* null domain */
2883 } else { /* ASCII */
2884 if (domain == NULL) {
2885 SecurityBlob->DomainName.Buffer = 0;
2886 SecurityBlob->DomainName.Length = 0;
2887 SecurityBlob->DomainName.MaximumLength = 0;
2890 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2891 strncpy(bcc_ptr, domain, 63);
2892 len = strnlen(domain, 64);
2893 SecurityBlob->DomainName.MaximumLength =
2895 SecurityBlob->DomainName.Buffer =
2896 cpu_to_le32(SecurityBlobLength);
2898 SecurityBlobLength += len;
2899 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2902 SecurityBlob->UserName.Buffer = 0;
2903 SecurityBlob->UserName.Length = 0;
2904 SecurityBlob->UserName.MaximumLength = 0;
2907 strncpy(bcc_ptr, user, 63);
2908 len = strnlen(user, 64);
2909 SecurityBlob->UserName.MaximumLength =
2911 SecurityBlob->UserName.Buffer =
2912 cpu_to_le32(SecurityBlobLength);
2914 SecurityBlobLength += len;
2915 SecurityBlob->UserName.Length = cpu_to_le16(len);
2917 /* BB fill in our workstation name if known BB */
2919 strcpy(bcc_ptr, "Linux version ");
2920 bcc_ptr += strlen("Linux version ");
2921 strcpy(bcc_ptr, system_utsname.release);
2922 bcc_ptr += strlen(system_utsname.release) + 1;
2923 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2924 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2925 bcc_ptr++; /* null domain */
2928 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2929 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2930 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2931 smb_buffer->smb_buf_length += count;
2932 pSMB->req.ByteCount = cpu_to_le16(count);
2934 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2935 &bytes_returned, 1);
2937 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2938 } else if ((smb_buffer_response->WordCount == 3)
2939 || (smb_buffer_response->WordCount == 4)) {
2940 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2942 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2943 if (action & GUEST_LOGIN)
2944 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2945 /* if(SecurityBlob2->MessageType != NtLm??){
2946 cFYI("Unexpected message type on auth response is %d "));
2950 ("Does UID on challenge %d match auth response UID %d ",
2951 ses->Suid, smb_buffer_response->Uid));
2952 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2953 bcc_ptr = pByteArea(smb_buffer_response);
2954 /* response can have either 3 or 4 word count - Samba sends 3 */
2955 if ((pSMBr->resp.hdr.WordCount == 3)
2956 || ((pSMBr->resp.hdr.WordCount == 4)
2958 pSMBr->resp.ByteCount))) {
2959 if (pSMBr->resp.hdr.WordCount == 4) {
2963 ("Security Blob Length %d ",
2968 ("NTLMSSP response to Authenticate "));
2970 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2971 if ((long) (bcc_ptr) % 2) {
2973 (BCC(smb_buffer_response)
2975 bcc_ptr++; /* Unicode strings must be word aligned */
2977 remaining_words = BCC(smb_buffer_response) / 2;
2980 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2981 /* We look for obvious messed up bcc or strings in response so we do not go off
2982 the end since (at least) WIN2K and Windows XP have a major bug in not null
2983 terminating last Unicode string in response */
2985 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2986 cifs_strfromUCS_le(ses->serverOS,
2990 bcc_ptr += 2 * (len + 1);
2991 remaining_words -= len + 1;
2992 ses->serverOS[2 * len] = 0;
2993 ses->serverOS[1 + (2 * len)] = 0;
2994 if (remaining_words > 0) {
2995 len = UniStrnlen((wchar_t *)
3000 kcalloc(1, 2 * (len + 1),
3002 cifs_strfromUCS_le(ses->
3008 bcc_ptr += 2 * (len + 1);
3009 ses->serverNOS[2 * len] = 0;
3010 ses->serverNOS[1+(2*len)] = 0;
3011 remaining_words -= len + 1;
3012 if (remaining_words > 0) {
3013 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3014 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3039 } /* else no more room so create dummy domain string */
3041 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
3042 } else { /* no room so create dummy domain and NOS string */
3043 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
3044 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
3046 } else { /* ASCII */
3047 len = strnlen(bcc_ptr, 1024);
3048 if (((long) bcc_ptr + len) -
3049 (long) pByteArea(smb_buffer_response)
3050 <= BCC(smb_buffer_response)) {
3051 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
3052 strncpy(ses->serverOS,bcc_ptr, len);
3055 bcc_ptr[0] = 0; /* null terminate the string */
3058 len = strnlen(bcc_ptr, 1024);
3059 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
3060 strncpy(ses->serverNOS, bcc_ptr, len);
3065 len = strnlen(bcc_ptr, 1024);
3066 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
3067 strncpy(ses->serverDomain, bcc_ptr, len);
3073 ("Variable field of length %d extends beyond end of smb ",
3078 (" Security Blob Length extends beyond end of SMB"));
3081 cERROR(1, ("No session structure passed in."));
3085 (" Invalid Word count %d: ",
3086 smb_buffer_response->WordCount));
3091 cifs_buf_release(smb_buffer);
3097 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3098 const char *tree, struct cifsTconInfo *tcon,
3099 const struct nls_table *nls_codepage)
3101 struct smb_hdr *smb_buffer;
3102 struct smb_hdr *smb_buffer_response;
3105 unsigned char *bcc_ptr;
3113 smb_buffer = cifs_buf_get();
3114 if (smb_buffer == NULL) {
3117 smb_buffer_response = smb_buffer;
3119 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3120 NULL /*no tid */ , 4 /*wct */ );
3122 smb_buffer->Mid = GetNextMid(ses->server);
3123 smb_buffer->Uid = ses->Suid;
3124 pSMB = (TCONX_REQ *) smb_buffer;
3125 pSMBr = (TCONX_RSP *) smb_buffer_response;
3127 pSMB->AndXCommand = 0xFF;
3128 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3129 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3130 bcc_ptr = &pSMB->Password[0];
3131 bcc_ptr++; /* skip password */
3133 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3134 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3136 if (ses->capabilities & CAP_STATUS32) {
3137 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3139 if (ses->capabilities & CAP_DFS) {
3140 smb_buffer->Flags2 |= SMBFLG2_DFS;
3142 if (ses->capabilities & CAP_UNICODE) {
3143 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3145 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
3146 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3147 bcc_ptr += 2; /* skip trailing null */
3148 } else { /* ASCII */
3150 strcpy(bcc_ptr, tree);
3151 bcc_ptr += strlen(tree) + 1;
3153 strcpy(bcc_ptr, "?????");
3154 bcc_ptr += strlen("?????");
3156 count = bcc_ptr - &pSMB->Password[0];
3157 pSMB->hdr.smb_buf_length += count;
3158 pSMB->ByteCount = cpu_to_le16(count);
3160 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3162 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3163 /* above now done in SendReceive */
3164 if ((rc == 0) && (tcon != NULL)) {
3165 tcon->tidStatus = CifsGood;
3166 tcon->tid = smb_buffer_response->Tid;
3167 bcc_ptr = pByteArea(smb_buffer_response);
3168 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3169 /* skip service field (NB: this field is always ASCII) */
3170 bcc_ptr += length + 1;
3171 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3172 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3173 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3174 if ((bcc_ptr + (2 * length)) -
3175 pByteArea(smb_buffer_response) <=
3176 BCC(smb_buffer_response)) {
3177 if(tcon->nativeFileSystem)
3178 kfree(tcon->nativeFileSystem);
3179 tcon->nativeFileSystem =
3180 kcalloc(1, length + 2, GFP_KERNEL);
3181 cifs_strfromUCS_le(tcon->nativeFileSystem,
3182 (wchar_t *) bcc_ptr,
3183 length, nls_codepage);
3184 bcc_ptr += 2 * length;
3185 bcc_ptr[0] = 0; /* null terminate the string */
3189 /* else do not bother copying these informational fields */
3191 length = strnlen(bcc_ptr, 1024);
3192 if ((bcc_ptr + length) -
3193 pByteArea(smb_buffer_response) <=
3194 BCC(smb_buffer_response)) {
3195 if(tcon->nativeFileSystem)
3196 kfree(tcon->nativeFileSystem);
3197 tcon->nativeFileSystem =
3198 kcalloc(1, length + 1, GFP_KERNEL);
3199 strncpy(tcon->nativeFileSystem, bcc_ptr,
3202 /* else do not bother copying these informational fields */
3204 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3205 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3206 } else if ((rc == 0) && tcon == NULL) {
3207 /* all we need to save for IPC$ connection */
3208 ses->ipc_tid = smb_buffer_response->Tid;
3212 cifs_buf_release(smb_buffer);
3217 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3221 struct cifsSesInfo *ses = NULL;
3222 struct task_struct *cifsd_task;
3226 if (cifs_sb->tcon) {
3227 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3228 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3233 tconInfoFree(cifs_sb->tcon);
3234 if ((ses) && (ses->server)) {
3235 /* save off task so we do not refer to ses later */
3236 cifsd_task = ses->server->tsk;
3237 cFYI(1, ("About to do SMBLogoff "));
3238 rc = CIFSSMBLogoff(xid, ses);
3242 } else if (rc == -ESHUTDOWN) {
3243 cFYI(1,("Waking up socket by sending it signal"));
3245 send_sig(SIGKILL,cifsd_task,1);
3247 } /* else - we have an smb session
3248 left on this socket do not kill cifsd */
3250 cFYI(1, ("No session or bad tcon"));
3253 cifs_sb->tcon = NULL;
3255 set_current_state(TASK_INTERRUPTIBLE);
3256 schedule_timeout(HZ / 2);
3262 return rc; /* BB check if we should always return zero here */
3265 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3266 struct nls_table * nls_info)
3269 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3270 int ntlmv2_flag = FALSE;
3273 /* what if server changes its buffer size after dropping the session? */
3274 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3275 rc = CIFSSMBNegotiate(xid, pSesInfo);
3276 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3277 rc = CIFSSMBNegotiate(xid, pSesInfo);
3282 spin_lock(&GlobalMid_Lock);
3283 if(pSesInfo->server->tcpStatus != CifsExiting)
3284 pSesInfo->server->tcpStatus = CifsGood;
3287 spin_unlock(&GlobalMid_Lock);
3293 pSesInfo->capabilities = pSesInfo->server->capabilities;
3294 if(linuxExtEnabled == 0)
3295 pSesInfo->capabilities &= (~CAP_UNIX);
3296 /* pSesInfo->sequence_number = 0;*/
3297 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3298 pSesInfo->server->secMode,
3299 pSesInfo->server->capabilities,
3300 pSesInfo->server->timeZone));
3301 if (extended_security
3302 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3303 && (pSesInfo->server->secType == NTLMSSP)) {
3304 cFYI(1, ("New style sesssetup "));
3305 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3306 NULL /* security blob */,
3307 0 /* blob length */,
3309 } else if (extended_security
3310 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3311 && (pSesInfo->server->secType == RawNTLMSSP)) {
3312 cFYI(1, ("NTLMSSP sesssetup "));
3313 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3320 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3321 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3326 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3328 CalcNTLMv2_response(pSesInfo,v2_response);
3330 cifs_calculate_ntlmv2_mac_key(
3331 pSesInfo->server->mac_signing_key,
3332 response, ntlm_session_key, */
3334 /* BB Put dummy sig in SessSetup PDU? */
3341 SMBNTencrypt(pSesInfo->password,
3342 pSesInfo->server->cryptKey,
3346 cifs_calculate_mac_key(
3347 pSesInfo->server->mac_signing_key,
3349 pSesInfo->password);
3351 /* for better security the weaker lanman hash not sent
3352 in AuthSessSetup so we no longer calculate it */
3354 rc = CIFSNTLMSSPAuthSessSetup(xid,
3360 } else { /* old style NTLM 0.12 session setup */
3361 SMBNTencrypt(pSesInfo->password,
3362 pSesInfo->server->cryptKey,
3366 cifs_calculate_mac_key(
3367 pSesInfo->server->mac_signing_key,
3368 ntlm_session_key, pSesInfo->password);
3370 rc = CIFSSessSetup(xid, pSesInfo,
3371 ntlm_session_key, nls_info);
3374 cERROR(1,("Send error in SessSetup = %d",rc));
3376 cFYI(1,("CIFS Session Established successfully"));
3377 pSesInfo->status = CifsGood;