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 */
80 unsigned short int port;
83 static int ipv4_connect(struct sockaddr_in *psin_server,
84 struct socket **csocket,
86 static int ipv6_connect(struct sockaddr_in6 *psin_server,
87 struct socket **csocket);
91 * cifs tcp session reconnection
93 * mark tcp session as reconnecting so temporarily locked
94 * mark all smb sessions as reconnecting for tcp session
95 * reconnect tcp session
96 * wake up waiters on reconnection? - (not needed currently)
100 cifs_reconnect(struct TCP_Server_Info *server)
103 struct list_head *tmp;
104 struct cifsSesInfo *ses;
105 struct cifsTconInfo *tcon;
106 struct mid_q_entry * mid_entry;
108 spin_lock(&GlobalMid_Lock);
109 if(server->tcpStatus == CifsExiting) {
110 /* the demux thread will exit normally
111 next time through the loop */
112 spin_unlock(&GlobalMid_Lock);
115 server->tcpStatus = CifsNeedReconnect;
116 spin_unlock(&GlobalMid_Lock);
119 cFYI(1, ("Reconnecting tcp session"));
121 /* before reconnecting the tcp session, mark the smb session (uid)
122 and the tid bad so they are not used until reconnected */
123 read_lock(&GlobalSMBSeslock);
124 list_for_each(tmp, &GlobalSMBSessionList) {
125 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
127 if (ses->server == server) {
128 ses->status = CifsNeedReconnect;
132 /* else tcp and smb sessions need reconnection */
134 list_for_each(tmp, &GlobalTreeConnectionList) {
135 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
136 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
137 tcon->tidStatus = CifsNeedReconnect;
140 read_unlock(&GlobalSMBSeslock);
141 /* do not want to be sending data on a socket we are freeing */
142 down(&server->tcpSem);
143 if(server->ssocket) {
144 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
145 server->ssocket->flags));
146 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
147 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
148 server->ssocket->flags));
149 sock_release(server->ssocket);
150 server->ssocket = NULL;
153 spin_lock(&GlobalMid_Lock);
154 list_for_each(tmp, &server->pending_mid_q) {
155 mid_entry = list_entry(tmp, struct
159 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
160 /* Mark other intransit requests as needing
161 retry so we do not immediately mark the
162 session bad again (ie after we reconnect
163 below) as they timeout too */
164 mid_entry->midState = MID_RETRY_NEEDED;
168 spin_unlock(&GlobalMid_Lock);
171 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
173 if(server->protocolType == IPV6) {
174 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
176 rc = ipv4_connect(&server->addr.sockAddr,
178 server->workstation_RFC1001_name);
181 set_current_state(TASK_INTERRUPTIBLE);
182 schedule_timeout(3 * HZ);
184 atomic_inc(&tcpSesReconnectCount);
185 spin_lock(&GlobalMid_Lock);
186 if(server->tcpStatus != CifsExiting)
187 server->tcpStatus = CifsGood;
188 server->sequence_number = 0;
189 spin_unlock(&GlobalMid_Lock);
190 /* atomic_set(&server->inFlight,0);*/
191 wake_up(&server->response_q);
199 0 not a transact2, or all data present
200 >0 transact2 with that much data missing
201 -EINVAL = invalid transact2
204 static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
206 struct smb_t2_rsp * pSMBt;
208 int data_in_this_rsp;
211 if(pSMB->Command != SMB_COM_TRANSACTION2)
214 /* check for plausible wct, bcc and t2 data and parm sizes */
215 /* check for parm and data offset going beyond end of smb */
216 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
217 cFYI(1,("invalid transact2 word count"));
221 pSMBt = (struct smb_t2_rsp *)pSMB;
223 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
224 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
226 remaining = total_data_size - data_in_this_rsp;
230 else if(remaining < 0) {
231 cFYI(1,("total data %d smaller than data in frame %d",
232 total_data_size, data_in_this_rsp));
235 cFYI(1,("missing %d bytes from transact2, check next response",
237 if(total_data_size > maxBufSize) {
238 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
239 total_data_size,maxBufSize));
246 static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
248 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
249 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
254 char * data_area_of_target;
255 char * data_area_of_buf2;
258 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
260 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
261 cFYI(1,("total data sizes of primary and secondary t2 differ"));
264 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
266 remaining = total_data_size - total_in_buf;
271 if(remaining == 0) /* nothing to do, ignore */
274 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
275 if(remaining < total_in_buf2) {
276 cFYI(1,("transact2 2nd response contains too much data"));
279 /* find end of first SMB data area */
280 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
281 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
282 /* validate target area */
284 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
285 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
287 data_area_of_target += total_in_buf;
289 /* copy second buffer into end of first buffer */
290 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
291 total_in_buf += total_in_buf2;
292 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
293 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
294 byte_count += total_in_buf2;
295 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
297 byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
298 byte_count += total_in_buf2;
300 /* BB also add check that we are not beyond maximum buffer size */
302 pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
304 if(remaining == total_in_buf2) {
305 cFYI(1,("found the last secondary response"));
306 return 0; /* we are done */
307 } else /* more responses to go */
313 cifs_demultiplex_thread(struct TCP_Server_Info *server)
316 unsigned int pdu_length, total_read;
317 struct smb_hdr *smb_buffer = NULL;
318 struct smb_hdr *bigbuf = NULL;
319 struct smb_hdr *smallbuf = NULL;
320 struct msghdr smb_msg;
322 struct socket *csocket = server->ssocket;
323 struct list_head *tmp;
324 struct cifsSesInfo *ses;
325 struct task_struct *task_to_wake = NULL;
326 struct mid_q_entry *mid_entry;
328 int isLargeBuf = FALSE;
333 allow_signal(SIGKILL);
334 current->flags |= PF_MEMALLOC;
335 server->tsk = current; /* save process info to wake at shutdown */
336 cFYI(1, ("Demultiplex PID: %d", current->pid));
337 write_lock(&GlobalSMBSeslock);
338 atomic_inc(&tcpSesAllocCount);
339 length = tcpSesAllocCount.counter;
340 write_unlock(&GlobalSMBSeslock);
342 mempool_resize(cifs_req_poolp,
343 length + cifs_min_rcv,
347 while (server->tcpStatus != CifsExiting) {
348 if (bigbuf == NULL) {
349 bigbuf = cifs_buf_get();
351 cERROR(1,("No memory for large SMB response"));
353 /* retry will check if exiting */
356 } else if(isLargeBuf) {
357 /* we are reusing a dirtry large buf, clear its start */
358 memset(bigbuf, 0, sizeof (struct smb_hdr));
361 if (smallbuf == NULL) {
362 smallbuf = cifs_small_buf_get();
363 if(smallbuf == NULL) {
364 cERROR(1,("No memory for SMB response"));
366 /* retry will check if exiting */
369 /* beginning of smb buffer is cleared in our buf_get */
370 } else /* if existing small buf clear beginning */
371 memset(smallbuf, 0, sizeof (struct smb_hdr));
375 smb_buffer = smallbuf;
376 iov.iov_base = smb_buffer;
378 smb_msg.msg_control = NULL;
379 smb_msg.msg_controllen = 0;
381 kernel_recvmsg(csocket, &smb_msg,
382 &iov, 1, 4, 0 /* BB see socket.h flags */);
384 if(server->tcpStatus == CifsExiting) {
386 } else if (server->tcpStatus == CifsNeedReconnect) {
387 cFYI(1,("Reconnect after server stopped responding"));
388 cifs_reconnect(server);
389 cFYI(1,("call to reconnect done"));
390 csocket = server->ssocket;
392 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
393 msleep(1); /* minimum sleep to prevent looping
394 allowing socket to clear and app threads to set
395 tcpStatus CifsNeedReconnect if server hung */
397 } else if (length <= 0) {
398 if(server->tcpStatus == CifsNew) {
399 cFYI(1,("tcp session abend after SMBnegprot"));
400 /* some servers kill the TCP session rather than
401 returning an SMB negprot error, in which
402 case reconnecting here is not going to help,
403 and so simply return error to mount */
406 if(length == -EINTR) {
407 cFYI(1,("cifsd thread killed"));
410 cFYI(1,("Reconnect after unexpected peek error %d",
412 cifs_reconnect(server);
413 csocket = server->ssocket;
414 wake_up(&server->response_q);
416 } else if (length < 4) {
418 ("Frame under four bytes received (%d bytes long)",
420 cifs_reconnect(server);
421 csocket = server->ssocket;
422 wake_up(&server->response_q);
426 /* the right amount was read from socket - 4 bytes */
428 pdu_length = ntohl(smb_buffer->smb_buf_length);
429 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
431 temp = (char *) smb_buffer;
432 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
434 } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
435 cFYI(1,("Good RFC 1002 session rsp"));
437 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
438 /* we get this from Windows 98 instead of
439 an error on SMB negprot response */
440 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
442 if(server->tcpStatus == CifsNew) {
443 /* if nack on negprot (rather than
444 ret of smb negprot error) reconnecting
445 not going to help, ret error to mount */
448 /* give server a second to
449 clean up before reconnect attempt */
451 /* always try 445 first on reconnect
452 since we get NACK on some if we ever
453 connected to port 139 (the NACK is
454 since we do not begin with RFC1001
455 session initialize frame) */
456 server->addr.sockAddr.sin_port =
458 cifs_reconnect(server);
459 csocket = server->ssocket;
460 wake_up(&server->response_q);
463 } else if (temp[0] != (char) 0) {
464 cERROR(1,("Unknown RFC 1002 frame"));
465 cifs_dump_mem(" Received Data: ", temp, length);
466 cifs_reconnect(server);
467 csocket = server->ssocket;
471 /* else we have an SMB response */
472 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
473 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
474 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
475 length, pdu_length+4));
476 cifs_reconnect(server);
477 csocket = server->ssocket;
478 wake_up(&server->response_q);
485 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
487 memcpy(bigbuf, smallbuf, 4);
491 iov.iov_base = 4 + (char *)smb_buffer;
492 iov.iov_len = pdu_length;
493 for (total_read = 0; total_read < pdu_length;
494 total_read += length) {
495 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
496 pdu_length - total_read, 0);
497 if((server->tcpStatus == CifsExiting) ||
498 (length == -EINTR)) {
502 } else if (server->tcpStatus == CifsNeedReconnect) {
503 cifs_reconnect(server);
504 csocket = server->ssocket;
505 /* Reconnect wakes up rspns q */
506 /* Now we will reread sock */
509 } else if ((length == -ERESTARTSYS) ||
510 (length == -EAGAIN)) {
511 msleep(1); /* minimum sleep to prevent looping,
512 allowing socket to clear and app
513 threads to set tcpStatus
514 CifsNeedReconnect if server hung*/
516 } else if (length <= 0) {
517 cERROR(1,("Received no data, expecting %d",
518 pdu_length - total_read));
519 cifs_reconnect(server);
520 csocket = server->ssocket;
527 else if(reconnect == 1)
530 length += 4; /* account for rfc1002 hdr */
533 dump_smb(smb_buffer, length);
534 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
535 cERROR(1, ("Bad SMB Received "));
541 spin_lock(&GlobalMid_Lock);
542 list_for_each(tmp, &server->pending_mid_q) {
543 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
545 if ((mid_entry->mid == smb_buffer->Mid) &&
546 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
547 (mid_entry->command == smb_buffer->Command)) {
548 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
549 /* We have a multipart transact2 resp */
551 if(mid_entry->resp_buf) {
552 /* merge response - fix up 1st*/
553 if(coalesce_t2(smb_buffer,
554 mid_entry->resp_buf)) {
557 /* all parts received */
562 cERROR(1,("1st trans2 resp needs bigbuf"));
563 /* BB maybe we can fix this up, switch
564 to already allocated large buffer? */
566 /* Have first buffer */
567 mid_entry->resp_buf =
569 mid_entry->largeBuf = 1;
575 mid_entry->resp_buf = smb_buffer;
577 mid_entry->largeBuf = 1;
579 mid_entry->largeBuf = 0;
581 task_to_wake = mid_entry->tsk;
582 mid_entry->midState = MID_RESPONSE_RECEIVED;
586 spin_unlock(&GlobalMid_Lock);
588 /* Was previous buf put in mpx struct for multi-rsp? */
590 /* smb buffer will be freed by user thread */
596 wake_up_process(task_to_wake);
597 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
598 && (isMultiRsp == FALSE)) {
599 cERROR(1, ("No task to wake, unknown frame rcvd!"));
600 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
602 } /* end while !EXITING */
604 spin_lock(&GlobalMid_Lock);
605 server->tcpStatus = CifsExiting;
607 /* check if we have blocked requests that need to free */
608 /* Note that cifs_max_pending is normally 50, but
609 can be set at module install time to as little as two */
610 if(atomic_read(&server->inFlight) >= cifs_max_pending)
611 atomic_set(&server->inFlight, cifs_max_pending - 1);
612 /* We do not want to set the max_pending too low or we
613 could end up with the counter going negative */
614 spin_unlock(&GlobalMid_Lock);
615 /* Although there should not be any requests blocked on
616 this queue it can not hurt to be paranoid and try to wake up requests
617 that may haven been blocked when more than 50 at time were on the wire
618 to the same server - they now will see the session is in exit state
619 and get out of SendReceive. */
620 wake_up_all(&server->request_q);
621 /* give those requests time to exit */
624 if(server->ssocket) {
625 sock_release(csocket);
626 server->ssocket = NULL;
628 /* buffer usuallly freed in free_mid - need to free it here on exit */
630 cifs_buf_release(bigbuf);
631 if (smallbuf != NULL)
632 cifs_small_buf_release(smallbuf);
634 read_lock(&GlobalSMBSeslock);
635 if (list_empty(&server->pending_mid_q)) {
636 /* loop through server session structures attached to this and
638 list_for_each(tmp, &GlobalSMBSessionList) {
640 list_entry(tmp, struct cifsSesInfo,
642 if (ses->server == server) {
643 ses->status = CifsExiting;
647 read_unlock(&GlobalSMBSeslock);
649 /* although we can not zero the server struct pointer yet,
650 since there are active requests which may depnd on them,
651 mark the corresponding SMB sessions as exiting too */
652 list_for_each(tmp, &GlobalSMBSessionList) {
653 ses = list_entry(tmp, struct cifsSesInfo,
655 if (ses->server == server) {
656 ses->status = CifsExiting;
660 spin_lock(&GlobalMid_Lock);
661 list_for_each(tmp, &server->pending_mid_q) {
662 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
663 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
665 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
666 task_to_wake = mid_entry->tsk;
668 wake_up_process(task_to_wake);
672 spin_unlock(&GlobalMid_Lock);
673 read_unlock(&GlobalSMBSeslock);
674 /* 1/8th of sec is more than enough time for them to exit */
678 if (list_empty(&server->pending_mid_q)) {
679 /* mpx threads have not exited yet give them
680 at least the smb send timeout time for long ops */
681 /* due to delays on oplock break requests, we need
682 to wait at least 45 seconds before giving up
683 on a request getting a response and going ahead
685 cFYI(1, ("Wait for exit from demultiplex thread"));
687 /* if threads still have not exited they are probably never
688 coming home not much else we can do but free the memory */
691 write_lock(&GlobalSMBSeslock);
692 atomic_dec(&tcpSesAllocCount);
693 length = tcpSesAllocCount.counter;
695 /* last chance to mark ses pointers invalid
696 if there are any pointing to this (e.g
697 if a crazy root user tried to kill cifsd
698 kernel thread explicitly this might happen) */
699 list_for_each(tmp, &GlobalSMBSessionList) {
700 ses = list_entry(tmp, struct cifsSesInfo,
702 if (ses->server == server) {
706 write_unlock(&GlobalSMBSeslock);
710 mempool_resize(cifs_req_poolp,
711 length + cifs_min_rcv,
720 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
724 unsigned int temp_len, i, j;
730 memset(vol->source_rfc1001_name,0x20,15);
731 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
732 /* does not have to be a perfect mapping since the field is
733 informational, only used for servers that do not support
734 port 445 and it can be overridden at mount time */
735 vol->source_rfc1001_name[i] =
736 toupper(system_utsname.nodename[i]);
738 vol->source_rfc1001_name[15] = 0;
740 vol->linux_uid = current->uid; /* current->euid instead? */
741 vol->linux_gid = current->gid;
742 vol->dir_mode = S_IRWXUGO;
743 /* 2767 perms indicate mandatory locking support */
744 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
746 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
752 if(strncmp(options,"sep=",4) == 0) {
753 if(options[4] != 0) {
754 separator[0] = options[4];
757 cFYI(1,("Null separator not allowed"));
761 while ((data = strsep(&options, separator)) != NULL) {
764 if ((value = strchr(data, '=')) != NULL)
767 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
769 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
771 } else if (strnicmp(data, "user", 4) == 0) {
772 if (!value || !*value) {
774 "CIFS: invalid or missing username\n");
775 return 1; /* needs_arg; */
777 if (strnlen(value, 200) < 200) {
778 vol->username = value;
780 printk(KERN_WARNING "CIFS: username too long\n");
783 } else if (strnicmp(data, "pass", 4) == 0) {
785 vol->password = NULL;
787 } else if(value[0] == 0) {
788 /* check if string begins with double comma
789 since that would mean the password really
790 does start with a comma, and would not
791 indicate an empty string */
792 if(value[1] != separator[0]) {
793 vol->password = NULL;
797 temp_len = strlen(value);
798 /* removed password length check, NTLM passwords
799 can be arbitrarily long */
801 /* if comma in password, the string will be
802 prematurely null terminated. Commas in password are
803 specified across the cifs mount interface by a double
804 comma ie ,, and a comma used as in other cases ie ','
805 as a parameter delimiter/separator is single and due
806 to the strsep above is temporarily zeroed. */
808 /* NB: password legally can have multiple commas and
809 the only illegal character in a password is null */
811 if ((value[temp_len] == 0) &&
812 (value[temp_len+1] == separator[0])) {
814 value[temp_len] = separator[0];
815 temp_len+=2; /* move after the second comma */
816 while(value[temp_len] != 0) {
817 if (value[temp_len] == separator[0]) {
818 if (value[temp_len+1] ==
820 /* skip second comma */
823 /* single comma indicating start
830 if(value[temp_len] == 0) {
834 /* point option to start of next parm */
835 options = value + temp_len + 1;
837 /* go from value to value + temp_len condensing
838 double commas to singles. Note that this ends up
839 allocating a few bytes too many, which is ok */
840 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
841 if(vol->password == NULL) {
842 printk("CIFS: no memory for pass\n");
845 for(i=0,j=0;i<temp_len;i++,j++) {
846 vol->password[j] = value[i];
847 if(value[i] == separator[0]
848 && value[i+1] == separator[0]) {
849 /* skip second comma */
853 vol->password[j] = 0;
855 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
856 if(vol->password == NULL) {
857 printk("CIFS: no memory for pass\n");
860 strcpy(vol->password, value);
862 } else if (strnicmp(data, "ip", 2) == 0) {
863 if (!value || !*value) {
865 } else if (strnlen(value, 35) < 35) {
868 printk(KERN_WARNING "CIFS: ip address too long\n");
871 } else if ((strnicmp(data, "unc", 3) == 0)
872 || (strnicmp(data, "target", 6) == 0)
873 || (strnicmp(data, "path", 4) == 0)) {
874 if (!value || !*value) {
876 "CIFS: invalid path to network resource\n");
877 return 1; /* needs_arg; */
879 if ((temp_len = strnlen(value, 300)) < 300) {
880 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
883 strcpy(vol->UNC,value);
884 if (strncmp(vol->UNC, "//", 2) == 0) {
887 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
889 "CIFS: UNC Path does not begin with // or \\\\ \n");
893 printk(KERN_WARNING "CIFS: UNC name too long\n");
896 } else if ((strnicmp(data, "domain", 3) == 0)
897 || (strnicmp(data, "workgroup", 5) == 0)) {
898 if (!value || !*value) {
899 printk(KERN_WARNING "CIFS: invalid domain name\n");
900 return 1; /* needs_arg; */
902 /* BB are there cases in which a comma can be valid in
903 a domain name and need special handling? */
904 if (strnlen(value, 65) < 65) {
905 vol->domainname = value;
906 cFYI(1, ("Domain name set"));
908 printk(KERN_WARNING "CIFS: domain name too long\n");
911 } else if (strnicmp(data, "iocharset", 9) == 0) {
912 if (!value || !*value) {
913 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
914 return 1; /* needs_arg; */
916 if (strnlen(value, 65) < 65) {
917 if(strnicmp(value,"default",7))
918 vol->iocharset = value;
919 /* if iocharset not set load_nls_default used by caller */
920 cFYI(1, ("iocharset set to %s",value));
922 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
925 } else if (strnicmp(data, "uid", 3) == 0) {
926 if (value && *value) {
928 simple_strtoul(value, &value, 0);
930 } else if (strnicmp(data, "gid", 3) == 0) {
931 if (value && *value) {
933 simple_strtoul(value, &value, 0);
935 } else if (strnicmp(data, "file_mode", 4) == 0) {
936 if (value && *value) {
938 simple_strtoul(value, &value, 0);
940 } else if (strnicmp(data, "dir_mode", 4) == 0) {
941 if (value && *value) {
943 simple_strtoul(value, &value, 0);
945 } else if (strnicmp(data, "dirmode", 4) == 0) {
946 if (value && *value) {
948 simple_strtoul(value, &value, 0);
950 } else if (strnicmp(data, "port", 4) == 0) {
951 if (value && *value) {
953 simple_strtoul(value, &value, 0);
955 } else if (strnicmp(data, "rsize", 5) == 0) {
956 if (value && *value) {
958 simple_strtoul(value, &value, 0);
960 } else if (strnicmp(data, "wsize", 5) == 0) {
961 if (value && *value) {
963 simple_strtoul(value, &value, 0);
965 } else if (strnicmp(data, "sockopt", 5) == 0) {
966 if (value && *value) {
968 simple_strtoul(value, &value, 0);
970 } else if (strnicmp(data, "netbiosname", 4) == 0) {
971 if (!value || !*value || (*value == ' ')) {
972 cFYI(1,("invalid (empty) netbiosname specified"));
974 memset(vol->source_rfc1001_name,0x20,15);
976 /* BB are there cases in which a comma can be
977 valid in this workstation netbios name (and need
978 special handling)? */
980 /* We do not uppercase netbiosname for user */
984 vol->source_rfc1001_name[i] = value[i];
986 /* The string has 16th byte zero still from
987 set at top of the function */
988 if((i==15) && (value[i] != 0))
989 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
991 } else if (strnicmp(data, "credentials", 4) == 0) {
993 } else if (strnicmp(data, "version", 3) == 0) {
995 } else if (strnicmp(data, "guest",5) == 0) {
997 } else if (strnicmp(data, "rw", 2) == 0) {
999 } else if ((strnicmp(data, "suid", 4) == 0) ||
1000 (strnicmp(data, "nosuid", 6) == 0) ||
1001 (strnicmp(data, "exec", 4) == 0) ||
1002 (strnicmp(data, "noexec", 6) == 0) ||
1003 (strnicmp(data, "nodev", 5) == 0) ||
1004 (strnicmp(data, "noauto", 6) == 0) ||
1005 (strnicmp(data, "dev", 3) == 0)) {
1006 /* The mount tool or mount.cifs helper (if present)
1007 uses these opts to set flags, and the flags are read
1008 by the kernel vfs layer before we get here (ie
1009 before read super) so there is no point trying to
1010 parse these options again and set anything and it
1011 is ok to just ignore them */
1013 } else if (strnicmp(data, "ro", 2) == 0) {
1015 } else if (strnicmp(data, "hard", 4) == 0) {
1017 } else if (strnicmp(data, "soft", 4) == 0) {
1019 } else if (strnicmp(data, "perm", 4) == 0) {
1021 } else if (strnicmp(data, "noperm", 6) == 0) {
1023 } else if (strnicmp(data, "mapchars", 8) == 0) {
1025 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1027 } else if (strnicmp(data, "setuids", 7) == 0) {
1029 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1031 } else if (strnicmp(data, "nohard", 6) == 0) {
1033 } else if (strnicmp(data, "nosoft", 6) == 0) {
1035 } else if (strnicmp(data, "nointr", 6) == 0) {
1037 } else if (strnicmp(data, "intr", 4) == 0) {
1039 } else if (strnicmp(data, "serverino",7) == 0) {
1040 vol->server_ino = 1;
1041 } else if (strnicmp(data, "noserverino",9) == 0) {
1042 vol->server_ino = 0;
1043 } else if (strnicmp(data, "acl",3) == 0) {
1044 vol->no_psx_acl = 0;
1045 } else if (strnicmp(data, "noacl",5) == 0) {
1046 vol->no_psx_acl = 1;
1047 } else if (strnicmp(data, "direct",6) == 0) {
1049 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1051 } else if (strnicmp(data, "in6_addr",8) == 0) {
1052 if (!value || !*value) {
1053 vol->in6_addr = NULL;
1054 } else if (strnlen(value, 49) == 48) {
1055 vol->in6_addr = value;
1057 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1060 } else if (strnicmp(data, "noac", 4) == 0) {
1061 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1063 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1065 if (vol->UNC == NULL) {
1066 if(devname == NULL) {
1067 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1070 if ((temp_len = strnlen(devname, 300)) < 300) {
1071 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1072 if(vol->UNC == NULL)
1074 strcpy(vol->UNC,devname);
1075 if (strncmp(vol->UNC, "//", 2) == 0) {
1078 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1079 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1083 printk(KERN_WARNING "CIFS: UNC name too long\n");
1087 if(vol->UNCip == NULL)
1088 vol->UNCip = &vol->UNC[2];
1093 static struct cifsSesInfo *
1094 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1095 struct in6_addr *target_ip6_addr,
1096 char *userName, struct TCP_Server_Info **psrvTcp)
1098 struct list_head *tmp;
1099 struct cifsSesInfo *ses;
1101 read_lock(&GlobalSMBSeslock);
1103 list_for_each(tmp, &GlobalSMBSessionList) {
1104 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1106 if((target_ip_addr &&
1107 (ses->server->addr.sockAddr.sin_addr.s_addr
1108 == target_ip_addr->s_addr)) || (target_ip6_addr
1109 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1110 target_ip6_addr,sizeof(*target_ip6_addr)))){
1111 /* BB lock server and tcp session and increment use count here?? */
1112 *psrvTcp = ses->server; /* found a match on the TCP session */
1113 /* BB check if reconnection needed */
1115 (ses->userName, userName,
1116 MAX_USERNAME_SIZE) == 0){
1117 read_unlock(&GlobalSMBSeslock);
1118 return ses; /* found exact match on both tcp and SMB sessions */
1122 /* else tcp and smb sessions need reconnection */
1124 read_unlock(&GlobalSMBSeslock);
1128 static struct cifsTconInfo *
1129 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1131 struct list_head *tmp;
1132 struct cifsTconInfo *tcon;
1134 read_lock(&GlobalSMBSeslock);
1135 list_for_each(tmp, &GlobalTreeConnectionList) {
1136 cFYI(1, ("Next tcon - "));
1137 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1139 if (tcon->ses->server) {
1141 (" old ip addr: %x == new ip %x ?",
1142 tcon->ses->server->addr.sockAddr.sin_addr.
1143 s_addr, new_target_ip_addr));
1144 if (tcon->ses->server->addr.sockAddr.sin_addr.
1145 s_addr == new_target_ip_addr) {
1146 /* BB lock tcon and server and tcp session and increment use count here? */
1147 /* found a match on the TCP session */
1148 /* BB check if reconnection needed */
1149 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1150 tcon->treeName, uncName));
1152 (tcon->treeName, uncName,
1153 MAX_TREE_SIZE) == 0) {
1155 ("Matched UNC, old user: %s == new: %s ?",
1156 tcon->treeName, uncName));
1158 (tcon->ses->userName,
1160 MAX_USERNAME_SIZE) == 0) {
1161 read_unlock(&GlobalSMBSeslock);
1162 return tcon;/* also matched user (smb session)*/
1169 read_unlock(&GlobalSMBSeslock);
1174 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1175 const char *old_path, const struct nls_table *nls_codepage,
1178 unsigned char *referrals = NULL;
1179 unsigned int num_referrals;
1182 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1183 &num_referrals, &referrals, remap);
1185 /* BB Add in code to: if valid refrl, if not ip address contact
1186 the helper that resolves tcp names, mount to it, try to
1187 tcon to it unmount it if fail */
1196 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1197 const char *old_path, const struct nls_table *nls_codepage,
1198 unsigned int *pnum_referrals,
1199 unsigned char ** preferrals, int remap)
1204 *pnum_referrals = 0;
1206 if (pSesInfo->ipc_tid == 0) {
1207 temp_unc = kmalloc(2 /* for slashes */ +
1208 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1209 + 1 + 4 /* slash IPC$ */ + 2,
1211 if (temp_unc == NULL)
1215 strcpy(temp_unc + 2, pSesInfo->serverName);
1216 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1217 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1219 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1223 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1224 pnum_referrals, nls_codepage, remap);
1229 /* See RFC1001 section 14 on representation of Netbios names */
1230 static void rfc1002mangle(char * target,char * source, unsigned int length)
1234 for(i=0,j=0;i<(length);i++) {
1235 /* mask a nibble at a time and encode */
1236 target[j] = 'A' + (0x0F & (source[i] >> 4));
1237 target[j+1] = 'A' + (0x0F & source[i]);
1245 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1246 char * netbios_name)
1250 __be16 orig_port = 0;
1252 if(*csocket == NULL) {
1253 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1255 cERROR(1, ("Error %d creating socket",rc));
1259 /* BB other socket options to set KEEPALIVE, NODELAY? */
1260 cFYI(1,("Socket created"));
1261 (*csocket)->sk->sk_allocation = GFP_NOFS;
1265 psin_server->sin_family = AF_INET;
1266 if(psin_server->sin_port) { /* user overrode default port */
1267 rc = (*csocket)->ops->connect(*csocket,
1268 (struct sockaddr *) psin_server,
1269 sizeof (struct sockaddr_in),0);
1275 /* save original port so we can retry user specified port
1276 later if fall back ports fail this time */
1277 orig_port = psin_server->sin_port;
1279 /* do not retry on the same port we just failed on */
1280 if(psin_server->sin_port != htons(CIFS_PORT)) {
1281 psin_server->sin_port = htons(CIFS_PORT);
1283 rc = (*csocket)->ops->connect(*csocket,
1284 (struct sockaddr *) psin_server,
1285 sizeof (struct sockaddr_in),0);
1291 psin_server->sin_port = htons(RFC1001_PORT);
1292 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1293 psin_server, sizeof (struct sockaddr_in),0);
1298 /* give up here - unless we want to retry on different
1299 protocol families some day */
1302 psin_server->sin_port = orig_port;
1303 cFYI(1,("Error %d connecting to server via ipv4",rc));
1304 sock_release(*csocket);
1308 /* Eventually check for other socket options to change from
1309 the default. sock_setsockopt not used because it expects
1310 user space buffer */
1311 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1313 /* send RFC1001 sessinit */
1315 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1316 /* some servers require RFC1001 sessinit before sending
1317 negprot - BB check reconnection in case where second
1318 sessinit is sent but no second negprot */
1319 struct rfc1002_session_packet * ses_init_buf;
1320 struct smb_hdr * smb_buf;
1321 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1323 ses_init_buf->trailer.session_req.called_len = 32;
1324 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1325 DEFAULT_CIFS_CALLED_NAME,16);
1326 ses_init_buf->trailer.session_req.calling_len = 32;
1327 /* calling name ends in null (byte 16) from old smb
1329 if(netbios_name && (netbios_name[0] !=0)) {
1330 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1333 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1334 "LINUX_CIFS_CLNT",16);
1336 ses_init_buf->trailer.session_req.scope1 = 0;
1337 ses_init_buf->trailer.session_req.scope2 = 0;
1338 smb_buf = (struct smb_hdr *)ses_init_buf;
1339 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1340 smb_buf->smb_buf_length = 0x81000044;
1341 rc = smb_send(*csocket, smb_buf, 0x44,
1342 (struct sockaddr *)psin_server);
1343 kfree(ses_init_buf);
1345 /* else the negprot may still work without this
1346 even though malloc failed */
1354 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1358 __be16 orig_port = 0;
1360 if(*csocket == NULL) {
1361 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1363 cERROR(1, ("Error %d creating ipv6 socket",rc));
1367 /* BB other socket options to set KEEPALIVE, NODELAY? */
1368 cFYI(1,("ipv6 Socket created"));
1369 (*csocket)->sk->sk_allocation = GFP_NOFS;
1373 psin_server->sin6_family = AF_INET6;
1375 if(psin_server->sin6_port) { /* user overrode default port */
1376 rc = (*csocket)->ops->connect(*csocket,
1377 (struct sockaddr *) psin_server,
1378 sizeof (struct sockaddr_in6),0);
1384 /* save original port so we can retry user specified port
1385 later if fall back ports fail this time */
1387 orig_port = psin_server->sin6_port;
1388 /* do not retry on the same port we just failed on */
1389 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1390 psin_server->sin6_port = htons(CIFS_PORT);
1392 rc = (*csocket)->ops->connect(*csocket,
1393 (struct sockaddr *) psin_server,
1394 sizeof (struct sockaddr_in6),0);
1400 psin_server->sin6_port = htons(RFC1001_PORT);
1401 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1402 psin_server, sizeof (struct sockaddr_in6),0);
1407 /* give up here - unless we want to retry on different
1408 protocol families some day */
1411 psin_server->sin6_port = orig_port;
1412 cFYI(1,("Error %d connecting to server via ipv6",rc));
1413 sock_release(*csocket);
1417 /* Eventually check for other socket options to change from
1418 the default. sock_setsockopt not used because it expects
1419 user space buffer */
1420 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1426 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1427 char *mount_data, const char *devname)
1431 int address_type = AF_INET;
1432 struct socket *csocket = NULL;
1433 struct sockaddr_in sin_server;
1434 struct sockaddr_in6 sin_server6;
1435 struct smb_vol volume_info;
1436 struct cifsSesInfo *pSesInfo = NULL;
1437 struct cifsSesInfo *existingCifsSes = NULL;
1438 struct cifsTconInfo *tcon = NULL;
1439 struct TCP_Server_Info *srvTcp = NULL;
1443 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1445 memset(&volume_info,0,sizeof(struct smb_vol));
1446 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1448 kfree(volume_info.UNC);
1449 if(volume_info.password)
1450 kfree(volume_info.password);
1455 if (volume_info.username) {
1456 /* BB fixme parse for domain name here */
1457 cFYI(1, ("Username: %s ", volume_info.username));
1460 cifserror("No username specified ");
1461 /* In userspace mount helper we can get user name from alternate
1462 locations such as env variables and files on disk */
1464 kfree(volume_info.UNC);
1465 if(volume_info.password)
1466 kfree(volume_info.password);
1471 if (volume_info.UNCip && volume_info.UNC) {
1472 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1475 /* not ipv4 address, try ipv6 */
1476 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1478 address_type = AF_INET6;
1480 address_type = AF_INET;
1484 /* we failed translating address */
1486 kfree(volume_info.UNC);
1487 if(volume_info.password)
1488 kfree(volume_info.password);
1493 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1496 } else if (volume_info.UNCip){
1497 /* BB using ip addr as server name connect to the DFS root below */
1498 cERROR(1,("Connecting to DFS root not implemented yet"));
1500 kfree(volume_info.UNC);
1501 if(volume_info.password)
1502 kfree(volume_info.password);
1505 } else /* which servers DFS root would we conect to */ {
1507 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1509 kfree(volume_info.UNC);
1510 if(volume_info.password)
1511 kfree(volume_info.password);
1516 /* this is needed for ASCII cp to Unicode converts */
1517 if(volume_info.iocharset == NULL) {
1518 cifs_sb->local_nls = load_nls_default();
1519 /* load_nls_default can not return null */
1521 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1522 if(cifs_sb->local_nls == NULL) {
1523 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1525 kfree(volume_info.UNC);
1526 if(volume_info.password)
1527 kfree(volume_info.password);
1533 if(address_type == AF_INET)
1534 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1535 NULL /* no ipv6 addr */,
1536 volume_info.username, &srvTcp);
1537 else if(address_type == AF_INET6)
1538 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1539 &sin_server6.sin6_addr,
1540 volume_info.username, &srvTcp);
1543 kfree(volume_info.UNC);
1544 if(volume_info.password)
1545 kfree(volume_info.password);
1552 cFYI(1, ("Existing tcp session with server found "));
1553 } else { /* create socket */
1554 if(volume_info.port)
1555 sin_server.sin_port = htons(volume_info.port);
1557 sin_server.sin_port = 0;
1558 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1561 ("Error connecting to IPv4 socket. Aborting operation"));
1563 sock_release(csocket);
1565 kfree(volume_info.UNC);
1566 if(volume_info.password)
1567 kfree(volume_info.password);
1572 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1573 if (srvTcp == NULL) {
1575 sock_release(csocket);
1577 kfree(volume_info.UNC);
1578 if(volume_info.password)
1579 kfree(volume_info.password);
1583 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1584 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1585 atomic_set(&srvTcp->inFlight,0);
1586 /* BB Add code for ipv6 case too */
1587 srvTcp->ssocket = csocket;
1588 srvTcp->protocolType = IPV4;
1589 init_waitqueue_head(&srvTcp->response_q);
1590 init_waitqueue_head(&srvTcp->request_q);
1591 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1592 /* at this point we are the only ones with the pointer
1593 to the struct since the kernel thread not created yet
1594 so no need to spinlock this init of tcpStatus */
1595 srvTcp->tcpStatus = CifsNew;
1596 init_MUTEX(&srvTcp->tcpSem);
1597 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1598 CLONE_FS | CLONE_FILES | CLONE_VM);
1601 sock_release(csocket);
1603 kfree(volume_info.UNC);
1604 if(volume_info.password)
1605 kfree(volume_info.password);
1610 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1611 srvTcp->sequence_number = 0;
1615 if (existingCifsSes) {
1616 pSesInfo = existingCifsSes;
1617 cFYI(1, ("Existing smb sess found "));
1618 if(volume_info.password)
1619 kfree(volume_info.password);
1620 /* volume_info.UNC freed at end of function */
1622 cFYI(1, ("Existing smb sess not found "));
1623 pSesInfo = sesInfoAlloc();
1624 if (pSesInfo == NULL)
1627 pSesInfo->server = srvTcp;
1628 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1629 NIPQUAD(sin_server.sin_addr.s_addr));
1633 /* volume_info.password freed at unmount */
1634 if (volume_info.password)
1635 pSesInfo->password = volume_info.password;
1636 if (volume_info.username)
1637 strncpy(pSesInfo->userName,
1638 volume_info.username,MAX_USERNAME_SIZE);
1639 if (volume_info.domainname)
1640 strncpy(pSesInfo->domainName,
1641 volume_info.domainname,MAX_USERNAME_SIZE);
1642 pSesInfo->linux_uid = volume_info.linux_uid;
1643 down(&pSesInfo->sesSem);
1644 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1645 up(&pSesInfo->sesSem);
1647 atomic_inc(&srvTcp->socketUseCount);
1649 if(volume_info.password)
1650 kfree(volume_info.password);
1653 /* search for existing tcon to this server share */
1655 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1656 cifs_sb->rsize = volume_info.rsize;
1658 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1659 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1660 cifs_sb->wsize = volume_info.wsize;
1662 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1663 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1664 cifs_sb->rsize = PAGE_CACHE_SIZE;
1665 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1667 cifs_sb->mnt_uid = volume_info.linux_uid;
1668 cifs_sb->mnt_gid = volume_info.linux_gid;
1669 cifs_sb->mnt_file_mode = volume_info.file_mode;
1670 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1671 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1673 if(volume_info.noperm)
1674 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1675 if(volume_info.setuids)
1676 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1677 if(volume_info.server_ino)
1678 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1679 if(volume_info.remap)
1680 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1681 if(volume_info.no_xattr)
1682 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1683 if(volume_info.direct_io) {
1684 cERROR(1,("mounting share using direct i/o"));
1685 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1689 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1690 volume_info.username);
1692 cFYI(1, ("Found match on UNC path "));
1693 /* we can have only one retry value for a connection
1694 to a share so for resources mounted more than once
1695 to the same server share the last value passed in
1696 for the retry flag is used */
1697 tcon->retry = volume_info.retry;
1699 tcon = tconInfoAlloc();
1703 /* check for null share name ie connect to dfs root */
1705 /* BB check if this works for exactly length three strings */
1706 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1707 && (strchr(volume_info.UNC + 3, '/') ==
1709 rc = connect_to_dfs_path(xid, pSesInfo,
1710 "", cifs_sb->local_nls,
1711 cifs_sb->mnt_cifs_flags &
1712 CIFS_MOUNT_MAP_SPECIAL_CHR);
1714 kfree(volume_info.UNC);
1718 rc = CIFSTCon(xid, pSesInfo,
1720 tcon, cifs_sb->local_nls);
1721 cFYI(1, ("CIFS Tcon rc = %d", rc));
1724 atomic_inc(&pSesInfo->inUse);
1725 tcon->retry = volume_info.retry;
1731 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1732 sb->s_maxbytes = (u64) 1 << 63;
1734 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1737 sb->s_time_gran = 100;
1739 /* on error free sesinfo and tcon struct if needed */
1741 /* if session setup failed, use count is zero but
1742 we still need to free cifsd thread */
1743 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1744 spin_lock(&GlobalMid_Lock);
1745 srvTcp->tcpStatus = CifsExiting;
1746 spin_unlock(&GlobalMid_Lock);
1748 send_sig(SIGKILL,srvTcp->tsk,1);
1750 /* If find_unc succeeded then rc == 0 so we can not end */
1751 if (tcon) /* up accidently freeing someone elses tcon struct */
1753 if (existingCifsSes == NULL) {
1755 if ((pSesInfo->server) &&
1756 (pSesInfo->status == CifsGood)) {
1758 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1759 /* if the socketUseCount is now zero */
1760 if((temp_rc == -ESHUTDOWN) &&
1761 (pSesInfo->server->tsk))
1762 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1764 cFYI(1, ("No session or bad tcon"));
1765 sesInfoFree(pSesInfo);
1766 /* pSesInfo = NULL; */
1770 atomic_inc(&tcon->useCount);
1771 cifs_sb->tcon = tcon;
1772 tcon->ses = pSesInfo;
1774 /* do not care if following two calls succeed - informational only */
1775 CIFSSMBQFSDeviceInfo(xid, tcon);
1776 CIFSSMBQFSAttributeInfo(xid, tcon);
1777 if (tcon->ses->capabilities & CAP_UNIX) {
1778 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1779 if(!volume_info.no_psx_acl) {
1780 if(CIFS_UNIX_POSIX_ACL_CAP &
1781 le64_to_cpu(tcon->fsUnixInfo.Capability))
1782 cFYI(1,("server negotiated posix acl support"));
1783 sb->s_flags |= MS_POSIXACL;
1789 /* volume_info.password is freed above when existing session found
1790 (in which case it is not needed anymore) but when new sesion is created
1791 the password ptr is put in the new session structure (in which case the
1792 password will be freed at unmount time) */
1794 kfree(volume_info.UNC);
1800 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1801 char session_key[CIFS_SESSION_KEY_SIZE],
1802 const struct nls_table *nls_codepage)
1804 struct smb_hdr *smb_buffer;
1805 struct smb_hdr *smb_buffer_response;
1806 SESSION_SETUP_ANDX *pSMB;
1807 SESSION_SETUP_ANDX *pSMBr;
1812 int remaining_words = 0;
1813 int bytes_returned = 0;
1818 cFYI(1, ("In sesssetup "));
1821 user = ses->userName;
1822 domain = ses->domainName;
1823 smb_buffer = cifs_buf_get();
1824 if (smb_buffer == NULL) {
1827 smb_buffer_response = smb_buffer;
1828 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1830 /* send SMBsessionSetup here */
1831 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1832 NULL /* no tCon exists yet */ , 13 /* wct */ );
1834 pSMB->req_no_secext.AndXCommand = 0xFF;
1835 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1836 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1838 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1839 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1841 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1842 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1843 if (ses->capabilities & CAP_UNICODE) {
1844 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1845 capabilities |= CAP_UNICODE;
1847 if (ses->capabilities & CAP_STATUS32) {
1848 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1849 capabilities |= CAP_STATUS32;
1851 if (ses->capabilities & CAP_DFS) {
1852 smb_buffer->Flags2 |= SMBFLG2_DFS;
1853 capabilities |= CAP_DFS;
1855 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1857 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1858 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1860 pSMB->req_no_secext.CaseSensitivePasswordLength =
1861 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1862 bcc_ptr = pByteArea(smb_buffer);
1863 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1864 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1865 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1866 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1868 if (ses->capabilities & CAP_UNICODE) {
1869 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1874 bytes_returned = 0; /* skill null user */
1877 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1879 /* convert number of 16 bit words to bytes */
1880 bcc_ptr += 2 * bytes_returned;
1881 bcc_ptr += 2; /* trailing null */
1884 cifs_strtoUCS((wchar_t *) bcc_ptr,
1885 "CIFS_LINUX_DOM", 32, nls_codepage);
1888 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1890 bcc_ptr += 2 * bytes_returned;
1893 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1895 bcc_ptr += 2 * bytes_returned;
1897 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1899 bcc_ptr += 2 * bytes_returned;
1902 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1904 bcc_ptr += 2 * bytes_returned;
1908 strncpy(bcc_ptr, user, 200);
1909 bcc_ptr += strnlen(user, 200);
1913 if (domain == NULL) {
1914 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1915 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1917 strncpy(bcc_ptr, domain, 64);
1918 bcc_ptr += strnlen(domain, 64);
1922 strcpy(bcc_ptr, "Linux version ");
1923 bcc_ptr += strlen("Linux version ");
1924 strcpy(bcc_ptr, system_utsname.release);
1925 bcc_ptr += strlen(system_utsname.release) + 1;
1926 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1927 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1929 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1930 smb_buffer->smb_buf_length += count;
1931 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1933 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1934 &bytes_returned, 1);
1936 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1937 } else if ((smb_buffer_response->WordCount == 3)
1938 || (smb_buffer_response->WordCount == 4)) {
1939 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1940 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1941 if (action & GUEST_LOGIN)
1942 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1943 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1944 cFYI(1, ("UID = %d ", ses->Suid));
1945 /* response can have either 3 or 4 word count - Samba sends 3 */
1946 bcc_ptr = pByteArea(smb_buffer_response);
1947 if ((pSMBr->resp.hdr.WordCount == 3)
1948 || ((pSMBr->resp.hdr.WordCount == 4)
1949 && (blob_len < pSMBr->resp.ByteCount))) {
1950 if (pSMBr->resp.hdr.WordCount == 4)
1951 bcc_ptr += blob_len;
1953 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1954 if ((long) (bcc_ptr) % 2) {
1956 (BCC(smb_buffer_response) - 1) /2;
1957 bcc_ptr++; /* Unicode strings must be word aligned */
1960 BCC(smb_buffer_response) / 2;
1963 UniStrnlen((wchar_t *) bcc_ptr,
1964 remaining_words - 1);
1965 /* We look for obvious messed up bcc or strings in response so we do not go off
1966 the end since (at least) WIN2K and Windows XP have a major bug in not null
1967 terminating last Unicode string in response */
1968 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1969 if(ses->serverOS == NULL)
1970 goto sesssetup_nomem;
1971 cifs_strfromUCS_le(ses->serverOS,
1972 (wchar_t *)bcc_ptr, len,nls_codepage);
1973 bcc_ptr += 2 * (len + 1);
1974 remaining_words -= len + 1;
1975 ses->serverOS[2 * len] = 0;
1976 ses->serverOS[1 + (2 * len)] = 0;
1977 if (remaining_words > 0) {
1978 len = UniStrnlen((wchar_t *)bcc_ptr,
1980 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
1981 if(ses->serverNOS == NULL)
1982 goto sesssetup_nomem;
1983 cifs_strfromUCS_le(ses->serverNOS,
1984 (wchar_t *)bcc_ptr,len,nls_codepage);
1985 bcc_ptr += 2 * (len + 1);
1986 ses->serverNOS[2 * len] = 0;
1987 ses->serverNOS[1 + (2 * len)] = 0;
1988 if(strncmp(ses->serverNOS,
1989 "NT LAN Manager 4",16) == 0) {
1990 cFYI(1,("NT4 server"));
1991 ses->flags |= CIFS_SES_NT4;
1993 remaining_words -= len + 1;
1994 if (remaining_words > 0) {
1995 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1996 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1998 kcalloc(1, 2*(len+1),GFP_KERNEL);
1999 if(ses->serverDomain == NULL)
2000 goto sesssetup_nomem;
2001 cifs_strfromUCS_le(ses->serverDomain,
2002 (wchar_t *)bcc_ptr,len,nls_codepage);
2003 bcc_ptr += 2 * (len + 1);
2004 ses->serverDomain[2*len] = 0;
2005 ses->serverDomain[1+(2*len)] = 0;
2006 } /* else no more room so create dummy domain string */
2009 kcalloc(1, 2, GFP_KERNEL);
2010 } else { /* no room so create dummy domain and NOS string */
2011 /* if these kcallocs fail not much we
2012 can do, but better to not fail the
2015 kcalloc(1, 2, GFP_KERNEL);
2017 kcalloc(1, 2, GFP_KERNEL);
2019 } else { /* ASCII */
2020 len = strnlen(bcc_ptr, 1024);
2021 if (((long) bcc_ptr + len) - (long)
2022 pByteArea(smb_buffer_response)
2023 <= BCC(smb_buffer_response)) {
2024 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2025 if(ses->serverOS == NULL)
2026 goto sesssetup_nomem;
2027 strncpy(ses->serverOS,bcc_ptr, len);
2030 bcc_ptr[0] = 0; /* null terminate the string */
2033 len = strnlen(bcc_ptr, 1024);
2034 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2035 if(ses->serverNOS == NULL)
2036 goto sesssetup_nomem;
2037 strncpy(ses->serverNOS, bcc_ptr, len);
2042 len = strnlen(bcc_ptr, 1024);
2043 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2044 if(ses->serverDomain == NULL)
2045 goto sesssetup_nomem;
2046 strncpy(ses->serverDomain, bcc_ptr, len);
2052 ("Variable field of length %d extends beyond end of smb ",
2057 (" Security Blob Length extends beyond end of SMB"));
2061 (" Invalid Word count %d: ",
2062 smb_buffer_response->WordCount));
2065 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2066 since that could make reconnection harder, and
2067 reconnection might be needed to free memory */
2069 cifs_buf_release(smb_buffer);
2075 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2076 char *SecurityBlob,int SecurityBlobLength,
2077 const struct nls_table *nls_codepage)
2079 struct smb_hdr *smb_buffer;
2080 struct smb_hdr *smb_buffer_response;
2081 SESSION_SETUP_ANDX *pSMB;
2082 SESSION_SETUP_ANDX *pSMBr;
2087 int remaining_words = 0;
2088 int bytes_returned = 0;
2093 cFYI(1, ("In spnego sesssetup "));
2096 user = ses->userName;
2097 domain = ses->domainName;
2099 smb_buffer = cifs_buf_get();
2100 if (smb_buffer == NULL) {
2103 smb_buffer_response = smb_buffer;
2104 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2106 /* send SMBsessionSetup here */
2107 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2108 NULL /* no tCon exists yet */ , 12 /* wct */ );
2109 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2110 pSMB->req.AndXCommand = 0xFF;
2111 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2112 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2114 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2115 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2117 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2118 CAP_EXTENDED_SECURITY;
2119 if (ses->capabilities & CAP_UNICODE) {
2120 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2121 capabilities |= CAP_UNICODE;
2123 if (ses->capabilities & CAP_STATUS32) {
2124 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2125 capabilities |= CAP_STATUS32;
2127 if (ses->capabilities & CAP_DFS) {
2128 smb_buffer->Flags2 |= SMBFLG2_DFS;
2129 capabilities |= CAP_DFS;
2131 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2133 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2134 bcc_ptr = pByteArea(smb_buffer);
2135 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2136 bcc_ptr += SecurityBlobLength;
2138 if (ses->capabilities & CAP_UNICODE) {
2139 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2144 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
2145 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2146 bcc_ptr += 2; /* trailing null */
2149 cifs_strtoUCS((wchar_t *) bcc_ptr,
2150 "CIFS_LINUX_DOM", 32, nls_codepage);
2153 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2155 bcc_ptr += 2 * bytes_returned;
2158 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2160 bcc_ptr += 2 * bytes_returned;
2162 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2164 bcc_ptr += 2 * bytes_returned;
2167 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2169 bcc_ptr += 2 * bytes_returned;
2172 strncpy(bcc_ptr, user, 200);
2173 bcc_ptr += strnlen(user, 200);
2176 if (domain == NULL) {
2177 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2178 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2180 strncpy(bcc_ptr, domain, 64);
2181 bcc_ptr += strnlen(domain, 64);
2185 strcpy(bcc_ptr, "Linux version ");
2186 bcc_ptr += strlen("Linux version ");
2187 strcpy(bcc_ptr, system_utsname.release);
2188 bcc_ptr += strlen(system_utsname.release) + 1;
2189 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2190 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2192 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2193 smb_buffer->smb_buf_length += count;
2194 pSMB->req.ByteCount = cpu_to_le16(count);
2196 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2197 &bytes_returned, 1);
2199 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2200 } else if ((smb_buffer_response->WordCount == 3)
2201 || (smb_buffer_response->WordCount == 4)) {
2202 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2204 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2205 if (action & GUEST_LOGIN)
2206 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2208 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2209 cFYI(1, ("UID = %d ", ses->Suid));
2210 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2212 /* BB Fix below to make endian neutral !! */
2214 if ((pSMBr->resp.hdr.WordCount == 3)
2215 || ((pSMBr->resp.hdr.WordCount == 4)
2217 pSMBr->resp.ByteCount))) {
2218 if (pSMBr->resp.hdr.WordCount == 4) {
2222 ("Security Blob Length %d ",
2226 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2227 if ((long) (bcc_ptr) % 2) {
2229 (BCC(smb_buffer_response)
2231 bcc_ptr++; /* Unicode strings must be word aligned */
2235 (smb_buffer_response) / 2;
2238 UniStrnlen((wchar_t *) bcc_ptr,
2239 remaining_words - 1);
2240 /* We look for obvious messed up bcc or strings in response so we do not go off
2241 the end since (at least) WIN2K and Windows XP have a major bug in not null
2242 terminating last Unicode string in response */
2244 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2245 cifs_strfromUCS_le(ses->serverOS,
2249 bcc_ptr += 2 * (len + 1);
2250 remaining_words -= len + 1;
2251 ses->serverOS[2 * len] = 0;
2252 ses->serverOS[1 + (2 * len)] = 0;
2253 if (remaining_words > 0) {
2254 len = UniStrnlen((wchar_t *)bcc_ptr,
2258 kcalloc(1, 2 * (len + 1),
2260 cifs_strfromUCS_le(ses->serverNOS,
2264 bcc_ptr += 2 * (len + 1);
2265 ses->serverNOS[2 * len] = 0;
2266 ses->serverNOS[1 + (2 * len)] = 0;
2267 remaining_words -= len + 1;
2268 if (remaining_words > 0) {
2269 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2270 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2271 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2272 cifs_strfromUCS_le(ses->serverDomain,
2276 bcc_ptr += 2*(len+1);
2277 ses->serverDomain[2*len] = 0;
2278 ses->serverDomain[1+(2*len)] = 0;
2279 } /* else no more room so create dummy domain string */
2282 kcalloc(1, 2,GFP_KERNEL);
2283 } else { /* no room so create dummy domain and NOS string */
2284 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2285 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2287 } else { /* ASCII */
2289 len = strnlen(bcc_ptr, 1024);
2290 if (((long) bcc_ptr + len) - (long)
2291 pByteArea(smb_buffer_response)
2292 <= BCC(smb_buffer_response)) {
2293 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2294 strncpy(ses->serverOS, bcc_ptr, len);
2297 bcc_ptr[0] = 0; /* null terminate the string */
2300 len = strnlen(bcc_ptr, 1024);
2301 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2302 strncpy(ses->serverNOS, bcc_ptr, len);
2307 len = strnlen(bcc_ptr, 1024);
2308 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2309 strncpy(ses->serverDomain, bcc_ptr, len);
2315 ("Variable field of length %d extends beyond end of smb ",
2320 (" Security Blob Length extends beyond end of SMB"));
2323 cERROR(1, ("No session structure passed in."));
2327 (" Invalid Word count %d: ",
2328 smb_buffer_response->WordCount));
2333 cifs_buf_release(smb_buffer);
2339 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2340 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2341 const struct nls_table *nls_codepage)
2343 struct smb_hdr *smb_buffer;
2344 struct smb_hdr *smb_buffer_response;
2345 SESSION_SETUP_ANDX *pSMB;
2346 SESSION_SETUP_ANDX *pSMBr;
2350 int remaining_words = 0;
2351 int bytes_returned = 0;
2353 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2354 PNEGOTIATE_MESSAGE SecurityBlob;
2355 PCHALLENGE_MESSAGE SecurityBlob2;
2356 __u32 negotiate_flags, capabilities;
2359 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2362 domain = ses->domainName;
2363 *pNTLMv2_flag = FALSE;
2364 smb_buffer = cifs_buf_get();
2365 if (smb_buffer == NULL) {
2368 smb_buffer_response = smb_buffer;
2369 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2370 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2372 /* send SMBsessionSetup here */
2373 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2374 NULL /* no tCon exists yet */ , 12 /* wct */ );
2375 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2376 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2378 pSMB->req.AndXCommand = 0xFF;
2379 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2380 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2382 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2383 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2385 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2386 CAP_EXTENDED_SECURITY;
2387 if (ses->capabilities & CAP_UNICODE) {
2388 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2389 capabilities |= CAP_UNICODE;
2391 if (ses->capabilities & CAP_STATUS32) {
2392 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2393 capabilities |= CAP_STATUS32;
2395 if (ses->capabilities & CAP_DFS) {
2396 smb_buffer->Flags2 |= SMBFLG2_DFS;
2397 capabilities |= CAP_DFS;
2399 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2401 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2402 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2403 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2404 SecurityBlob->MessageType = NtLmNegotiate;
2406 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2407 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2408 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2410 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2412 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2413 /* setup pointers to domain name and workstation name */
2414 bcc_ptr += SecurityBlobLength;
2416 SecurityBlob->WorkstationName.Buffer = 0;
2417 SecurityBlob->WorkstationName.Length = 0;
2418 SecurityBlob->WorkstationName.MaximumLength = 0;
2420 if (domain == NULL) {
2421 SecurityBlob->DomainName.Buffer = 0;
2422 SecurityBlob->DomainName.Length = 0;
2423 SecurityBlob->DomainName.MaximumLength = 0;
2426 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2427 strncpy(bcc_ptr, domain, 63);
2428 len = strnlen(domain, 64);
2429 SecurityBlob->DomainName.MaximumLength =
2431 SecurityBlob->DomainName.Buffer =
2432 cpu_to_le32((long) &SecurityBlob->
2434 (long) &SecurityBlob->Signature);
2436 SecurityBlobLength += len;
2437 SecurityBlob->DomainName.Length =
2440 if (ses->capabilities & CAP_UNICODE) {
2441 if ((long) bcc_ptr % 2) {
2447 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2449 bcc_ptr += 2 * bytes_returned;
2451 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2453 bcc_ptr += 2 * bytes_returned;
2454 bcc_ptr += 2; /* null terminate Linux version */
2456 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2458 bcc_ptr += 2 * bytes_returned;
2461 bcc_ptr += 2; /* null terminate network opsys string */
2464 bcc_ptr += 2; /* null domain */
2465 } else { /* ASCII */
2466 strcpy(bcc_ptr, "Linux version ");
2467 bcc_ptr += strlen("Linux version ");
2468 strcpy(bcc_ptr, system_utsname.release);
2469 bcc_ptr += strlen(system_utsname.release) + 1;
2470 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2471 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2472 bcc_ptr++; /* empty domain field */
2475 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2476 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2477 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2478 smb_buffer->smb_buf_length += count;
2479 pSMB->req.ByteCount = cpu_to_le16(count);
2481 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2482 &bytes_returned, 1);
2484 if (smb_buffer_response->Status.CifsError ==
2485 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2489 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2490 } else if ((smb_buffer_response->WordCount == 3)
2491 || (smb_buffer_response->WordCount == 4)) {
2492 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2493 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2495 if (action & GUEST_LOGIN)
2496 cFYI(1, (" Guest login"));
2497 /* Do we want to set anything in SesInfo struct when guest login? */
2499 bcc_ptr = pByteArea(smb_buffer_response);
2500 /* response can have either 3 or 4 word count - Samba sends 3 */
2502 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2503 if (SecurityBlob2->MessageType != NtLmChallenge) {
2505 ("Unexpected NTLMSSP message type received %d",
2506 SecurityBlob2->MessageType));
2508 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2509 cFYI(1, ("UID = %d ", ses->Suid));
2510 if ((pSMBr->resp.hdr.WordCount == 3)
2511 || ((pSMBr->resp.hdr.WordCount == 4)
2513 pSMBr->resp.ByteCount))) {
2515 if (pSMBr->resp.hdr.WordCount == 4) {
2516 bcc_ptr += blob_len;
2518 ("Security Blob Length %d ",
2522 cFYI(1, ("NTLMSSP Challenge rcvd "));
2524 memcpy(ses->server->cryptKey,
2525 SecurityBlob2->Challenge,
2526 CIFS_CRYPTO_KEY_SIZE);
2527 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2528 *pNTLMv2_flag = TRUE;
2530 if((SecurityBlob2->NegotiateFlags &
2531 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2532 || (sign_CIFS_PDUs > 1))
2533 ses->server->secMode |=
2534 SECMODE_SIGN_REQUIRED;
2535 if ((SecurityBlob2->NegotiateFlags &
2536 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2537 ses->server->secMode |=
2538 SECMODE_SIGN_ENABLED;
2540 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2541 if ((long) (bcc_ptr) % 2) {
2543 (BCC(smb_buffer_response)
2545 bcc_ptr++; /* Unicode strings must be word aligned */
2549 (smb_buffer_response) / 2;
2552 UniStrnlen((wchar_t *) bcc_ptr,
2553 remaining_words - 1);
2554 /* We look for obvious messed up bcc or strings in response so we do not go off
2555 the end since (at least) WIN2K and Windows XP have a major bug in not null
2556 terminating last Unicode string in response */
2558 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2559 cifs_strfromUCS_le(ses->serverOS,
2563 bcc_ptr += 2 * (len + 1);
2564 remaining_words -= len + 1;
2565 ses->serverOS[2 * len] = 0;
2566 ses->serverOS[1 + (2 * len)] = 0;
2567 if (remaining_words > 0) {
2568 len = UniStrnlen((wchar_t *)
2573 kcalloc(1, 2 * (len + 1),
2575 cifs_strfromUCS_le(ses->
2581 bcc_ptr += 2 * (len + 1);
2582 ses->serverNOS[2 * len] = 0;
2585 remaining_words -= len + 1;
2586 if (remaining_words > 0) {
2587 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2588 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2613 } /* else no more room so create dummy domain string */
2618 } else { /* no room so create dummy domain and NOS string */
2620 kcalloc(1, 2, GFP_KERNEL);
2622 kcalloc(1, 2, GFP_KERNEL);
2624 } else { /* ASCII */
2625 len = strnlen(bcc_ptr, 1024);
2626 if (((long) bcc_ptr + len) - (long)
2627 pByteArea(smb_buffer_response)
2628 <= BCC(smb_buffer_response)) {
2632 strncpy(ses->serverOS,
2636 bcc_ptr[0] = 0; /* null terminate string */
2639 len = strnlen(bcc_ptr, 1024);
2643 strncpy(ses->serverNOS, bcc_ptr, len);
2648 len = strnlen(bcc_ptr, 1024);
2652 strncpy(ses->serverDomain, bcc_ptr, len);
2658 ("Variable field of length %d extends beyond end of smb ",
2663 (" Security Blob Length extends beyond end of SMB"));
2666 cERROR(1, ("No session structure passed in."));
2670 (" Invalid Word count %d: ",
2671 smb_buffer_response->WordCount));
2676 cifs_buf_release(smb_buffer);
2681 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2682 char *ntlm_session_key, int ntlmv2_flag,
2683 const struct nls_table *nls_codepage)
2685 struct smb_hdr *smb_buffer;
2686 struct smb_hdr *smb_buffer_response;
2687 SESSION_SETUP_ANDX *pSMB;
2688 SESSION_SETUP_ANDX *pSMBr;
2693 int remaining_words = 0;
2694 int bytes_returned = 0;
2696 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2697 PAUTHENTICATE_MESSAGE SecurityBlob;
2698 __u32 negotiate_flags, capabilities;
2701 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2704 user = ses->userName;
2705 domain = ses->domainName;
2706 smb_buffer = cifs_buf_get();
2707 if (smb_buffer == NULL) {
2710 smb_buffer_response = smb_buffer;
2711 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2712 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2714 /* send SMBsessionSetup here */
2715 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2716 NULL /* no tCon exists yet */ , 12 /* wct */ );
2717 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2718 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2719 pSMB->req.AndXCommand = 0xFF;
2720 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2721 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2723 pSMB->req.hdr.Uid = ses->Suid;
2725 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2726 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2728 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2729 CAP_EXTENDED_SECURITY;
2730 if (ses->capabilities & CAP_UNICODE) {
2731 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2732 capabilities |= CAP_UNICODE;
2734 if (ses->capabilities & CAP_STATUS32) {
2735 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2736 capabilities |= CAP_STATUS32;
2738 if (ses->capabilities & CAP_DFS) {
2739 smb_buffer->Flags2 |= SMBFLG2_DFS;
2740 capabilities |= CAP_DFS;
2742 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2744 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2745 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2746 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2747 SecurityBlob->MessageType = NtLmAuthenticate;
2748 bcc_ptr += SecurityBlobLength;
2750 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2751 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2752 0x80000000 | NTLMSSP_NEGOTIATE_128;
2754 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2756 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2758 /* setup pointers to domain name and workstation name */
2760 SecurityBlob->WorkstationName.Buffer = 0;
2761 SecurityBlob->WorkstationName.Length = 0;
2762 SecurityBlob->WorkstationName.MaximumLength = 0;
2763 SecurityBlob->SessionKey.Length = 0;
2764 SecurityBlob->SessionKey.MaximumLength = 0;
2765 SecurityBlob->SessionKey.Buffer = 0;
2767 SecurityBlob->LmChallengeResponse.Length = 0;
2768 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2769 SecurityBlob->LmChallengeResponse.Buffer = 0;
2771 SecurityBlob->NtChallengeResponse.Length =
2772 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2773 SecurityBlob->NtChallengeResponse.MaximumLength =
2774 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2775 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2776 SecurityBlob->NtChallengeResponse.Buffer =
2777 cpu_to_le32(SecurityBlobLength);
2778 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2779 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2781 if (ses->capabilities & CAP_UNICODE) {
2782 if (domain == NULL) {
2783 SecurityBlob->DomainName.Buffer = 0;
2784 SecurityBlob->DomainName.Length = 0;
2785 SecurityBlob->DomainName.MaximumLength = 0;
2788 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2791 SecurityBlob->DomainName.MaximumLength =
2793 SecurityBlob->DomainName.Buffer =
2794 cpu_to_le32(SecurityBlobLength);
2796 SecurityBlobLength += len;
2797 SecurityBlob->DomainName.Length =
2801 SecurityBlob->UserName.Buffer = 0;
2802 SecurityBlob->UserName.Length = 0;
2803 SecurityBlob->UserName.MaximumLength = 0;
2806 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2809 SecurityBlob->UserName.MaximumLength =
2811 SecurityBlob->UserName.Buffer =
2812 cpu_to_le32(SecurityBlobLength);
2814 SecurityBlobLength += len;
2815 SecurityBlob->UserName.Length =
2819 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2820 SecurityBlob->WorkstationName.Length *= 2;
2821 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2822 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2823 bcc_ptr += SecurityBlob->WorkstationName.Length;
2824 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2825 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2827 if ((long) bcc_ptr % 2) {
2832 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2834 bcc_ptr += 2 * bytes_returned;
2836 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2838 bcc_ptr += 2 * bytes_returned;
2839 bcc_ptr += 2; /* null term version string */
2841 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2843 bcc_ptr += 2 * bytes_returned;
2846 bcc_ptr += 2; /* null terminate network opsys string */
2849 bcc_ptr += 2; /* null domain */
2850 } else { /* ASCII */
2851 if (domain == NULL) {
2852 SecurityBlob->DomainName.Buffer = 0;
2853 SecurityBlob->DomainName.Length = 0;
2854 SecurityBlob->DomainName.MaximumLength = 0;
2857 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2858 strncpy(bcc_ptr, domain, 63);
2859 len = strnlen(domain, 64);
2860 SecurityBlob->DomainName.MaximumLength =
2862 SecurityBlob->DomainName.Buffer =
2863 cpu_to_le32(SecurityBlobLength);
2865 SecurityBlobLength += len;
2866 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2869 SecurityBlob->UserName.Buffer = 0;
2870 SecurityBlob->UserName.Length = 0;
2871 SecurityBlob->UserName.MaximumLength = 0;
2874 strncpy(bcc_ptr, user, 63);
2875 len = strnlen(user, 64);
2876 SecurityBlob->UserName.MaximumLength =
2878 SecurityBlob->UserName.Buffer =
2879 cpu_to_le32(SecurityBlobLength);
2881 SecurityBlobLength += len;
2882 SecurityBlob->UserName.Length = cpu_to_le16(len);
2884 /* BB fill in our workstation name if known BB */
2886 strcpy(bcc_ptr, "Linux version ");
2887 bcc_ptr += strlen("Linux version ");
2888 strcpy(bcc_ptr, system_utsname.release);
2889 bcc_ptr += strlen(system_utsname.release) + 1;
2890 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2891 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2892 bcc_ptr++; /* null domain */
2895 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2896 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2897 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2898 smb_buffer->smb_buf_length += count;
2899 pSMB->req.ByteCount = cpu_to_le16(count);
2901 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2902 &bytes_returned, 1);
2904 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2905 } else if ((smb_buffer_response->WordCount == 3)
2906 || (smb_buffer_response->WordCount == 4)) {
2907 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2909 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2910 if (action & GUEST_LOGIN)
2911 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2912 /* if(SecurityBlob2->MessageType != NtLm??){
2913 cFYI("Unexpected message type on auth response is %d "));
2917 ("Does UID on challenge %d match auth response UID %d ",
2918 ses->Suid, smb_buffer_response->Uid));
2919 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2920 bcc_ptr = pByteArea(smb_buffer_response);
2921 /* response can have either 3 or 4 word count - Samba sends 3 */
2922 if ((pSMBr->resp.hdr.WordCount == 3)
2923 || ((pSMBr->resp.hdr.WordCount == 4)
2925 pSMBr->resp.ByteCount))) {
2926 if (pSMBr->resp.hdr.WordCount == 4) {
2930 ("Security Blob Length %d ",
2935 ("NTLMSSP response to Authenticate "));
2937 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2938 if ((long) (bcc_ptr) % 2) {
2940 (BCC(smb_buffer_response)
2942 bcc_ptr++; /* Unicode strings must be word aligned */
2944 remaining_words = BCC(smb_buffer_response) / 2;
2947 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2948 /* We look for obvious messed up bcc or strings in response so we do not go off
2949 the end since (at least) WIN2K and Windows XP have a major bug in not null
2950 terminating last Unicode string in response */
2952 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2953 cifs_strfromUCS_le(ses->serverOS,
2957 bcc_ptr += 2 * (len + 1);
2958 remaining_words -= len + 1;
2959 ses->serverOS[2 * len] = 0;
2960 ses->serverOS[1 + (2 * len)] = 0;
2961 if (remaining_words > 0) {
2962 len = UniStrnlen((wchar_t *)
2967 kcalloc(1, 2 * (len + 1),
2969 cifs_strfromUCS_le(ses->
2975 bcc_ptr += 2 * (len + 1);
2976 ses->serverNOS[2 * len] = 0;
2977 ses->serverNOS[1+(2*len)] = 0;
2978 remaining_words -= len + 1;
2979 if (remaining_words > 0) {
2980 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2981 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3006 } /* else no more room so create dummy domain string */
3008 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
3009 } else { /* no room so create dummy domain and NOS string */
3010 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
3011 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
3013 } else { /* ASCII */
3014 len = strnlen(bcc_ptr, 1024);
3015 if (((long) bcc_ptr + len) -
3016 (long) pByteArea(smb_buffer_response)
3017 <= BCC(smb_buffer_response)) {
3018 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
3019 strncpy(ses->serverOS,bcc_ptr, len);
3022 bcc_ptr[0] = 0; /* null terminate the string */
3025 len = strnlen(bcc_ptr, 1024);
3026 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
3027 strncpy(ses->serverNOS, bcc_ptr, len);
3032 len = strnlen(bcc_ptr, 1024);
3033 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
3034 strncpy(ses->serverDomain, bcc_ptr, len);
3040 ("Variable field of length %d extends beyond end of smb ",
3045 (" Security Blob Length extends beyond end of SMB"));
3048 cERROR(1, ("No session structure passed in."));
3052 (" Invalid Word count %d: ",
3053 smb_buffer_response->WordCount));
3058 cifs_buf_release(smb_buffer);
3064 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3065 const char *tree, struct cifsTconInfo *tcon,
3066 const struct nls_table *nls_codepage)
3068 struct smb_hdr *smb_buffer;
3069 struct smb_hdr *smb_buffer_response;
3072 unsigned char *bcc_ptr;
3080 smb_buffer = cifs_buf_get();
3081 if (smb_buffer == NULL) {
3084 smb_buffer_response = smb_buffer;
3086 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3087 NULL /*no tid */ , 4 /*wct */ );
3088 smb_buffer->Uid = ses->Suid;
3089 pSMB = (TCONX_REQ *) smb_buffer;
3090 pSMBr = (TCONX_RSP *) smb_buffer_response;
3092 pSMB->AndXCommand = 0xFF;
3093 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3094 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3095 bcc_ptr = &pSMB->Password[0];
3096 bcc_ptr++; /* skip password */
3098 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3099 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3101 if (ses->capabilities & CAP_STATUS32) {
3102 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3104 if (ses->capabilities & CAP_DFS) {
3105 smb_buffer->Flags2 |= SMBFLG2_DFS;
3107 if (ses->capabilities & CAP_UNICODE) {
3108 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3110 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
3111 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3112 bcc_ptr += 2; /* skip trailing null */
3113 } else { /* ASCII */
3115 strcpy(bcc_ptr, tree);
3116 bcc_ptr += strlen(tree) + 1;
3118 strcpy(bcc_ptr, "?????");
3119 bcc_ptr += strlen("?????");
3121 count = bcc_ptr - &pSMB->Password[0];
3122 pSMB->hdr.smb_buf_length += count;
3123 pSMB->ByteCount = cpu_to_le16(count);
3125 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3127 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3128 /* above now done in SendReceive */
3129 if ((rc == 0) && (tcon != NULL)) {
3130 tcon->tidStatus = CifsGood;
3131 tcon->tid = smb_buffer_response->Tid;
3132 bcc_ptr = pByteArea(smb_buffer_response);
3133 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3134 /* skip service field (NB: this field is always ASCII) */
3135 bcc_ptr += length + 1;
3136 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3137 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3138 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3139 if ((bcc_ptr + (2 * length)) -
3140 pByteArea(smb_buffer_response) <=
3141 BCC(smb_buffer_response)) {
3142 if(tcon->nativeFileSystem)
3143 kfree(tcon->nativeFileSystem);
3144 tcon->nativeFileSystem =
3145 kcalloc(1, length + 2, GFP_KERNEL);
3146 cifs_strfromUCS_le(tcon->nativeFileSystem,
3147 (wchar_t *) bcc_ptr,
3148 length, nls_codepage);
3149 bcc_ptr += 2 * length;
3150 bcc_ptr[0] = 0; /* null terminate the string */
3154 /* else do not bother copying these informational fields */
3156 length = strnlen(bcc_ptr, 1024);
3157 if ((bcc_ptr + length) -
3158 pByteArea(smb_buffer_response) <=
3159 BCC(smb_buffer_response)) {
3160 if(tcon->nativeFileSystem)
3161 kfree(tcon->nativeFileSystem);
3162 tcon->nativeFileSystem =
3163 kcalloc(1, length + 1, GFP_KERNEL);
3164 strncpy(tcon->nativeFileSystem, bcc_ptr,
3167 /* else do not bother copying these informational fields */
3169 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3170 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3171 } else if ((rc == 0) && tcon == NULL) {
3172 /* all we need to save for IPC$ connection */
3173 ses->ipc_tid = smb_buffer_response->Tid;
3177 cifs_buf_release(smb_buffer);
3182 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3186 struct cifsSesInfo *ses = NULL;
3187 struct task_struct *cifsd_task;
3191 if (cifs_sb->tcon) {
3192 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3193 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3198 tconInfoFree(cifs_sb->tcon);
3199 if ((ses) && (ses->server)) {
3200 /* save off task so we do not refer to ses later */
3201 cifsd_task = ses->server->tsk;
3202 cFYI(1, ("About to do SMBLogoff "));
3203 rc = CIFSSMBLogoff(xid, ses);
3207 } else if (rc == -ESHUTDOWN) {
3208 cFYI(1,("Waking up socket by sending it signal"));
3210 send_sig(SIGKILL,cifsd_task,1);
3212 } /* else - we have an smb session
3213 left on this socket do not kill cifsd */
3215 cFYI(1, ("No session or bad tcon"));
3218 cifs_sb->tcon = NULL;
3220 set_current_state(TASK_INTERRUPTIBLE);
3221 schedule_timeout(HZ / 2);
3227 return rc; /* BB check if we should always return zero here */
3230 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3231 struct nls_table * nls_info)
3234 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3235 int ntlmv2_flag = FALSE;
3238 /* what if server changes its buffer size after dropping the session? */
3239 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3240 rc = CIFSSMBNegotiate(xid, pSesInfo);
3241 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3242 rc = CIFSSMBNegotiate(xid, pSesInfo);
3247 spin_lock(&GlobalMid_Lock);
3248 if(pSesInfo->server->tcpStatus != CifsExiting)
3249 pSesInfo->server->tcpStatus = CifsGood;
3252 spin_unlock(&GlobalMid_Lock);
3258 pSesInfo->capabilities = pSesInfo->server->capabilities;
3259 if(linuxExtEnabled == 0)
3260 pSesInfo->capabilities &= (~CAP_UNIX);
3261 /* pSesInfo->sequence_number = 0;*/
3262 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3263 pSesInfo->server->secMode,
3264 pSesInfo->server->capabilities,
3265 pSesInfo->server->timeZone));
3266 if (extended_security
3267 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3268 && (pSesInfo->server->secType == NTLMSSP)) {
3269 cFYI(1, ("New style sesssetup "));
3270 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3271 NULL /* security blob */,
3272 0 /* blob length */,
3274 } else if (extended_security
3275 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3276 && (pSesInfo->server->secType == RawNTLMSSP)) {
3277 cFYI(1, ("NTLMSSP sesssetup "));
3278 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3285 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3286 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3291 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3293 CalcNTLMv2_response(pSesInfo,v2_response);
3295 cifs_calculate_ntlmv2_mac_key(
3296 pSesInfo->server->mac_signing_key,
3297 response, ntlm_session_key, */
3299 /* BB Put dummy sig in SessSetup PDU? */
3306 SMBNTencrypt(pSesInfo->password,
3307 pSesInfo->server->cryptKey,
3311 cifs_calculate_mac_key(
3312 pSesInfo->server->mac_signing_key,
3314 pSesInfo->password);
3316 /* for better security the weaker lanman hash not sent
3317 in AuthSessSetup so we no longer calculate it */
3319 rc = CIFSNTLMSSPAuthSessSetup(xid,
3325 } else { /* old style NTLM 0.12 session setup */
3326 SMBNTencrypt(pSesInfo->password,
3327 pSesInfo->server->cryptKey,
3331 cifs_calculate_mac_key(
3332 pSesInfo->server->mac_signing_key,
3333 ntlm_session_key, pSesInfo->password);
3335 rc = CIFSSessSetup(xid, pSesInfo,
3336 ntlm_session_key, nls_info);
3339 cERROR(1,("Send error in SessSetup = %d",rc));
3341 cFYI(1,("CIFS Session Established successfully"));
3342 pSesInfo->status = CifsGood;