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 pSMB->req_no_secext.AndXCommand = 0xFF;
1861 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1862 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1864 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1865 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1867 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1868 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1869 if (ses->capabilities & CAP_UNICODE) {
1870 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1871 capabilities |= CAP_UNICODE;
1873 if (ses->capabilities & CAP_STATUS32) {
1874 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1875 capabilities |= CAP_STATUS32;
1877 if (ses->capabilities & CAP_DFS) {
1878 smb_buffer->Flags2 |= SMBFLG2_DFS;
1879 capabilities |= CAP_DFS;
1881 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1883 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1884 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1886 pSMB->req_no_secext.CaseSensitivePasswordLength =
1887 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1888 bcc_ptr = pByteArea(smb_buffer);
1889 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1890 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1891 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1892 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1894 if (ses->capabilities & CAP_UNICODE) {
1895 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1900 bytes_returned = 0; /* skill null user */
1903 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1905 /* convert number of 16 bit words to bytes */
1906 bcc_ptr += 2 * bytes_returned;
1907 bcc_ptr += 2; /* trailing null */
1910 cifs_strtoUCS((wchar_t *) bcc_ptr,
1911 "CIFS_LINUX_DOM", 32, nls_codepage);
1914 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1916 bcc_ptr += 2 * bytes_returned;
1919 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1921 bcc_ptr += 2 * bytes_returned;
1923 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1925 bcc_ptr += 2 * bytes_returned;
1928 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1930 bcc_ptr += 2 * bytes_returned;
1934 strncpy(bcc_ptr, user, 200);
1935 bcc_ptr += strnlen(user, 200);
1939 if (domain == NULL) {
1940 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1941 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1943 strncpy(bcc_ptr, domain, 64);
1944 bcc_ptr += strnlen(domain, 64);
1948 strcpy(bcc_ptr, "Linux version ");
1949 bcc_ptr += strlen("Linux version ");
1950 strcpy(bcc_ptr, system_utsname.release);
1951 bcc_ptr += strlen(system_utsname.release) + 1;
1952 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1953 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1955 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1956 smb_buffer->smb_buf_length += count;
1957 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1959 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1960 &bytes_returned, 1);
1962 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1963 } else if ((smb_buffer_response->WordCount == 3)
1964 || (smb_buffer_response->WordCount == 4)) {
1965 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1966 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1967 if (action & GUEST_LOGIN)
1968 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1969 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1970 cFYI(1, ("UID = %d ", ses->Suid));
1971 /* response can have either 3 or 4 word count - Samba sends 3 */
1972 bcc_ptr = pByteArea(smb_buffer_response);
1973 if ((pSMBr->resp.hdr.WordCount == 3)
1974 || ((pSMBr->resp.hdr.WordCount == 4)
1975 && (blob_len < pSMBr->resp.ByteCount))) {
1976 if (pSMBr->resp.hdr.WordCount == 4)
1977 bcc_ptr += blob_len;
1979 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1980 if ((long) (bcc_ptr) % 2) {
1982 (BCC(smb_buffer_response) - 1) /2;
1983 bcc_ptr++; /* Unicode strings must be word aligned */
1986 BCC(smb_buffer_response) / 2;
1989 UniStrnlen((wchar_t *) bcc_ptr,
1990 remaining_words - 1);
1991 /* We look for obvious messed up bcc or strings in response so we do not go off
1992 the end since (at least) WIN2K and Windows XP have a major bug in not null
1993 terminating last Unicode string in response */
1994 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1995 if(ses->serverOS == NULL)
1996 goto sesssetup_nomem;
1997 cifs_strfromUCS_le(ses->serverOS,
1998 (wchar_t *)bcc_ptr, len,nls_codepage);
1999 bcc_ptr += 2 * (len + 1);
2000 remaining_words -= len + 1;
2001 ses->serverOS[2 * len] = 0;
2002 ses->serverOS[1 + (2 * len)] = 0;
2003 if (remaining_words > 0) {
2004 len = UniStrnlen((wchar_t *)bcc_ptr,
2006 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
2007 if(ses->serverNOS == NULL)
2008 goto sesssetup_nomem;
2009 cifs_strfromUCS_le(ses->serverNOS,
2010 (wchar_t *)bcc_ptr,len,nls_codepage);
2011 bcc_ptr += 2 * (len + 1);
2012 ses->serverNOS[2 * len] = 0;
2013 ses->serverNOS[1 + (2 * len)] = 0;
2014 if(strncmp(ses->serverNOS,
2015 "NT LAN Manager 4",16) == 0) {
2016 cFYI(1,("NT4 server"));
2017 ses->flags |= CIFS_SES_NT4;
2019 remaining_words -= len + 1;
2020 if (remaining_words > 0) {
2021 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2022 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2024 kcalloc(1, 2*(len+1),GFP_KERNEL);
2025 if(ses->serverDomain == NULL)
2026 goto sesssetup_nomem;
2027 cifs_strfromUCS_le(ses->serverDomain,
2028 (wchar_t *)bcc_ptr,len,nls_codepage);
2029 bcc_ptr += 2 * (len + 1);
2030 ses->serverDomain[2*len] = 0;
2031 ses->serverDomain[1+(2*len)] = 0;
2032 } /* else no more room so create dummy domain string */
2035 kcalloc(1, 2, GFP_KERNEL);
2036 } else { /* no room so create dummy domain and NOS string */
2037 /* if these kcallocs fail not much we
2038 can do, but better to not fail the
2041 kcalloc(1, 2, GFP_KERNEL);
2043 kcalloc(1, 2, GFP_KERNEL);
2045 } else { /* ASCII */
2046 len = strnlen(bcc_ptr, 1024);
2047 if (((long) bcc_ptr + len) - (long)
2048 pByteArea(smb_buffer_response)
2049 <= BCC(smb_buffer_response)) {
2050 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2051 if(ses->serverOS == NULL)
2052 goto sesssetup_nomem;
2053 strncpy(ses->serverOS,bcc_ptr, len);
2056 bcc_ptr[0] = 0; /* null terminate the string */
2059 len = strnlen(bcc_ptr, 1024);
2060 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2061 if(ses->serverNOS == NULL)
2062 goto sesssetup_nomem;
2063 strncpy(ses->serverNOS, bcc_ptr, len);
2068 len = strnlen(bcc_ptr, 1024);
2069 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2070 if(ses->serverDomain == NULL)
2071 goto sesssetup_nomem;
2072 strncpy(ses->serverDomain, bcc_ptr, len);
2078 ("Variable field of length %d extends beyond end of smb ",
2083 (" Security Blob Length extends beyond end of SMB"));
2087 (" Invalid Word count %d: ",
2088 smb_buffer_response->WordCount));
2091 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2092 since that could make reconnection harder, and
2093 reconnection might be needed to free memory */
2095 cifs_buf_release(smb_buffer);
2101 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2102 char *SecurityBlob,int SecurityBlobLength,
2103 const struct nls_table *nls_codepage)
2105 struct smb_hdr *smb_buffer;
2106 struct smb_hdr *smb_buffer_response;
2107 SESSION_SETUP_ANDX *pSMB;
2108 SESSION_SETUP_ANDX *pSMBr;
2113 int remaining_words = 0;
2114 int bytes_returned = 0;
2119 cFYI(1, ("In spnego sesssetup "));
2122 user = ses->userName;
2123 domain = ses->domainName;
2125 smb_buffer = cifs_buf_get();
2126 if (smb_buffer == NULL) {
2129 smb_buffer_response = smb_buffer;
2130 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2132 /* send SMBsessionSetup here */
2133 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2134 NULL /* no tCon exists yet */ , 12 /* wct */ );
2135 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2136 pSMB->req.AndXCommand = 0xFF;
2137 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2138 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2140 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2141 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2143 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2144 CAP_EXTENDED_SECURITY;
2145 if (ses->capabilities & CAP_UNICODE) {
2146 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2147 capabilities |= CAP_UNICODE;
2149 if (ses->capabilities & CAP_STATUS32) {
2150 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2151 capabilities |= CAP_STATUS32;
2153 if (ses->capabilities & CAP_DFS) {
2154 smb_buffer->Flags2 |= SMBFLG2_DFS;
2155 capabilities |= CAP_DFS;
2157 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2159 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2160 bcc_ptr = pByteArea(smb_buffer);
2161 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2162 bcc_ptr += SecurityBlobLength;
2164 if (ses->capabilities & CAP_UNICODE) {
2165 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2170 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
2171 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2172 bcc_ptr += 2; /* trailing null */
2175 cifs_strtoUCS((wchar_t *) bcc_ptr,
2176 "CIFS_LINUX_DOM", 32, nls_codepage);
2179 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2181 bcc_ptr += 2 * bytes_returned;
2184 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2186 bcc_ptr += 2 * bytes_returned;
2188 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2190 bcc_ptr += 2 * bytes_returned;
2193 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2195 bcc_ptr += 2 * bytes_returned;
2198 strncpy(bcc_ptr, user, 200);
2199 bcc_ptr += strnlen(user, 200);
2202 if (domain == NULL) {
2203 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2204 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2206 strncpy(bcc_ptr, domain, 64);
2207 bcc_ptr += strnlen(domain, 64);
2211 strcpy(bcc_ptr, "Linux version ");
2212 bcc_ptr += strlen("Linux version ");
2213 strcpy(bcc_ptr, system_utsname.release);
2214 bcc_ptr += strlen(system_utsname.release) + 1;
2215 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2216 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2218 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2219 smb_buffer->smb_buf_length += count;
2220 pSMB->req.ByteCount = cpu_to_le16(count);
2222 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2223 &bytes_returned, 1);
2225 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2226 } else if ((smb_buffer_response->WordCount == 3)
2227 || (smb_buffer_response->WordCount == 4)) {
2228 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2230 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2231 if (action & GUEST_LOGIN)
2232 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2234 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2235 cFYI(1, ("UID = %d ", ses->Suid));
2236 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2238 /* BB Fix below to make endian neutral !! */
2240 if ((pSMBr->resp.hdr.WordCount == 3)
2241 || ((pSMBr->resp.hdr.WordCount == 4)
2243 pSMBr->resp.ByteCount))) {
2244 if (pSMBr->resp.hdr.WordCount == 4) {
2248 ("Security Blob Length %d ",
2252 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2253 if ((long) (bcc_ptr) % 2) {
2255 (BCC(smb_buffer_response)
2257 bcc_ptr++; /* Unicode strings must be word aligned */
2261 (smb_buffer_response) / 2;
2264 UniStrnlen((wchar_t *) bcc_ptr,
2265 remaining_words - 1);
2266 /* We look for obvious messed up bcc or strings in response so we do not go off
2267 the end since (at least) WIN2K and Windows XP have a major bug in not null
2268 terminating last Unicode string in response */
2270 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2271 cifs_strfromUCS_le(ses->serverOS,
2275 bcc_ptr += 2 * (len + 1);
2276 remaining_words -= len + 1;
2277 ses->serverOS[2 * len] = 0;
2278 ses->serverOS[1 + (2 * len)] = 0;
2279 if (remaining_words > 0) {
2280 len = UniStrnlen((wchar_t *)bcc_ptr,
2284 kcalloc(1, 2 * (len + 1),
2286 cifs_strfromUCS_le(ses->serverNOS,
2290 bcc_ptr += 2 * (len + 1);
2291 ses->serverNOS[2 * len] = 0;
2292 ses->serverNOS[1 + (2 * len)] = 0;
2293 remaining_words -= len + 1;
2294 if (remaining_words > 0) {
2295 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2296 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2297 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2298 cifs_strfromUCS_le(ses->serverDomain,
2302 bcc_ptr += 2*(len+1);
2303 ses->serverDomain[2*len] = 0;
2304 ses->serverDomain[1+(2*len)] = 0;
2305 } /* else no more room so create dummy domain string */
2308 kcalloc(1, 2,GFP_KERNEL);
2309 } else { /* no room so create dummy domain and NOS string */
2310 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2311 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2313 } else { /* ASCII */
2315 len = strnlen(bcc_ptr, 1024);
2316 if (((long) bcc_ptr + len) - (long)
2317 pByteArea(smb_buffer_response)
2318 <= BCC(smb_buffer_response)) {
2319 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2320 strncpy(ses->serverOS, bcc_ptr, len);
2323 bcc_ptr[0] = 0; /* null terminate the string */
2326 len = strnlen(bcc_ptr, 1024);
2327 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2328 strncpy(ses->serverNOS, bcc_ptr, len);
2333 len = strnlen(bcc_ptr, 1024);
2334 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2335 strncpy(ses->serverDomain, bcc_ptr, len);
2341 ("Variable field of length %d extends beyond end of smb ",
2346 (" Security Blob Length extends beyond end of SMB"));
2349 cERROR(1, ("No session structure passed in."));
2353 (" Invalid Word count %d: ",
2354 smb_buffer_response->WordCount));
2359 cifs_buf_release(smb_buffer);
2365 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2366 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2367 const struct nls_table *nls_codepage)
2369 struct smb_hdr *smb_buffer;
2370 struct smb_hdr *smb_buffer_response;
2371 SESSION_SETUP_ANDX *pSMB;
2372 SESSION_SETUP_ANDX *pSMBr;
2376 int remaining_words = 0;
2377 int bytes_returned = 0;
2379 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2380 PNEGOTIATE_MESSAGE SecurityBlob;
2381 PCHALLENGE_MESSAGE SecurityBlob2;
2382 __u32 negotiate_flags, capabilities;
2385 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2388 domain = ses->domainName;
2389 *pNTLMv2_flag = FALSE;
2390 smb_buffer = cifs_buf_get();
2391 if (smb_buffer == NULL) {
2394 smb_buffer_response = smb_buffer;
2395 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2396 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2398 /* send SMBsessionSetup here */
2399 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2400 NULL /* no tCon exists yet */ , 12 /* wct */ );
2401 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2402 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2404 pSMB->req.AndXCommand = 0xFF;
2405 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2406 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2408 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2409 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2411 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2412 CAP_EXTENDED_SECURITY;
2413 if (ses->capabilities & CAP_UNICODE) {
2414 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2415 capabilities |= CAP_UNICODE;
2417 if (ses->capabilities & CAP_STATUS32) {
2418 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2419 capabilities |= CAP_STATUS32;
2421 if (ses->capabilities & CAP_DFS) {
2422 smb_buffer->Flags2 |= SMBFLG2_DFS;
2423 capabilities |= CAP_DFS;
2425 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2427 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2428 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2429 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2430 SecurityBlob->MessageType = NtLmNegotiate;
2432 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2433 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2434 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2436 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2438 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2439 /* setup pointers to domain name and workstation name */
2440 bcc_ptr += SecurityBlobLength;
2442 SecurityBlob->WorkstationName.Buffer = 0;
2443 SecurityBlob->WorkstationName.Length = 0;
2444 SecurityBlob->WorkstationName.MaximumLength = 0;
2446 if (domain == NULL) {
2447 SecurityBlob->DomainName.Buffer = 0;
2448 SecurityBlob->DomainName.Length = 0;
2449 SecurityBlob->DomainName.MaximumLength = 0;
2452 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2453 strncpy(bcc_ptr, domain, 63);
2454 len = strnlen(domain, 64);
2455 SecurityBlob->DomainName.MaximumLength =
2457 SecurityBlob->DomainName.Buffer =
2458 cpu_to_le32((long) &SecurityBlob->
2460 (long) &SecurityBlob->Signature);
2462 SecurityBlobLength += len;
2463 SecurityBlob->DomainName.Length =
2466 if (ses->capabilities & CAP_UNICODE) {
2467 if ((long) bcc_ptr % 2) {
2473 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2475 bcc_ptr += 2 * bytes_returned;
2477 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2479 bcc_ptr += 2 * bytes_returned;
2480 bcc_ptr += 2; /* null terminate Linux version */
2482 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2484 bcc_ptr += 2 * bytes_returned;
2487 bcc_ptr += 2; /* null terminate network opsys string */
2490 bcc_ptr += 2; /* null domain */
2491 } else { /* ASCII */
2492 strcpy(bcc_ptr, "Linux version ");
2493 bcc_ptr += strlen("Linux version ");
2494 strcpy(bcc_ptr, system_utsname.release);
2495 bcc_ptr += strlen(system_utsname.release) + 1;
2496 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2497 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2498 bcc_ptr++; /* empty domain field */
2501 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2502 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2503 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2504 smb_buffer->smb_buf_length += count;
2505 pSMB->req.ByteCount = cpu_to_le16(count);
2507 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2508 &bytes_returned, 1);
2510 if (smb_buffer_response->Status.CifsError ==
2511 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2515 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2516 } else if ((smb_buffer_response->WordCount == 3)
2517 || (smb_buffer_response->WordCount == 4)) {
2518 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2519 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2521 if (action & GUEST_LOGIN)
2522 cFYI(1, (" Guest login"));
2523 /* Do we want to set anything in SesInfo struct when guest login? */
2525 bcc_ptr = pByteArea(smb_buffer_response);
2526 /* response can have either 3 or 4 word count - Samba sends 3 */
2528 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2529 if (SecurityBlob2->MessageType != NtLmChallenge) {
2531 ("Unexpected NTLMSSP message type received %d",
2532 SecurityBlob2->MessageType));
2534 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2535 cFYI(1, ("UID = %d ", ses->Suid));
2536 if ((pSMBr->resp.hdr.WordCount == 3)
2537 || ((pSMBr->resp.hdr.WordCount == 4)
2539 pSMBr->resp.ByteCount))) {
2541 if (pSMBr->resp.hdr.WordCount == 4) {
2542 bcc_ptr += blob_len;
2544 ("Security Blob Length %d ",
2548 cFYI(1, ("NTLMSSP Challenge rcvd "));
2550 memcpy(ses->server->cryptKey,
2551 SecurityBlob2->Challenge,
2552 CIFS_CRYPTO_KEY_SIZE);
2553 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2554 *pNTLMv2_flag = TRUE;
2556 if((SecurityBlob2->NegotiateFlags &
2557 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2558 || (sign_CIFS_PDUs > 1))
2559 ses->server->secMode |=
2560 SECMODE_SIGN_REQUIRED;
2561 if ((SecurityBlob2->NegotiateFlags &
2562 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2563 ses->server->secMode |=
2564 SECMODE_SIGN_ENABLED;
2566 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2567 if ((long) (bcc_ptr) % 2) {
2569 (BCC(smb_buffer_response)
2571 bcc_ptr++; /* Unicode strings must be word aligned */
2575 (smb_buffer_response) / 2;
2578 UniStrnlen((wchar_t *) bcc_ptr,
2579 remaining_words - 1);
2580 /* We look for obvious messed up bcc or strings in response so we do not go off
2581 the end since (at least) WIN2K and Windows XP have a major bug in not null
2582 terminating last Unicode string in response */
2584 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2585 cifs_strfromUCS_le(ses->serverOS,
2589 bcc_ptr += 2 * (len + 1);
2590 remaining_words -= len + 1;
2591 ses->serverOS[2 * len] = 0;
2592 ses->serverOS[1 + (2 * len)] = 0;
2593 if (remaining_words > 0) {
2594 len = UniStrnlen((wchar_t *)
2599 kcalloc(1, 2 * (len + 1),
2601 cifs_strfromUCS_le(ses->
2607 bcc_ptr += 2 * (len + 1);
2608 ses->serverNOS[2 * len] = 0;
2611 remaining_words -= len + 1;
2612 if (remaining_words > 0) {
2613 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2614 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2639 } /* else no more room so create dummy domain string */
2644 } else { /* no room so create dummy domain and NOS string */
2646 kcalloc(1, 2, GFP_KERNEL);
2648 kcalloc(1, 2, GFP_KERNEL);
2650 } else { /* ASCII */
2651 len = strnlen(bcc_ptr, 1024);
2652 if (((long) bcc_ptr + len) - (long)
2653 pByteArea(smb_buffer_response)
2654 <= BCC(smb_buffer_response)) {
2658 strncpy(ses->serverOS,
2662 bcc_ptr[0] = 0; /* null terminate string */
2665 len = strnlen(bcc_ptr, 1024);
2669 strncpy(ses->serverNOS, bcc_ptr, len);
2674 len = strnlen(bcc_ptr, 1024);
2678 strncpy(ses->serverDomain, bcc_ptr, len);
2684 ("Variable field of length %d extends beyond end of smb ",
2689 (" Security Blob Length extends beyond end of SMB"));
2692 cERROR(1, ("No session structure passed in."));
2696 (" Invalid Word count %d: ",
2697 smb_buffer_response->WordCount));
2702 cifs_buf_release(smb_buffer);
2707 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2708 char *ntlm_session_key, int ntlmv2_flag,
2709 const struct nls_table *nls_codepage)
2711 struct smb_hdr *smb_buffer;
2712 struct smb_hdr *smb_buffer_response;
2713 SESSION_SETUP_ANDX *pSMB;
2714 SESSION_SETUP_ANDX *pSMBr;
2719 int remaining_words = 0;
2720 int bytes_returned = 0;
2722 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2723 PAUTHENTICATE_MESSAGE SecurityBlob;
2724 __u32 negotiate_flags, capabilities;
2727 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2730 user = ses->userName;
2731 domain = ses->domainName;
2732 smb_buffer = cifs_buf_get();
2733 if (smb_buffer == NULL) {
2736 smb_buffer_response = smb_buffer;
2737 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2738 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2740 /* send SMBsessionSetup here */
2741 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2742 NULL /* no tCon exists yet */ , 12 /* wct */ );
2743 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2744 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2745 pSMB->req.AndXCommand = 0xFF;
2746 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2747 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2749 pSMB->req.hdr.Uid = ses->Suid;
2751 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2752 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2754 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2755 CAP_EXTENDED_SECURITY;
2756 if (ses->capabilities & CAP_UNICODE) {
2757 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2758 capabilities |= CAP_UNICODE;
2760 if (ses->capabilities & CAP_STATUS32) {
2761 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2762 capabilities |= CAP_STATUS32;
2764 if (ses->capabilities & CAP_DFS) {
2765 smb_buffer->Flags2 |= SMBFLG2_DFS;
2766 capabilities |= CAP_DFS;
2768 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2770 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2771 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2772 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2773 SecurityBlob->MessageType = NtLmAuthenticate;
2774 bcc_ptr += SecurityBlobLength;
2776 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2777 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2778 0x80000000 | NTLMSSP_NEGOTIATE_128;
2780 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2782 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2784 /* setup pointers to domain name and workstation name */
2786 SecurityBlob->WorkstationName.Buffer = 0;
2787 SecurityBlob->WorkstationName.Length = 0;
2788 SecurityBlob->WorkstationName.MaximumLength = 0;
2789 SecurityBlob->SessionKey.Length = 0;
2790 SecurityBlob->SessionKey.MaximumLength = 0;
2791 SecurityBlob->SessionKey.Buffer = 0;
2793 SecurityBlob->LmChallengeResponse.Length = 0;
2794 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2795 SecurityBlob->LmChallengeResponse.Buffer = 0;
2797 SecurityBlob->NtChallengeResponse.Length =
2798 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2799 SecurityBlob->NtChallengeResponse.MaximumLength =
2800 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2801 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2802 SecurityBlob->NtChallengeResponse.Buffer =
2803 cpu_to_le32(SecurityBlobLength);
2804 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2805 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2807 if (ses->capabilities & CAP_UNICODE) {
2808 if (domain == NULL) {
2809 SecurityBlob->DomainName.Buffer = 0;
2810 SecurityBlob->DomainName.Length = 0;
2811 SecurityBlob->DomainName.MaximumLength = 0;
2814 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2817 SecurityBlob->DomainName.MaximumLength =
2819 SecurityBlob->DomainName.Buffer =
2820 cpu_to_le32(SecurityBlobLength);
2822 SecurityBlobLength += len;
2823 SecurityBlob->DomainName.Length =
2827 SecurityBlob->UserName.Buffer = 0;
2828 SecurityBlob->UserName.Length = 0;
2829 SecurityBlob->UserName.MaximumLength = 0;
2832 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2835 SecurityBlob->UserName.MaximumLength =
2837 SecurityBlob->UserName.Buffer =
2838 cpu_to_le32(SecurityBlobLength);
2840 SecurityBlobLength += len;
2841 SecurityBlob->UserName.Length =
2845 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2846 SecurityBlob->WorkstationName.Length *= 2;
2847 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2848 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2849 bcc_ptr += SecurityBlob->WorkstationName.Length;
2850 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2851 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2853 if ((long) bcc_ptr % 2) {
2858 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2860 bcc_ptr += 2 * bytes_returned;
2862 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2864 bcc_ptr += 2 * bytes_returned;
2865 bcc_ptr += 2; /* null term version string */
2867 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2869 bcc_ptr += 2 * bytes_returned;
2872 bcc_ptr += 2; /* null terminate network opsys string */
2875 bcc_ptr += 2; /* null domain */
2876 } else { /* ASCII */
2877 if (domain == NULL) {
2878 SecurityBlob->DomainName.Buffer = 0;
2879 SecurityBlob->DomainName.Length = 0;
2880 SecurityBlob->DomainName.MaximumLength = 0;
2883 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2884 strncpy(bcc_ptr, domain, 63);
2885 len = strnlen(domain, 64);
2886 SecurityBlob->DomainName.MaximumLength =
2888 SecurityBlob->DomainName.Buffer =
2889 cpu_to_le32(SecurityBlobLength);
2891 SecurityBlobLength += len;
2892 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2895 SecurityBlob->UserName.Buffer = 0;
2896 SecurityBlob->UserName.Length = 0;
2897 SecurityBlob->UserName.MaximumLength = 0;
2900 strncpy(bcc_ptr, user, 63);
2901 len = strnlen(user, 64);
2902 SecurityBlob->UserName.MaximumLength =
2904 SecurityBlob->UserName.Buffer =
2905 cpu_to_le32(SecurityBlobLength);
2907 SecurityBlobLength += len;
2908 SecurityBlob->UserName.Length = cpu_to_le16(len);
2910 /* BB fill in our workstation name if known BB */
2912 strcpy(bcc_ptr, "Linux version ");
2913 bcc_ptr += strlen("Linux version ");
2914 strcpy(bcc_ptr, system_utsname.release);
2915 bcc_ptr += strlen(system_utsname.release) + 1;
2916 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2917 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2918 bcc_ptr++; /* null domain */
2921 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2922 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2923 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2924 smb_buffer->smb_buf_length += count;
2925 pSMB->req.ByteCount = cpu_to_le16(count);
2927 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2928 &bytes_returned, 1);
2930 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2931 } else if ((smb_buffer_response->WordCount == 3)
2932 || (smb_buffer_response->WordCount == 4)) {
2933 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2935 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2936 if (action & GUEST_LOGIN)
2937 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2938 /* if(SecurityBlob2->MessageType != NtLm??){
2939 cFYI("Unexpected message type on auth response is %d "));
2943 ("Does UID on challenge %d match auth response UID %d ",
2944 ses->Suid, smb_buffer_response->Uid));
2945 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2946 bcc_ptr = pByteArea(smb_buffer_response);
2947 /* response can have either 3 or 4 word count - Samba sends 3 */
2948 if ((pSMBr->resp.hdr.WordCount == 3)
2949 || ((pSMBr->resp.hdr.WordCount == 4)
2951 pSMBr->resp.ByteCount))) {
2952 if (pSMBr->resp.hdr.WordCount == 4) {
2956 ("Security Blob Length %d ",
2961 ("NTLMSSP response to Authenticate "));
2963 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2964 if ((long) (bcc_ptr) % 2) {
2966 (BCC(smb_buffer_response)
2968 bcc_ptr++; /* Unicode strings must be word aligned */
2970 remaining_words = BCC(smb_buffer_response) / 2;
2973 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2974 /* We look for obvious messed up bcc or strings in response so we do not go off
2975 the end since (at least) WIN2K and Windows XP have a major bug in not null
2976 terminating last Unicode string in response */
2978 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2979 cifs_strfromUCS_le(ses->serverOS,
2983 bcc_ptr += 2 * (len + 1);
2984 remaining_words -= len + 1;
2985 ses->serverOS[2 * len] = 0;
2986 ses->serverOS[1 + (2 * len)] = 0;
2987 if (remaining_words > 0) {
2988 len = UniStrnlen((wchar_t *)
2993 kcalloc(1, 2 * (len + 1),
2995 cifs_strfromUCS_le(ses->
3001 bcc_ptr += 2 * (len + 1);
3002 ses->serverNOS[2 * len] = 0;
3003 ses->serverNOS[1+(2*len)] = 0;
3004 remaining_words -= len + 1;
3005 if (remaining_words > 0) {
3006 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3007 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3032 } /* else no more room so create dummy domain string */
3034 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
3035 } else { /* no room so create dummy domain and NOS string */
3036 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
3037 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
3039 } else { /* ASCII */
3040 len = strnlen(bcc_ptr, 1024);
3041 if (((long) bcc_ptr + len) -
3042 (long) pByteArea(smb_buffer_response)
3043 <= BCC(smb_buffer_response)) {
3044 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
3045 strncpy(ses->serverOS,bcc_ptr, len);
3048 bcc_ptr[0] = 0; /* null terminate the string */
3051 len = strnlen(bcc_ptr, 1024);
3052 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
3053 strncpy(ses->serverNOS, bcc_ptr, len);
3058 len = strnlen(bcc_ptr, 1024);
3059 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
3060 strncpy(ses->serverDomain, bcc_ptr, len);
3066 ("Variable field of length %d extends beyond end of smb ",
3071 (" Security Blob Length extends beyond end of SMB"));
3074 cERROR(1, ("No session structure passed in."));
3078 (" Invalid Word count %d: ",
3079 smb_buffer_response->WordCount));
3084 cifs_buf_release(smb_buffer);
3090 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3091 const char *tree, struct cifsTconInfo *tcon,
3092 const struct nls_table *nls_codepage)
3094 struct smb_hdr *smb_buffer;
3095 struct smb_hdr *smb_buffer_response;
3098 unsigned char *bcc_ptr;
3106 smb_buffer = cifs_buf_get();
3107 if (smb_buffer == NULL) {
3110 smb_buffer_response = smb_buffer;
3112 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3113 NULL /*no tid */ , 4 /*wct */ );
3114 smb_buffer->Uid = ses->Suid;
3115 pSMB = (TCONX_REQ *) smb_buffer;
3116 pSMBr = (TCONX_RSP *) smb_buffer_response;
3118 pSMB->AndXCommand = 0xFF;
3119 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3120 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3121 bcc_ptr = &pSMB->Password[0];
3122 bcc_ptr++; /* skip password */
3124 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3125 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3127 if (ses->capabilities & CAP_STATUS32) {
3128 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3130 if (ses->capabilities & CAP_DFS) {
3131 smb_buffer->Flags2 |= SMBFLG2_DFS;
3133 if (ses->capabilities & CAP_UNICODE) {
3134 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3136 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
3137 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3138 bcc_ptr += 2; /* skip trailing null */
3139 } else { /* ASCII */
3141 strcpy(bcc_ptr, tree);
3142 bcc_ptr += strlen(tree) + 1;
3144 strcpy(bcc_ptr, "?????");
3145 bcc_ptr += strlen("?????");
3147 count = bcc_ptr - &pSMB->Password[0];
3148 pSMB->hdr.smb_buf_length += count;
3149 pSMB->ByteCount = cpu_to_le16(count);
3151 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3153 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3154 /* above now done in SendReceive */
3155 if ((rc == 0) && (tcon != NULL)) {
3156 tcon->tidStatus = CifsGood;
3157 tcon->tid = smb_buffer_response->Tid;
3158 bcc_ptr = pByteArea(smb_buffer_response);
3159 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3160 /* skip service field (NB: this field is always ASCII) */
3161 bcc_ptr += length + 1;
3162 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3163 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3164 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3165 if ((bcc_ptr + (2 * length)) -
3166 pByteArea(smb_buffer_response) <=
3167 BCC(smb_buffer_response)) {
3168 if(tcon->nativeFileSystem)
3169 kfree(tcon->nativeFileSystem);
3170 tcon->nativeFileSystem =
3171 kcalloc(1, length + 2, GFP_KERNEL);
3172 cifs_strfromUCS_le(tcon->nativeFileSystem,
3173 (wchar_t *) bcc_ptr,
3174 length, nls_codepage);
3175 bcc_ptr += 2 * length;
3176 bcc_ptr[0] = 0; /* null terminate the string */
3180 /* else do not bother copying these informational fields */
3182 length = strnlen(bcc_ptr, 1024);
3183 if ((bcc_ptr + length) -
3184 pByteArea(smb_buffer_response) <=
3185 BCC(smb_buffer_response)) {
3186 if(tcon->nativeFileSystem)
3187 kfree(tcon->nativeFileSystem);
3188 tcon->nativeFileSystem =
3189 kcalloc(1, length + 1, GFP_KERNEL);
3190 strncpy(tcon->nativeFileSystem, bcc_ptr,
3193 /* else do not bother copying these informational fields */
3195 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3196 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3197 } else if ((rc == 0) && tcon == NULL) {
3198 /* all we need to save for IPC$ connection */
3199 ses->ipc_tid = smb_buffer_response->Tid;
3203 cifs_buf_release(smb_buffer);
3208 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3212 struct cifsSesInfo *ses = NULL;
3213 struct task_struct *cifsd_task;
3217 if (cifs_sb->tcon) {
3218 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3219 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3224 tconInfoFree(cifs_sb->tcon);
3225 if ((ses) && (ses->server)) {
3226 /* save off task so we do not refer to ses later */
3227 cifsd_task = ses->server->tsk;
3228 cFYI(1, ("About to do SMBLogoff "));
3229 rc = CIFSSMBLogoff(xid, ses);
3233 } else if (rc == -ESHUTDOWN) {
3234 cFYI(1,("Waking up socket by sending it signal"));
3236 send_sig(SIGKILL,cifsd_task,1);
3238 } /* else - we have an smb session
3239 left on this socket do not kill cifsd */
3241 cFYI(1, ("No session or bad tcon"));
3244 cifs_sb->tcon = NULL;
3246 set_current_state(TASK_INTERRUPTIBLE);
3247 schedule_timeout(HZ / 2);
3253 return rc; /* BB check if we should always return zero here */
3256 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3257 struct nls_table * nls_info)
3260 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3261 int ntlmv2_flag = FALSE;
3264 /* what if server changes its buffer size after dropping the session? */
3265 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3266 rc = CIFSSMBNegotiate(xid, pSesInfo);
3267 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3268 rc = CIFSSMBNegotiate(xid, pSesInfo);
3273 spin_lock(&GlobalMid_Lock);
3274 if(pSesInfo->server->tcpStatus != CifsExiting)
3275 pSesInfo->server->tcpStatus = CifsGood;
3278 spin_unlock(&GlobalMid_Lock);
3284 pSesInfo->capabilities = pSesInfo->server->capabilities;
3285 if(linuxExtEnabled == 0)
3286 pSesInfo->capabilities &= (~CAP_UNIX);
3287 /* pSesInfo->sequence_number = 0;*/
3288 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3289 pSesInfo->server->secMode,
3290 pSesInfo->server->capabilities,
3291 pSesInfo->server->timeZone));
3292 if (extended_security
3293 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3294 && (pSesInfo->server->secType == NTLMSSP)) {
3295 cFYI(1, ("New style sesssetup "));
3296 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3297 NULL /* security blob */,
3298 0 /* blob length */,
3300 } else if (extended_security
3301 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3302 && (pSesInfo->server->secType == RawNTLMSSP)) {
3303 cFYI(1, ("NTLMSSP sesssetup "));
3304 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3311 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3312 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3317 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3319 CalcNTLMv2_response(pSesInfo,v2_response);
3321 cifs_calculate_ntlmv2_mac_key(
3322 pSesInfo->server->mac_signing_key,
3323 response, ntlm_session_key, */
3325 /* BB Put dummy sig in SessSetup PDU? */
3332 SMBNTencrypt(pSesInfo->password,
3333 pSesInfo->server->cryptKey,
3337 cifs_calculate_mac_key(
3338 pSesInfo->server->mac_signing_key,
3340 pSesInfo->password);
3342 /* for better security the weaker lanman hash not sent
3343 in AuthSessSetup so we no longer calculate it */
3345 rc = CIFSNTLMSSPAuthSessSetup(xid,
3351 } else { /* old style NTLM 0.12 session setup */
3352 SMBNTencrypt(pSesInfo->password,
3353 pSesInfo->server->cryptKey,
3357 cifs_calculate_mac_key(
3358 pSesInfo->server->mac_signing_key,
3359 ntlm_session_key, pSesInfo->password);
3361 rc = CIFSSessSetup(xid, pSesInfo,
3362 ntlm_session_key, nls_info);
3365 cERROR(1,("Send error in SessSetup = %d",rc));
3367 cFYI(1,("CIFS Session Established successfully"));
3368 pSesInfo->status = CifsGood;