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);
183 atomic_inc(&tcpSesReconnectCount);
184 spin_lock(&GlobalMid_Lock);
185 if(server->tcpStatus != CifsExiting)
186 server->tcpStatus = CifsGood;
187 server->sequence_number = 0;
188 spin_unlock(&GlobalMid_Lock);
189 /* atomic_set(&server->inFlight,0);*/
190 wake_up(&server->response_q);
198 0 not a transact2, or all data present
199 >0 transact2 with that much data missing
200 -EINVAL = invalid transact2
203 static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
205 struct smb_t2_rsp * pSMBt;
207 int data_in_this_rsp;
210 if(pSMB->Command != SMB_COM_TRANSACTION2)
213 /* check for plausible wct, bcc and t2 data and parm sizes */
214 /* check for parm and data offset going beyond end of smb */
215 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
216 cFYI(1,("invalid transact2 word count"));
220 pSMBt = (struct smb_t2_rsp *)pSMB;
222 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
223 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
225 remaining = total_data_size - data_in_this_rsp;
229 else if(remaining < 0) {
230 cFYI(1,("total data %d smaller than data in frame %d",
231 total_data_size, data_in_this_rsp));
234 cFYI(1,("missing %d bytes from transact2, check next response",
236 if(total_data_size > maxBufSize) {
237 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
238 total_data_size,maxBufSize));
245 static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
247 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
248 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
253 char * data_area_of_target;
254 char * data_area_of_buf2;
257 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
259 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
260 cFYI(1,("total data sizes of primary and secondary t2 differ"));
263 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
265 remaining = total_data_size - total_in_buf;
270 if(remaining == 0) /* nothing to do, ignore */
273 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
274 if(remaining < total_in_buf2) {
275 cFYI(1,("transact2 2nd response contains too much data"));
278 /* find end of first SMB data area */
279 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
280 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
281 /* validate target area */
283 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
284 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
286 data_area_of_target += total_in_buf;
288 /* copy second buffer into end of first buffer */
289 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
290 total_in_buf += total_in_buf2;
291 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
292 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
293 byte_count += total_in_buf2;
294 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
296 byte_count = be32_to_cpu(pTargetSMB->smb_buf_length);
297 byte_count += total_in_buf2;
299 /* BB also add check that we are not beyond maximum buffer size */
301 pTargetSMB->smb_buf_length = cpu_to_be32(byte_count);
303 if(remaining == total_in_buf2) {
304 cFYI(1,("found the last secondary response"));
305 return 0; /* we are done */
306 } else /* more responses to go */
312 cifs_demultiplex_thread(struct TCP_Server_Info *server)
315 unsigned int pdu_length, total_read;
316 struct smb_hdr *smb_buffer = NULL;
317 struct smb_hdr *bigbuf = NULL;
318 struct smb_hdr *smallbuf = NULL;
319 struct msghdr smb_msg;
321 struct socket *csocket = server->ssocket;
322 struct list_head *tmp;
323 struct cifsSesInfo *ses;
324 struct task_struct *task_to_wake = NULL;
325 struct mid_q_entry *mid_entry;
327 int isLargeBuf = FALSE;
332 allow_signal(SIGKILL);
333 current->flags |= PF_MEMALLOC;
334 server->tsk = current; /* save process info to wake at shutdown */
335 cFYI(1, ("Demultiplex PID: %d", current->pid));
336 write_lock(&GlobalSMBSeslock);
337 atomic_inc(&tcpSesAllocCount);
338 length = tcpSesAllocCount.counter;
339 write_unlock(&GlobalSMBSeslock);
341 mempool_resize(cifs_req_poolp,
342 length + cifs_min_rcv,
346 while (server->tcpStatus != CifsExiting) {
347 if (bigbuf == NULL) {
348 bigbuf = cifs_buf_get();
350 cERROR(1,("No memory for large SMB response"));
352 /* retry will check if exiting */
355 } else if(isLargeBuf) {
356 /* we are reusing a dirtry large buf, clear its start */
357 memset(bigbuf, 0, sizeof (struct smb_hdr));
360 if (smallbuf == NULL) {
361 smallbuf = cifs_small_buf_get();
362 if(smallbuf == NULL) {
363 cERROR(1,("No memory for SMB response"));
365 /* retry will check if exiting */
368 /* beginning of smb buffer is cleared in our buf_get */
369 } else /* if existing small buf clear beginning */
370 memset(smallbuf, 0, sizeof (struct smb_hdr));
374 smb_buffer = smallbuf;
375 iov.iov_base = smb_buffer;
377 smb_msg.msg_control = NULL;
378 smb_msg.msg_controllen = 0;
380 kernel_recvmsg(csocket, &smb_msg,
381 &iov, 1, 4, 0 /* BB see socket.h flags */);
383 if(server->tcpStatus == CifsExiting) {
385 } else if (server->tcpStatus == CifsNeedReconnect) {
386 cFYI(1,("Reconnect after server stopped responding"));
387 cifs_reconnect(server);
388 cFYI(1,("call to reconnect done"));
389 csocket = server->ssocket;
391 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
392 msleep(1); /* minimum sleep to prevent looping
393 allowing socket to clear and app threads to set
394 tcpStatus CifsNeedReconnect if server hung */
396 } else if (length <= 0) {
397 if(server->tcpStatus == CifsNew) {
398 cFYI(1,("tcp session abend after SMBnegprot"));
399 /* some servers kill the TCP session rather than
400 returning an SMB negprot error, in which
401 case reconnecting here is not going to help,
402 and so simply return error to mount */
405 if(length == -EINTR) {
406 cFYI(1,("cifsd thread killed"));
409 cFYI(1,("Reconnect after unexpected peek error %d",
411 cifs_reconnect(server);
412 csocket = server->ssocket;
413 wake_up(&server->response_q);
415 } else if (length < 4) {
417 ("Frame under four bytes received (%d bytes long)",
419 cifs_reconnect(server);
420 csocket = server->ssocket;
421 wake_up(&server->response_q);
425 /* the right amount was read from socket - 4 bytes */
427 pdu_length = ntohl(smb_buffer->smb_buf_length);
428 cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4));
430 temp = (char *) smb_buffer;
431 if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) {
433 } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
434 cFYI(1,("Good RFC 1002 session rsp"));
436 } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
437 /* we get this from Windows 98 instead of
438 an error on SMB negprot response */
439 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
441 if(server->tcpStatus == CifsNew) {
442 /* if nack on negprot (rather than
443 ret of smb negprot error) reconnecting
444 not going to help, ret error to mount */
447 /* give server a second to
448 clean up before reconnect attempt */
450 /* always try 445 first on reconnect
451 since we get NACK on some if we ever
452 connected to port 139 (the NACK is
453 since we do not begin with RFC1001
454 session initialize frame) */
455 server->addr.sockAddr.sin_port =
457 cifs_reconnect(server);
458 csocket = server->ssocket;
459 wake_up(&server->response_q);
462 } else if (temp[0] != (char) 0) {
463 cERROR(1,("Unknown RFC 1002 frame"));
464 cifs_dump_mem(" Received Data: ", temp, length);
465 cifs_reconnect(server);
466 csocket = server->ssocket;
470 /* else we have an SMB response */
471 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
472 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
473 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
474 length, pdu_length+4));
475 cifs_reconnect(server);
476 csocket = server->ssocket;
477 wake_up(&server->response_q);
484 if(pdu_length > MAX_CIFS_HDR_SIZE - 4) {
486 memcpy(bigbuf, smallbuf, 4);
490 iov.iov_base = 4 + (char *)smb_buffer;
491 iov.iov_len = pdu_length;
492 for (total_read = 0; total_read < pdu_length;
493 total_read += length) {
494 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
495 pdu_length - total_read, 0);
496 if((server->tcpStatus == CifsExiting) ||
497 (length == -EINTR)) {
501 } else if (server->tcpStatus == CifsNeedReconnect) {
502 cifs_reconnect(server);
503 csocket = server->ssocket;
504 /* Reconnect wakes up rspns q */
505 /* Now we will reread sock */
508 } else if ((length == -ERESTARTSYS) ||
509 (length == -EAGAIN)) {
510 msleep(1); /* minimum sleep to prevent looping,
511 allowing socket to clear and app
512 threads to set tcpStatus
513 CifsNeedReconnect if server hung*/
515 } else if (length <= 0) {
516 cERROR(1,("Received no data, expecting %d",
517 pdu_length - total_read));
518 cifs_reconnect(server);
519 csocket = server->ssocket;
526 else if(reconnect == 1)
529 length += 4; /* account for rfc1002 hdr */
532 dump_smb(smb_buffer, length);
533 if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) {
534 cERROR(1, ("Bad SMB Received "));
540 spin_lock(&GlobalMid_Lock);
541 list_for_each(tmp, &server->pending_mid_q) {
542 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
544 if ((mid_entry->mid == smb_buffer->Mid) &&
545 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
546 (mid_entry->command == smb_buffer->Command)) {
547 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
548 /* We have a multipart transact2 resp */
550 if(mid_entry->resp_buf) {
551 /* merge response - fix up 1st*/
552 if(coalesce_t2(smb_buffer,
553 mid_entry->resp_buf)) {
556 /* all parts received */
561 cERROR(1,("1st trans2 resp needs bigbuf"));
562 /* BB maybe we can fix this up, switch
563 to already allocated large buffer? */
565 /* Have first buffer */
566 mid_entry->resp_buf =
568 mid_entry->largeBuf = 1;
574 mid_entry->resp_buf = smb_buffer;
576 mid_entry->largeBuf = 1;
578 mid_entry->largeBuf = 0;
580 task_to_wake = mid_entry->tsk;
581 mid_entry->midState = MID_RESPONSE_RECEIVED;
585 spin_unlock(&GlobalMid_Lock);
587 /* Was previous buf put in mpx struct for multi-rsp? */
589 /* smb buffer will be freed by user thread */
595 wake_up_process(task_to_wake);
596 } else if ((is_valid_oplock_break(smb_buffer) == FALSE)
597 && (isMultiRsp == FALSE)) {
598 cERROR(1, ("No task to wake, unknown frame rcvd!"));
599 cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr));
601 } /* end while !EXITING */
603 spin_lock(&GlobalMid_Lock);
604 server->tcpStatus = CifsExiting;
606 /* check if we have blocked requests that need to free */
607 /* Note that cifs_max_pending is normally 50, but
608 can be set at module install time to as little as two */
609 if(atomic_read(&server->inFlight) >= cifs_max_pending)
610 atomic_set(&server->inFlight, cifs_max_pending - 1);
611 /* We do not want to set the max_pending too low or we
612 could end up with the counter going negative */
613 spin_unlock(&GlobalMid_Lock);
614 /* Although there should not be any requests blocked on
615 this queue it can not hurt to be paranoid and try to wake up requests
616 that may haven been blocked when more than 50 at time were on the wire
617 to the same server - they now will see the session is in exit state
618 and get out of SendReceive. */
619 wake_up_all(&server->request_q);
620 /* give those requests time to exit */
623 if(server->ssocket) {
624 sock_release(csocket);
625 server->ssocket = NULL;
627 /* buffer usuallly freed in free_mid - need to free it here on exit */
629 cifs_buf_release(bigbuf);
630 if (smallbuf != NULL)
631 cifs_small_buf_release(smallbuf);
633 read_lock(&GlobalSMBSeslock);
634 if (list_empty(&server->pending_mid_q)) {
635 /* loop through server session structures attached to this and
637 list_for_each(tmp, &GlobalSMBSessionList) {
639 list_entry(tmp, struct cifsSesInfo,
641 if (ses->server == server) {
642 ses->status = CifsExiting;
646 read_unlock(&GlobalSMBSeslock);
648 /* although we can not zero the server struct pointer yet,
649 since there are active requests which may depnd on them,
650 mark the corresponding SMB sessions as exiting too */
651 list_for_each(tmp, &GlobalSMBSessionList) {
652 ses = list_entry(tmp, struct cifsSesInfo,
654 if (ses->server == server) {
655 ses->status = CifsExiting;
659 spin_lock(&GlobalMid_Lock);
660 list_for_each(tmp, &server->pending_mid_q) {
661 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
662 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
664 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
665 task_to_wake = mid_entry->tsk;
667 wake_up_process(task_to_wake);
671 spin_unlock(&GlobalMid_Lock);
672 read_unlock(&GlobalSMBSeslock);
673 /* 1/8th of sec is more than enough time for them to exit */
677 if (list_empty(&server->pending_mid_q)) {
678 /* mpx threads have not exited yet give them
679 at least the smb send timeout time for long ops */
680 /* due to delays on oplock break requests, we need
681 to wait at least 45 seconds before giving up
682 on a request getting a response and going ahead
684 cFYI(1, ("Wait for exit from demultiplex thread"));
686 /* if threads still have not exited they are probably never
687 coming home not much else we can do but free the memory */
690 write_lock(&GlobalSMBSeslock);
691 atomic_dec(&tcpSesAllocCount);
692 length = tcpSesAllocCount.counter;
694 /* last chance to mark ses pointers invalid
695 if there are any pointing to this (e.g
696 if a crazy root user tried to kill cifsd
697 kernel thread explicitly this might happen) */
698 list_for_each(tmp, &GlobalSMBSessionList) {
699 ses = list_entry(tmp, struct cifsSesInfo,
701 if (ses->server == server) {
705 write_unlock(&GlobalSMBSeslock);
709 mempool_resize(cifs_req_poolp,
710 length + cifs_min_rcv,
719 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
723 unsigned int temp_len, i, j;
729 memset(vol->source_rfc1001_name,0x20,15);
730 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
731 /* does not have to be a perfect mapping since the field is
732 informational, only used for servers that do not support
733 port 445 and it can be overridden at mount time */
734 vol->source_rfc1001_name[i] =
735 toupper(system_utsname.nodename[i]);
737 vol->source_rfc1001_name[15] = 0;
739 vol->linux_uid = current->uid; /* current->euid instead? */
740 vol->linux_gid = current->gid;
741 vol->dir_mode = S_IRWXUGO;
742 /* 2767 perms indicate mandatory locking support */
743 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
745 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
751 if(strncmp(options,"sep=",4) == 0) {
752 if(options[4] != 0) {
753 separator[0] = options[4];
756 cFYI(1,("Null separator not allowed"));
760 while ((data = strsep(&options, separator)) != NULL) {
763 if ((value = strchr(data, '=')) != NULL)
766 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
768 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
770 } else if (strnicmp(data, "user", 4) == 0) {
771 if (!value || !*value) {
773 "CIFS: invalid or missing username\n");
774 return 1; /* needs_arg; */
776 if (strnlen(value, 200) < 200) {
777 vol->username = value;
779 printk(KERN_WARNING "CIFS: username too long\n");
782 } else if (strnicmp(data, "pass", 4) == 0) {
784 vol->password = NULL;
786 } else if(value[0] == 0) {
787 /* check if string begins with double comma
788 since that would mean the password really
789 does start with a comma, and would not
790 indicate an empty string */
791 if(value[1] != separator[0]) {
792 vol->password = NULL;
796 temp_len = strlen(value);
797 /* removed password length check, NTLM passwords
798 can be arbitrarily long */
800 /* if comma in password, the string will be
801 prematurely null terminated. Commas in password are
802 specified across the cifs mount interface by a double
803 comma ie ,, and a comma used as in other cases ie ','
804 as a parameter delimiter/separator is single and due
805 to the strsep above is temporarily zeroed. */
807 /* NB: password legally can have multiple commas and
808 the only illegal character in a password is null */
810 if ((value[temp_len] == 0) &&
811 (value[temp_len+1] == separator[0])) {
813 value[temp_len] = separator[0];
814 temp_len+=2; /* move after the second comma */
815 while(value[temp_len] != 0) {
816 if (value[temp_len] == separator[0]) {
817 if (value[temp_len+1] ==
819 /* skip second comma */
822 /* single comma indicating start
829 if(value[temp_len] == 0) {
833 /* point option to start of next parm */
834 options = value + temp_len + 1;
836 /* go from value to value + temp_len condensing
837 double commas to singles. Note that this ends up
838 allocating a few bytes too many, which is ok */
839 vol->password = kcalloc(1, temp_len, GFP_KERNEL);
840 if(vol->password == NULL) {
841 printk("CIFS: no memory for pass\n");
844 for(i=0,j=0;i<temp_len;i++,j++) {
845 vol->password[j] = value[i];
846 if(value[i] == separator[0]
847 && value[i+1] == separator[0]) {
848 /* skip second comma */
852 vol->password[j] = 0;
854 vol->password = kcalloc(1, temp_len+1, GFP_KERNEL);
855 if(vol->password == NULL) {
856 printk("CIFS: no memory for pass\n");
859 strcpy(vol->password, value);
861 } else if (strnicmp(data, "ip", 2) == 0) {
862 if (!value || !*value) {
864 } else if (strnlen(value, 35) < 35) {
867 printk(KERN_WARNING "CIFS: ip address too long\n");
870 } else if ((strnicmp(data, "unc", 3) == 0)
871 || (strnicmp(data, "target", 6) == 0)
872 || (strnicmp(data, "path", 4) == 0)) {
873 if (!value || !*value) {
875 "CIFS: invalid path to network resource\n");
876 return 1; /* needs_arg; */
878 if ((temp_len = strnlen(value, 300)) < 300) {
879 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
882 strcpy(vol->UNC,value);
883 if (strncmp(vol->UNC, "//", 2) == 0) {
886 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
888 "CIFS: UNC Path does not begin with // or \\\\ \n");
892 printk(KERN_WARNING "CIFS: UNC name too long\n");
895 } else if ((strnicmp(data, "domain", 3) == 0)
896 || (strnicmp(data, "workgroup", 5) == 0)) {
897 if (!value || !*value) {
898 printk(KERN_WARNING "CIFS: invalid domain name\n");
899 return 1; /* needs_arg; */
901 /* BB are there cases in which a comma can be valid in
902 a domain name and need special handling? */
903 if (strnlen(value, 65) < 65) {
904 vol->domainname = value;
905 cFYI(1, ("Domain name set"));
907 printk(KERN_WARNING "CIFS: domain name too long\n");
910 } else if (strnicmp(data, "iocharset", 9) == 0) {
911 if (!value || !*value) {
912 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
913 return 1; /* needs_arg; */
915 if (strnlen(value, 65) < 65) {
916 if(strnicmp(value,"default",7))
917 vol->iocharset = value;
918 /* if iocharset not set load_nls_default used by caller */
919 cFYI(1, ("iocharset set to %s",value));
921 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
924 } else if (strnicmp(data, "uid", 3) == 0) {
925 if (value && *value) {
927 simple_strtoul(value, &value, 0);
929 } else if (strnicmp(data, "gid", 3) == 0) {
930 if (value && *value) {
932 simple_strtoul(value, &value, 0);
934 } else if (strnicmp(data, "file_mode", 4) == 0) {
935 if (value && *value) {
937 simple_strtoul(value, &value, 0);
939 } else if (strnicmp(data, "dir_mode", 4) == 0) {
940 if (value && *value) {
942 simple_strtoul(value, &value, 0);
944 } else if (strnicmp(data, "dirmode", 4) == 0) {
945 if (value && *value) {
947 simple_strtoul(value, &value, 0);
949 } else if (strnicmp(data, "port", 4) == 0) {
950 if (value && *value) {
952 simple_strtoul(value, &value, 0);
954 } else if (strnicmp(data, "rsize", 5) == 0) {
955 if (value && *value) {
957 simple_strtoul(value, &value, 0);
959 } else if (strnicmp(data, "wsize", 5) == 0) {
960 if (value && *value) {
962 simple_strtoul(value, &value, 0);
964 } else if (strnicmp(data, "sockopt", 5) == 0) {
965 if (value && *value) {
967 simple_strtoul(value, &value, 0);
969 } else if (strnicmp(data, "netbiosname", 4) == 0) {
970 if (!value || !*value || (*value == ' ')) {
971 cFYI(1,("invalid (empty) netbiosname specified"));
973 memset(vol->source_rfc1001_name,0x20,15);
975 /* BB are there cases in which a comma can be
976 valid in this workstation netbios name (and need
977 special handling)? */
979 /* We do not uppercase netbiosname for user */
983 vol->source_rfc1001_name[i] = value[i];
985 /* The string has 16th byte zero still from
986 set at top of the function */
987 if((i==15) && (value[i] != 0))
988 printk(KERN_WARNING "CIFS: netbiosname longer than 15 and was truncated.\n");
990 } else if (strnicmp(data, "credentials", 4) == 0) {
992 } else if (strnicmp(data, "version", 3) == 0) {
994 } else if (strnicmp(data, "guest",5) == 0) {
996 } else if (strnicmp(data, "rw", 2) == 0) {
998 } else if ((strnicmp(data, "suid", 4) == 0) ||
999 (strnicmp(data, "nosuid", 6) == 0) ||
1000 (strnicmp(data, "exec", 4) == 0) ||
1001 (strnicmp(data, "noexec", 6) == 0) ||
1002 (strnicmp(data, "nodev", 5) == 0) ||
1003 (strnicmp(data, "noauto", 6) == 0) ||
1004 (strnicmp(data, "dev", 3) == 0)) {
1005 /* The mount tool or mount.cifs helper (if present)
1006 uses these opts to set flags, and the flags are read
1007 by the kernel vfs layer before we get here (ie
1008 before read super) so there is no point trying to
1009 parse these options again and set anything and it
1010 is ok to just ignore them */
1012 } else if (strnicmp(data, "ro", 2) == 0) {
1014 } else if (strnicmp(data, "hard", 4) == 0) {
1016 } else if (strnicmp(data, "soft", 4) == 0) {
1018 } else if (strnicmp(data, "perm", 4) == 0) {
1020 } else if (strnicmp(data, "noperm", 6) == 0) {
1022 } else if (strnicmp(data, "mapchars", 8) == 0) {
1024 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1026 } else if (strnicmp(data, "setuids", 7) == 0) {
1028 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1030 } else if (strnicmp(data, "nohard", 6) == 0) {
1032 } else if (strnicmp(data, "nosoft", 6) == 0) {
1034 } else if (strnicmp(data, "nointr", 6) == 0) {
1036 } else if (strnicmp(data, "intr", 4) == 0) {
1038 } else if (strnicmp(data, "serverino",7) == 0) {
1039 vol->server_ino = 1;
1040 } else if (strnicmp(data, "noserverino",9) == 0) {
1041 vol->server_ino = 0;
1042 } else if (strnicmp(data, "acl",3) == 0) {
1043 vol->no_psx_acl = 0;
1044 } else if (strnicmp(data, "noacl",5) == 0) {
1045 vol->no_psx_acl = 1;
1046 } else if (strnicmp(data, "direct",6) == 0) {
1048 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1050 } else if (strnicmp(data, "in6_addr",8) == 0) {
1051 if (!value || !*value) {
1052 vol->in6_addr = NULL;
1053 } else if (strnlen(value, 49) == 48) {
1054 vol->in6_addr = value;
1056 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1059 } else if (strnicmp(data, "noac", 4) == 0) {
1060 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1062 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1064 if (vol->UNC == NULL) {
1065 if(devname == NULL) {
1066 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1069 if ((temp_len = strnlen(devname, 300)) < 300) {
1070 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1071 if(vol->UNC == NULL)
1073 strcpy(vol->UNC,devname);
1074 if (strncmp(vol->UNC, "//", 2) == 0) {
1077 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1078 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1082 printk(KERN_WARNING "CIFS: UNC name too long\n");
1086 if(vol->UNCip == NULL)
1087 vol->UNCip = &vol->UNC[2];
1092 static struct cifsSesInfo *
1093 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1094 struct in6_addr *target_ip6_addr,
1095 char *userName, struct TCP_Server_Info **psrvTcp)
1097 struct list_head *tmp;
1098 struct cifsSesInfo *ses;
1100 read_lock(&GlobalSMBSeslock);
1102 list_for_each(tmp, &GlobalSMBSessionList) {
1103 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1105 if((target_ip_addr &&
1106 (ses->server->addr.sockAddr.sin_addr.s_addr
1107 == target_ip_addr->s_addr)) || (target_ip6_addr
1108 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1109 target_ip6_addr,sizeof(*target_ip6_addr)))){
1110 /* BB lock server and tcp session and increment use count here?? */
1111 *psrvTcp = ses->server; /* found a match on the TCP session */
1112 /* BB check if reconnection needed */
1114 (ses->userName, userName,
1115 MAX_USERNAME_SIZE) == 0){
1116 read_unlock(&GlobalSMBSeslock);
1117 return ses; /* found exact match on both tcp and SMB sessions */
1121 /* else tcp and smb sessions need reconnection */
1123 read_unlock(&GlobalSMBSeslock);
1127 static struct cifsTconInfo *
1128 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1130 struct list_head *tmp;
1131 struct cifsTconInfo *tcon;
1133 read_lock(&GlobalSMBSeslock);
1134 list_for_each(tmp, &GlobalTreeConnectionList) {
1135 cFYI(1, ("Next tcon - "));
1136 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1138 if (tcon->ses->server) {
1140 (" old ip addr: %x == new ip %x ?",
1141 tcon->ses->server->addr.sockAddr.sin_addr.
1142 s_addr, new_target_ip_addr));
1143 if (tcon->ses->server->addr.sockAddr.sin_addr.
1144 s_addr == new_target_ip_addr) {
1145 /* BB lock tcon and server and tcp session and increment use count here? */
1146 /* found a match on the TCP session */
1147 /* BB check if reconnection needed */
1148 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1149 tcon->treeName, uncName));
1151 (tcon->treeName, uncName,
1152 MAX_TREE_SIZE) == 0) {
1154 ("Matched UNC, old user: %s == new: %s ?",
1155 tcon->treeName, uncName));
1157 (tcon->ses->userName,
1159 MAX_USERNAME_SIZE) == 0) {
1160 read_unlock(&GlobalSMBSeslock);
1161 return tcon;/* also matched user (smb session)*/
1168 read_unlock(&GlobalSMBSeslock);
1173 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1174 const char *old_path, const struct nls_table *nls_codepage,
1177 unsigned char *referrals = NULL;
1178 unsigned int num_referrals;
1181 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1182 &num_referrals, &referrals, remap);
1184 /* BB Add in code to: if valid refrl, if not ip address contact
1185 the helper that resolves tcp names, mount to it, try to
1186 tcon to it unmount it if fail */
1195 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1196 const char *old_path, const struct nls_table *nls_codepage,
1197 unsigned int *pnum_referrals,
1198 unsigned char ** preferrals, int remap)
1203 *pnum_referrals = 0;
1205 if (pSesInfo->ipc_tid == 0) {
1206 temp_unc = kmalloc(2 /* for slashes */ +
1207 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1208 + 1 + 4 /* slash IPC$ */ + 2,
1210 if (temp_unc == NULL)
1214 strcpy(temp_unc + 2, pSesInfo->serverName);
1215 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1216 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1218 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1222 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1223 pnum_referrals, nls_codepage, remap);
1228 /* See RFC1001 section 14 on representation of Netbios names */
1229 static void rfc1002mangle(char * target,char * source, unsigned int length)
1233 for(i=0,j=0;i<(length);i++) {
1234 /* mask a nibble at a time and encode */
1235 target[j] = 'A' + (0x0F & (source[i] >> 4));
1236 target[j+1] = 'A' + (0x0F & source[i]);
1244 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1245 char * netbios_name)
1249 __be16 orig_port = 0;
1251 if(*csocket == NULL) {
1252 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1254 cERROR(1, ("Error %d creating socket",rc));
1258 /* BB other socket options to set KEEPALIVE, NODELAY? */
1259 cFYI(1,("Socket created"));
1260 (*csocket)->sk->sk_allocation = GFP_NOFS;
1264 psin_server->sin_family = AF_INET;
1265 if(psin_server->sin_port) { /* user overrode default port */
1266 rc = (*csocket)->ops->connect(*csocket,
1267 (struct sockaddr *) psin_server,
1268 sizeof (struct sockaddr_in),0);
1274 /* save original port so we can retry user specified port
1275 later if fall back ports fail this time */
1276 orig_port = psin_server->sin_port;
1278 /* do not retry on the same port we just failed on */
1279 if(psin_server->sin_port != htons(CIFS_PORT)) {
1280 psin_server->sin_port = htons(CIFS_PORT);
1282 rc = (*csocket)->ops->connect(*csocket,
1283 (struct sockaddr *) psin_server,
1284 sizeof (struct sockaddr_in),0);
1290 psin_server->sin_port = htons(RFC1001_PORT);
1291 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1292 psin_server, sizeof (struct sockaddr_in),0);
1297 /* give up here - unless we want to retry on different
1298 protocol families some day */
1301 psin_server->sin_port = orig_port;
1302 cFYI(1,("Error %d connecting to server via ipv4",rc));
1303 sock_release(*csocket);
1307 /* Eventually check for other socket options to change from
1308 the default. sock_setsockopt not used because it expects
1309 user space buffer */
1310 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1312 /* send RFC1001 sessinit */
1314 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1315 /* some servers require RFC1001 sessinit before sending
1316 negprot - BB check reconnection in case where second
1317 sessinit is sent but no second negprot */
1318 struct rfc1002_session_packet * ses_init_buf;
1319 struct smb_hdr * smb_buf;
1320 ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1322 ses_init_buf->trailer.session_req.called_len = 32;
1323 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1324 DEFAULT_CIFS_CALLED_NAME,16);
1325 ses_init_buf->trailer.session_req.calling_len = 32;
1326 /* calling name ends in null (byte 16) from old smb
1328 if(netbios_name && (netbios_name[0] !=0)) {
1329 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1332 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1333 "LINUX_CIFS_CLNT",16);
1335 ses_init_buf->trailer.session_req.scope1 = 0;
1336 ses_init_buf->trailer.session_req.scope2 = 0;
1337 smb_buf = (struct smb_hdr *)ses_init_buf;
1338 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1339 smb_buf->smb_buf_length = 0x81000044;
1340 rc = smb_send(*csocket, smb_buf, 0x44,
1341 (struct sockaddr *)psin_server);
1342 kfree(ses_init_buf);
1344 /* else the negprot may still work without this
1345 even though malloc failed */
1353 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1357 __be16 orig_port = 0;
1359 if(*csocket == NULL) {
1360 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1362 cERROR(1, ("Error %d creating ipv6 socket",rc));
1366 /* BB other socket options to set KEEPALIVE, NODELAY? */
1367 cFYI(1,("ipv6 Socket created"));
1368 (*csocket)->sk->sk_allocation = GFP_NOFS;
1372 psin_server->sin6_family = AF_INET6;
1374 if(psin_server->sin6_port) { /* user overrode default port */
1375 rc = (*csocket)->ops->connect(*csocket,
1376 (struct sockaddr *) psin_server,
1377 sizeof (struct sockaddr_in6),0);
1383 /* save original port so we can retry user specified port
1384 later if fall back ports fail this time */
1386 orig_port = psin_server->sin6_port;
1387 /* do not retry on the same port we just failed on */
1388 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1389 psin_server->sin6_port = htons(CIFS_PORT);
1391 rc = (*csocket)->ops->connect(*csocket,
1392 (struct sockaddr *) psin_server,
1393 sizeof (struct sockaddr_in6),0);
1399 psin_server->sin6_port = htons(RFC1001_PORT);
1400 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1401 psin_server, sizeof (struct sockaddr_in6),0);
1406 /* give up here - unless we want to retry on different
1407 protocol families some day */
1410 psin_server->sin6_port = orig_port;
1411 cFYI(1,("Error %d connecting to server via ipv6",rc));
1412 sock_release(*csocket);
1416 /* Eventually check for other socket options to change from
1417 the default. sock_setsockopt not used because it expects
1418 user space buffer */
1419 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1425 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1426 char *mount_data, const char *devname)
1430 int address_type = AF_INET;
1431 struct socket *csocket = NULL;
1432 struct sockaddr_in sin_server;
1433 struct sockaddr_in6 sin_server6;
1434 struct smb_vol volume_info;
1435 struct cifsSesInfo *pSesInfo = NULL;
1436 struct cifsSesInfo *existingCifsSes = NULL;
1437 struct cifsTconInfo *tcon = NULL;
1438 struct TCP_Server_Info *srvTcp = NULL;
1442 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1444 memset(&volume_info,0,sizeof(struct smb_vol));
1445 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1447 kfree(volume_info.UNC);
1448 if(volume_info.password)
1449 kfree(volume_info.password);
1454 if (volume_info.username) {
1455 /* BB fixme parse for domain name here */
1456 cFYI(1, ("Username: %s ", volume_info.username));
1459 cifserror("No username specified ");
1460 /* In userspace mount helper we can get user name from alternate
1461 locations such as env variables and files on disk */
1463 kfree(volume_info.UNC);
1464 if(volume_info.password)
1465 kfree(volume_info.password);
1470 if (volume_info.UNCip && volume_info.UNC) {
1471 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1474 /* not ipv4 address, try ipv6 */
1475 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1477 address_type = AF_INET6;
1479 address_type = AF_INET;
1483 /* we failed translating address */
1485 kfree(volume_info.UNC);
1486 if(volume_info.password)
1487 kfree(volume_info.password);
1492 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1495 } else if (volume_info.UNCip){
1496 /* BB using ip addr as server name connect to the DFS root below */
1497 cERROR(1,("Connecting to DFS root not implemented yet"));
1499 kfree(volume_info.UNC);
1500 if(volume_info.password)
1501 kfree(volume_info.password);
1504 } else /* which servers DFS root would we conect to */ {
1506 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified "));
1508 kfree(volume_info.UNC);
1509 if(volume_info.password)
1510 kfree(volume_info.password);
1515 /* this is needed for ASCII cp to Unicode converts */
1516 if(volume_info.iocharset == NULL) {
1517 cifs_sb->local_nls = load_nls_default();
1518 /* load_nls_default can not return null */
1520 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1521 if(cifs_sb->local_nls == NULL) {
1522 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1524 kfree(volume_info.UNC);
1525 if(volume_info.password)
1526 kfree(volume_info.password);
1532 if(address_type == AF_INET)
1533 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1534 NULL /* no ipv6 addr */,
1535 volume_info.username, &srvTcp);
1536 else if(address_type == AF_INET6)
1537 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1538 &sin_server6.sin6_addr,
1539 volume_info.username, &srvTcp);
1542 kfree(volume_info.UNC);
1543 if(volume_info.password)
1544 kfree(volume_info.password);
1551 cFYI(1, ("Existing tcp session with server found "));
1552 } else { /* create socket */
1553 if(volume_info.port)
1554 sin_server.sin_port = htons(volume_info.port);
1556 sin_server.sin_port = 0;
1557 rc = ipv4_connect(&sin_server,&csocket,volume_info.source_rfc1001_name);
1560 ("Error connecting to IPv4 socket. Aborting operation"));
1562 sock_release(csocket);
1564 kfree(volume_info.UNC);
1565 if(volume_info.password)
1566 kfree(volume_info.password);
1571 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1572 if (srvTcp == NULL) {
1574 sock_release(csocket);
1576 kfree(volume_info.UNC);
1577 if(volume_info.password)
1578 kfree(volume_info.password);
1582 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1583 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1584 atomic_set(&srvTcp->inFlight,0);
1585 /* BB Add code for ipv6 case too */
1586 srvTcp->ssocket = csocket;
1587 srvTcp->protocolType = IPV4;
1588 init_waitqueue_head(&srvTcp->response_q);
1589 init_waitqueue_head(&srvTcp->request_q);
1590 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1591 /* at this point we are the only ones with the pointer
1592 to the struct since the kernel thread not created yet
1593 so no need to spinlock this init of tcpStatus */
1594 srvTcp->tcpStatus = CifsNew;
1595 init_MUTEX(&srvTcp->tcpSem);
1596 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1597 CLONE_FS | CLONE_FILES | CLONE_VM);
1600 sock_release(csocket);
1602 kfree(volume_info.UNC);
1603 if(volume_info.password)
1604 kfree(volume_info.password);
1609 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1610 srvTcp->sequence_number = 0;
1614 if (existingCifsSes) {
1615 pSesInfo = existingCifsSes;
1616 cFYI(1, ("Existing smb sess found "));
1617 if(volume_info.password)
1618 kfree(volume_info.password);
1619 /* volume_info.UNC freed at end of function */
1621 cFYI(1, ("Existing smb sess not found "));
1622 pSesInfo = sesInfoAlloc();
1623 if (pSesInfo == NULL)
1626 pSesInfo->server = srvTcp;
1627 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1628 NIPQUAD(sin_server.sin_addr.s_addr));
1632 /* volume_info.password freed at unmount */
1633 if (volume_info.password)
1634 pSesInfo->password = volume_info.password;
1635 if (volume_info.username)
1636 strncpy(pSesInfo->userName,
1637 volume_info.username,MAX_USERNAME_SIZE);
1638 if (volume_info.domainname)
1639 strncpy(pSesInfo->domainName,
1640 volume_info.domainname,MAX_USERNAME_SIZE);
1641 pSesInfo->linux_uid = volume_info.linux_uid;
1642 down(&pSesInfo->sesSem);
1643 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1644 up(&pSesInfo->sesSem);
1646 atomic_inc(&srvTcp->socketUseCount);
1648 if(volume_info.password)
1649 kfree(volume_info.password);
1652 /* search for existing tcon to this server share */
1654 if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1655 cifs_sb->rsize = volume_info.rsize;
1657 cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */
1658 if((volume_info.wsize) && (volume_info.wsize <= CIFSMaxBufSize))
1659 cifs_sb->wsize = volume_info.wsize;
1661 cifs_sb->wsize = CIFSMaxBufSize; /* default */
1662 if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
1663 cifs_sb->rsize = PAGE_CACHE_SIZE;
1664 cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
1666 cifs_sb->mnt_uid = volume_info.linux_uid;
1667 cifs_sb->mnt_gid = volume_info.linux_gid;
1668 cifs_sb->mnt_file_mode = volume_info.file_mode;
1669 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1670 cFYI(1,("file mode: 0x%x dir mode: 0x%x",cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1672 if(volume_info.noperm)
1673 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1674 if(volume_info.setuids)
1675 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1676 if(volume_info.server_ino)
1677 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1678 if(volume_info.remap)
1679 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1680 if(volume_info.no_xattr)
1681 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1682 if(volume_info.direct_io) {
1683 cERROR(1,("mounting share using direct i/o"));
1684 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1688 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1689 volume_info.username);
1691 cFYI(1, ("Found match on UNC path "));
1692 /* we can have only one retry value for a connection
1693 to a share so for resources mounted more than once
1694 to the same server share the last value passed in
1695 for the retry flag is used */
1696 tcon->retry = volume_info.retry;
1698 tcon = tconInfoAlloc();
1702 /* check for null share name ie connect to dfs root */
1704 /* BB check if this works for exactly length three strings */
1705 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1706 && (strchr(volume_info.UNC + 3, '/') ==
1708 rc = connect_to_dfs_path(xid, pSesInfo,
1709 "", cifs_sb->local_nls,
1710 cifs_sb->mnt_cifs_flags &
1711 CIFS_MOUNT_MAP_SPECIAL_CHR);
1713 kfree(volume_info.UNC);
1717 rc = CIFSTCon(xid, pSesInfo,
1719 tcon, cifs_sb->local_nls);
1720 cFYI(1, ("CIFS Tcon rc = %d", rc));
1723 atomic_inc(&pSesInfo->inUse);
1724 tcon->retry = volume_info.retry;
1730 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1731 sb->s_maxbytes = (u64) 1 << 63;
1733 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1736 sb->s_time_gran = 100;
1738 /* on error free sesinfo and tcon struct if needed */
1740 /* if session setup failed, use count is zero but
1741 we still need to free cifsd thread */
1742 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1743 spin_lock(&GlobalMid_Lock);
1744 srvTcp->tcpStatus = CifsExiting;
1745 spin_unlock(&GlobalMid_Lock);
1747 send_sig(SIGKILL,srvTcp->tsk,1);
1749 /* If find_unc succeeded then rc == 0 so we can not end */
1750 if (tcon) /* up accidently freeing someone elses tcon struct */
1752 if (existingCifsSes == NULL) {
1754 if ((pSesInfo->server) &&
1755 (pSesInfo->status == CifsGood)) {
1757 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1758 /* if the socketUseCount is now zero */
1759 if((temp_rc == -ESHUTDOWN) &&
1760 (pSesInfo->server->tsk))
1761 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1763 cFYI(1, ("No session or bad tcon"));
1764 sesInfoFree(pSesInfo);
1765 /* pSesInfo = NULL; */
1769 atomic_inc(&tcon->useCount);
1770 cifs_sb->tcon = tcon;
1771 tcon->ses = pSesInfo;
1773 /* do not care if following two calls succeed - informational only */
1774 CIFSSMBQFSDeviceInfo(xid, tcon);
1775 CIFSSMBQFSAttributeInfo(xid, tcon);
1776 if (tcon->ses->capabilities & CAP_UNIX) {
1777 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1778 if(!volume_info.no_psx_acl) {
1779 if(CIFS_UNIX_POSIX_ACL_CAP &
1780 le64_to_cpu(tcon->fsUnixInfo.Capability))
1781 cFYI(1,("server negotiated posix acl support"));
1782 sb->s_flags |= MS_POSIXACL;
1788 /* volume_info.password is freed above when existing session found
1789 (in which case it is not needed anymore) but when new sesion is created
1790 the password ptr is put in the new session structure (in which case the
1791 password will be freed at unmount time) */
1793 kfree(volume_info.UNC);
1799 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1800 char session_key[CIFS_SESSION_KEY_SIZE],
1801 const struct nls_table *nls_codepage)
1803 struct smb_hdr *smb_buffer;
1804 struct smb_hdr *smb_buffer_response;
1805 SESSION_SETUP_ANDX *pSMB;
1806 SESSION_SETUP_ANDX *pSMBr;
1811 int remaining_words = 0;
1812 int bytes_returned = 0;
1817 cFYI(1, ("In sesssetup "));
1820 user = ses->userName;
1821 domain = ses->domainName;
1822 smb_buffer = cifs_buf_get();
1823 if (smb_buffer == NULL) {
1826 smb_buffer_response = smb_buffer;
1827 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
1829 /* send SMBsessionSetup here */
1830 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
1831 NULL /* no tCon exists yet */ , 13 /* wct */ );
1833 pSMB->req_no_secext.AndXCommand = 0xFF;
1834 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
1835 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
1837 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1838 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
1840 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
1841 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
1842 if (ses->capabilities & CAP_UNICODE) {
1843 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
1844 capabilities |= CAP_UNICODE;
1846 if (ses->capabilities & CAP_STATUS32) {
1847 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
1848 capabilities |= CAP_STATUS32;
1850 if (ses->capabilities & CAP_DFS) {
1851 smb_buffer->Flags2 |= SMBFLG2_DFS;
1852 capabilities |= CAP_DFS;
1854 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
1856 pSMB->req_no_secext.CaseInsensitivePasswordLength =
1857 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1859 pSMB->req_no_secext.CaseSensitivePasswordLength =
1860 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
1861 bcc_ptr = pByteArea(smb_buffer);
1862 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1863 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1864 memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
1865 bcc_ptr += CIFS_SESSION_KEY_SIZE;
1867 if (ses->capabilities & CAP_UNICODE) {
1868 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
1873 bytes_returned = 0; /* skill null user */
1876 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
1878 /* convert number of 16 bit words to bytes */
1879 bcc_ptr += 2 * bytes_returned;
1880 bcc_ptr += 2; /* trailing null */
1883 cifs_strtoUCS((wchar_t *) bcc_ptr,
1884 "CIFS_LINUX_DOM", 32, nls_codepage);
1887 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
1889 bcc_ptr += 2 * bytes_returned;
1892 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
1894 bcc_ptr += 2 * bytes_returned;
1896 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
1898 bcc_ptr += 2 * bytes_returned;
1901 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
1903 bcc_ptr += 2 * bytes_returned;
1907 strncpy(bcc_ptr, user, 200);
1908 bcc_ptr += strnlen(user, 200);
1912 if (domain == NULL) {
1913 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
1914 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
1916 strncpy(bcc_ptr, domain, 64);
1917 bcc_ptr += strnlen(domain, 64);
1921 strcpy(bcc_ptr, "Linux version ");
1922 bcc_ptr += strlen("Linux version ");
1923 strcpy(bcc_ptr, system_utsname.release);
1924 bcc_ptr += strlen(system_utsname.release) + 1;
1925 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
1926 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
1928 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
1929 smb_buffer->smb_buf_length += count;
1930 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
1932 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
1933 &bytes_returned, 1);
1935 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
1936 } else if ((smb_buffer_response->WordCount == 3)
1937 || (smb_buffer_response->WordCount == 4)) {
1938 __u16 action = le16_to_cpu(pSMBr->resp.Action);
1939 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
1940 if (action & GUEST_LOGIN)
1941 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
1942 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
1943 cFYI(1, ("UID = %d ", ses->Suid));
1944 /* response can have either 3 or 4 word count - Samba sends 3 */
1945 bcc_ptr = pByteArea(smb_buffer_response);
1946 if ((pSMBr->resp.hdr.WordCount == 3)
1947 || ((pSMBr->resp.hdr.WordCount == 4)
1948 && (blob_len < pSMBr->resp.ByteCount))) {
1949 if (pSMBr->resp.hdr.WordCount == 4)
1950 bcc_ptr += blob_len;
1952 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
1953 if ((long) (bcc_ptr) % 2) {
1955 (BCC(smb_buffer_response) - 1) /2;
1956 bcc_ptr++; /* Unicode strings must be word aligned */
1959 BCC(smb_buffer_response) / 2;
1962 UniStrnlen((wchar_t *) bcc_ptr,
1963 remaining_words - 1);
1964 /* We look for obvious messed up bcc or strings in response so we do not go off
1965 the end since (at least) WIN2K and Windows XP have a major bug in not null
1966 terminating last Unicode string in response */
1967 ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL);
1968 if(ses->serverOS == NULL)
1969 goto sesssetup_nomem;
1970 cifs_strfromUCS_le(ses->serverOS,
1971 (wchar_t *)bcc_ptr, len,nls_codepage);
1972 bcc_ptr += 2 * (len + 1);
1973 remaining_words -= len + 1;
1974 ses->serverOS[2 * len] = 0;
1975 ses->serverOS[1 + (2 * len)] = 0;
1976 if (remaining_words > 0) {
1977 len = UniStrnlen((wchar_t *)bcc_ptr,
1979 ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL);
1980 if(ses->serverNOS == NULL)
1981 goto sesssetup_nomem;
1982 cifs_strfromUCS_le(ses->serverNOS,
1983 (wchar_t *)bcc_ptr,len,nls_codepage);
1984 bcc_ptr += 2 * (len + 1);
1985 ses->serverNOS[2 * len] = 0;
1986 ses->serverNOS[1 + (2 * len)] = 0;
1987 if(strncmp(ses->serverNOS,
1988 "NT LAN Manager 4",16) == 0) {
1989 cFYI(1,("NT4 server"));
1990 ses->flags |= CIFS_SES_NT4;
1992 remaining_words -= len + 1;
1993 if (remaining_words > 0) {
1994 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1995 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
1997 kcalloc(1, 2*(len+1),GFP_KERNEL);
1998 if(ses->serverDomain == NULL)
1999 goto sesssetup_nomem;
2000 cifs_strfromUCS_le(ses->serverDomain,
2001 (wchar_t *)bcc_ptr,len,nls_codepage);
2002 bcc_ptr += 2 * (len + 1);
2003 ses->serverDomain[2*len] = 0;
2004 ses->serverDomain[1+(2*len)] = 0;
2005 } /* else no more room so create dummy domain string */
2008 kcalloc(1, 2, GFP_KERNEL);
2009 } else { /* no room so create dummy domain and NOS string */
2010 /* if these kcallocs fail not much we
2011 can do, but better to not fail the
2014 kcalloc(1, 2, GFP_KERNEL);
2016 kcalloc(1, 2, GFP_KERNEL);
2018 } else { /* ASCII */
2019 len = strnlen(bcc_ptr, 1024);
2020 if (((long) bcc_ptr + len) - (long)
2021 pByteArea(smb_buffer_response)
2022 <= BCC(smb_buffer_response)) {
2023 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
2024 if(ses->serverOS == NULL)
2025 goto sesssetup_nomem;
2026 strncpy(ses->serverOS,bcc_ptr, len);
2029 bcc_ptr[0] = 0; /* null terminate the string */
2032 len = strnlen(bcc_ptr, 1024);
2033 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2034 if(ses->serverNOS == NULL)
2035 goto sesssetup_nomem;
2036 strncpy(ses->serverNOS, bcc_ptr, len);
2041 len = strnlen(bcc_ptr, 1024);
2042 ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL);
2043 if(ses->serverDomain == NULL)
2044 goto sesssetup_nomem;
2045 strncpy(ses->serverDomain, bcc_ptr, len);
2051 ("Variable field of length %d extends beyond end of smb ",
2056 (" Security Blob Length extends beyond end of SMB"));
2060 (" Invalid Word count %d: ",
2061 smb_buffer_response->WordCount));
2064 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2065 since that could make reconnection harder, and
2066 reconnection might be needed to free memory */
2068 cifs_buf_release(smb_buffer);
2074 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2075 char *SecurityBlob,int SecurityBlobLength,
2076 const struct nls_table *nls_codepage)
2078 struct smb_hdr *smb_buffer;
2079 struct smb_hdr *smb_buffer_response;
2080 SESSION_SETUP_ANDX *pSMB;
2081 SESSION_SETUP_ANDX *pSMBr;
2086 int remaining_words = 0;
2087 int bytes_returned = 0;
2092 cFYI(1, ("In spnego sesssetup "));
2095 user = ses->userName;
2096 domain = ses->domainName;
2098 smb_buffer = cifs_buf_get();
2099 if (smb_buffer == NULL) {
2102 smb_buffer_response = smb_buffer;
2103 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2105 /* send SMBsessionSetup here */
2106 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2107 NULL /* no tCon exists yet */ , 12 /* wct */ );
2108 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2109 pSMB->req.AndXCommand = 0xFF;
2110 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2111 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2113 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2114 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2116 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2117 CAP_EXTENDED_SECURITY;
2118 if (ses->capabilities & CAP_UNICODE) {
2119 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2120 capabilities |= CAP_UNICODE;
2122 if (ses->capabilities & CAP_STATUS32) {
2123 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2124 capabilities |= CAP_STATUS32;
2126 if (ses->capabilities & CAP_DFS) {
2127 smb_buffer->Flags2 |= SMBFLG2_DFS;
2128 capabilities |= CAP_DFS;
2130 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2132 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2133 bcc_ptr = pByteArea(smb_buffer);
2134 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2135 bcc_ptr += SecurityBlobLength;
2137 if (ses->capabilities & CAP_UNICODE) {
2138 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2143 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
2144 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2145 bcc_ptr += 2; /* trailing null */
2148 cifs_strtoUCS((wchar_t *) bcc_ptr,
2149 "CIFS_LINUX_DOM", 32, nls_codepage);
2152 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2154 bcc_ptr += 2 * bytes_returned;
2157 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2159 bcc_ptr += 2 * bytes_returned;
2161 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2163 bcc_ptr += 2 * bytes_returned;
2166 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2168 bcc_ptr += 2 * bytes_returned;
2171 strncpy(bcc_ptr, user, 200);
2172 bcc_ptr += strnlen(user, 200);
2175 if (domain == NULL) {
2176 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2177 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2179 strncpy(bcc_ptr, domain, 64);
2180 bcc_ptr += strnlen(domain, 64);
2184 strcpy(bcc_ptr, "Linux version ");
2185 bcc_ptr += strlen("Linux version ");
2186 strcpy(bcc_ptr, system_utsname.release);
2187 bcc_ptr += strlen(system_utsname.release) + 1;
2188 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2189 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2191 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2192 smb_buffer->smb_buf_length += count;
2193 pSMB->req.ByteCount = cpu_to_le16(count);
2195 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2196 &bytes_returned, 1);
2198 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2199 } else if ((smb_buffer_response->WordCount == 3)
2200 || (smb_buffer_response->WordCount == 4)) {
2201 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2203 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2204 if (action & GUEST_LOGIN)
2205 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2207 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2208 cFYI(1, ("UID = %d ", ses->Suid));
2209 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2211 /* BB Fix below to make endian neutral !! */
2213 if ((pSMBr->resp.hdr.WordCount == 3)
2214 || ((pSMBr->resp.hdr.WordCount == 4)
2216 pSMBr->resp.ByteCount))) {
2217 if (pSMBr->resp.hdr.WordCount == 4) {
2221 ("Security Blob Length %d ",
2225 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2226 if ((long) (bcc_ptr) % 2) {
2228 (BCC(smb_buffer_response)
2230 bcc_ptr++; /* Unicode strings must be word aligned */
2234 (smb_buffer_response) / 2;
2237 UniStrnlen((wchar_t *) bcc_ptr,
2238 remaining_words - 1);
2239 /* We look for obvious messed up bcc or strings in response so we do not go off
2240 the end since (at least) WIN2K and Windows XP have a major bug in not null
2241 terminating last Unicode string in response */
2243 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2244 cifs_strfromUCS_le(ses->serverOS,
2248 bcc_ptr += 2 * (len + 1);
2249 remaining_words -= len + 1;
2250 ses->serverOS[2 * len] = 0;
2251 ses->serverOS[1 + (2 * len)] = 0;
2252 if (remaining_words > 0) {
2253 len = UniStrnlen((wchar_t *)bcc_ptr,
2257 kcalloc(1, 2 * (len + 1),
2259 cifs_strfromUCS_le(ses->serverNOS,
2263 bcc_ptr += 2 * (len + 1);
2264 ses->serverNOS[2 * len] = 0;
2265 ses->serverNOS[1 + (2 * len)] = 0;
2266 remaining_words -= len + 1;
2267 if (remaining_words > 0) {
2268 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2269 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2270 ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL);
2271 cifs_strfromUCS_le(ses->serverDomain,
2275 bcc_ptr += 2*(len+1);
2276 ses->serverDomain[2*len] = 0;
2277 ses->serverDomain[1+(2*len)] = 0;
2278 } /* else no more room so create dummy domain string */
2281 kcalloc(1, 2,GFP_KERNEL);
2282 } else { /* no room so create dummy domain and NOS string */
2283 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
2284 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
2286 } else { /* ASCII */
2288 len = strnlen(bcc_ptr, 1024);
2289 if (((long) bcc_ptr + len) - (long)
2290 pByteArea(smb_buffer_response)
2291 <= BCC(smb_buffer_response)) {
2292 ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL);
2293 strncpy(ses->serverOS, bcc_ptr, len);
2296 bcc_ptr[0] = 0; /* null terminate the string */
2299 len = strnlen(bcc_ptr, 1024);
2300 ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL);
2301 strncpy(ses->serverNOS, bcc_ptr, len);
2306 len = strnlen(bcc_ptr, 1024);
2307 ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL);
2308 strncpy(ses->serverDomain, bcc_ptr, len);
2314 ("Variable field of length %d extends beyond end of smb ",
2319 (" Security Blob Length extends beyond end of SMB"));
2322 cERROR(1, ("No session structure passed in."));
2326 (" Invalid Word count %d: ",
2327 smb_buffer_response->WordCount));
2332 cifs_buf_release(smb_buffer);
2338 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2339 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2340 const struct nls_table *nls_codepage)
2342 struct smb_hdr *smb_buffer;
2343 struct smb_hdr *smb_buffer_response;
2344 SESSION_SETUP_ANDX *pSMB;
2345 SESSION_SETUP_ANDX *pSMBr;
2349 int remaining_words = 0;
2350 int bytes_returned = 0;
2352 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2353 PNEGOTIATE_MESSAGE SecurityBlob;
2354 PCHALLENGE_MESSAGE SecurityBlob2;
2355 __u32 negotiate_flags, capabilities;
2358 cFYI(1, ("In NTLMSSP sesssetup (negotiate) "));
2361 domain = ses->domainName;
2362 *pNTLMv2_flag = FALSE;
2363 smb_buffer = cifs_buf_get();
2364 if (smb_buffer == NULL) {
2367 smb_buffer_response = smb_buffer;
2368 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2369 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2371 /* send SMBsessionSetup here */
2372 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2373 NULL /* no tCon exists yet */ , 12 /* wct */ );
2374 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2375 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2377 pSMB->req.AndXCommand = 0xFF;
2378 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2379 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2381 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2382 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2384 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2385 CAP_EXTENDED_SECURITY;
2386 if (ses->capabilities & CAP_UNICODE) {
2387 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2388 capabilities |= CAP_UNICODE;
2390 if (ses->capabilities & CAP_STATUS32) {
2391 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2392 capabilities |= CAP_STATUS32;
2394 if (ses->capabilities & CAP_DFS) {
2395 smb_buffer->Flags2 |= SMBFLG2_DFS;
2396 capabilities |= CAP_DFS;
2398 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2400 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2401 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2402 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2403 SecurityBlob->MessageType = NtLmNegotiate;
2405 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2406 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | 0x80000000 |
2407 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2409 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2411 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2412 /* setup pointers to domain name and workstation name */
2413 bcc_ptr += SecurityBlobLength;
2415 SecurityBlob->WorkstationName.Buffer = 0;
2416 SecurityBlob->WorkstationName.Length = 0;
2417 SecurityBlob->WorkstationName.MaximumLength = 0;
2419 if (domain == NULL) {
2420 SecurityBlob->DomainName.Buffer = 0;
2421 SecurityBlob->DomainName.Length = 0;
2422 SecurityBlob->DomainName.MaximumLength = 0;
2425 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2426 strncpy(bcc_ptr, domain, 63);
2427 len = strnlen(domain, 64);
2428 SecurityBlob->DomainName.MaximumLength =
2430 SecurityBlob->DomainName.Buffer =
2431 cpu_to_le32((long) &SecurityBlob->
2433 (long) &SecurityBlob->Signature);
2435 SecurityBlobLength += len;
2436 SecurityBlob->DomainName.Length =
2439 if (ses->capabilities & CAP_UNICODE) {
2440 if ((long) bcc_ptr % 2) {
2446 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2448 bcc_ptr += 2 * bytes_returned;
2450 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2452 bcc_ptr += 2 * bytes_returned;
2453 bcc_ptr += 2; /* null terminate Linux version */
2455 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2457 bcc_ptr += 2 * bytes_returned;
2460 bcc_ptr += 2; /* null terminate network opsys string */
2463 bcc_ptr += 2; /* null domain */
2464 } else { /* ASCII */
2465 strcpy(bcc_ptr, "Linux version ");
2466 bcc_ptr += strlen("Linux version ");
2467 strcpy(bcc_ptr, system_utsname.release);
2468 bcc_ptr += strlen(system_utsname.release) + 1;
2469 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2470 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2471 bcc_ptr++; /* empty domain field */
2474 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2475 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2476 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2477 smb_buffer->smb_buf_length += count;
2478 pSMB->req.ByteCount = cpu_to_le16(count);
2480 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2481 &bytes_returned, 1);
2483 if (smb_buffer_response->Status.CifsError ==
2484 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2488 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2489 } else if ((smb_buffer_response->WordCount == 3)
2490 || (smb_buffer_response->WordCount == 4)) {
2491 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2492 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2494 if (action & GUEST_LOGIN)
2495 cFYI(1, (" Guest login"));
2496 /* Do we want to set anything in SesInfo struct when guest login? */
2498 bcc_ptr = pByteArea(smb_buffer_response);
2499 /* response can have either 3 or 4 word count - Samba sends 3 */
2501 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2502 if (SecurityBlob2->MessageType != NtLmChallenge) {
2504 ("Unexpected NTLMSSP message type received %d",
2505 SecurityBlob2->MessageType));
2507 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2508 cFYI(1, ("UID = %d ", ses->Suid));
2509 if ((pSMBr->resp.hdr.WordCount == 3)
2510 || ((pSMBr->resp.hdr.WordCount == 4)
2512 pSMBr->resp.ByteCount))) {
2514 if (pSMBr->resp.hdr.WordCount == 4) {
2515 bcc_ptr += blob_len;
2517 ("Security Blob Length %d ",
2521 cFYI(1, ("NTLMSSP Challenge rcvd "));
2523 memcpy(ses->server->cryptKey,
2524 SecurityBlob2->Challenge,
2525 CIFS_CRYPTO_KEY_SIZE);
2526 if(SecurityBlob2->NegotiateFlags & cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2527 *pNTLMv2_flag = TRUE;
2529 if((SecurityBlob2->NegotiateFlags &
2530 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2531 || (sign_CIFS_PDUs > 1))
2532 ses->server->secMode |=
2533 SECMODE_SIGN_REQUIRED;
2534 if ((SecurityBlob2->NegotiateFlags &
2535 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2536 ses->server->secMode |=
2537 SECMODE_SIGN_ENABLED;
2539 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2540 if ((long) (bcc_ptr) % 2) {
2542 (BCC(smb_buffer_response)
2544 bcc_ptr++; /* Unicode strings must be word aligned */
2548 (smb_buffer_response) / 2;
2551 UniStrnlen((wchar_t *) bcc_ptr,
2552 remaining_words - 1);
2553 /* We look for obvious messed up bcc or strings in response so we do not go off
2554 the end since (at least) WIN2K and Windows XP have a major bug in not null
2555 terminating last Unicode string in response */
2557 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2558 cifs_strfromUCS_le(ses->serverOS,
2562 bcc_ptr += 2 * (len + 1);
2563 remaining_words -= len + 1;
2564 ses->serverOS[2 * len] = 0;
2565 ses->serverOS[1 + (2 * len)] = 0;
2566 if (remaining_words > 0) {
2567 len = UniStrnlen((wchar_t *)
2572 kcalloc(1, 2 * (len + 1),
2574 cifs_strfromUCS_le(ses->
2580 bcc_ptr += 2 * (len + 1);
2581 ses->serverNOS[2 * len] = 0;
2584 remaining_words -= len + 1;
2585 if (remaining_words > 0) {
2586 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2587 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2612 } /* else no more room so create dummy domain string */
2617 } else { /* no room so create dummy domain and NOS string */
2619 kcalloc(1, 2, GFP_KERNEL);
2621 kcalloc(1, 2, GFP_KERNEL);
2623 } else { /* ASCII */
2624 len = strnlen(bcc_ptr, 1024);
2625 if (((long) bcc_ptr + len) - (long)
2626 pByteArea(smb_buffer_response)
2627 <= BCC(smb_buffer_response)) {
2631 strncpy(ses->serverOS,
2635 bcc_ptr[0] = 0; /* null terminate string */
2638 len = strnlen(bcc_ptr, 1024);
2642 strncpy(ses->serverNOS, bcc_ptr, len);
2647 len = strnlen(bcc_ptr, 1024);
2651 strncpy(ses->serverDomain, bcc_ptr, len);
2657 ("Variable field of length %d extends beyond end of smb ",
2662 (" Security Blob Length extends beyond end of SMB"));
2665 cERROR(1, ("No session structure passed in."));
2669 (" Invalid Word count %d: ",
2670 smb_buffer_response->WordCount));
2675 cifs_buf_release(smb_buffer);
2680 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2681 char *ntlm_session_key, int ntlmv2_flag,
2682 const struct nls_table *nls_codepage)
2684 struct smb_hdr *smb_buffer;
2685 struct smb_hdr *smb_buffer_response;
2686 SESSION_SETUP_ANDX *pSMB;
2687 SESSION_SETUP_ANDX *pSMBr;
2692 int remaining_words = 0;
2693 int bytes_returned = 0;
2695 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2696 PAUTHENTICATE_MESSAGE SecurityBlob;
2697 __u32 negotiate_flags, capabilities;
2700 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2703 user = ses->userName;
2704 domain = ses->domainName;
2705 smb_buffer = cifs_buf_get();
2706 if (smb_buffer == NULL) {
2709 smb_buffer_response = smb_buffer;
2710 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2711 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2713 /* send SMBsessionSetup here */
2714 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2715 NULL /* no tCon exists yet */ , 12 /* wct */ );
2716 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2717 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2718 pSMB->req.AndXCommand = 0xFF;
2719 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2720 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2722 pSMB->req.hdr.Uid = ses->Suid;
2724 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2725 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2727 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2728 CAP_EXTENDED_SECURITY;
2729 if (ses->capabilities & CAP_UNICODE) {
2730 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2731 capabilities |= CAP_UNICODE;
2733 if (ses->capabilities & CAP_STATUS32) {
2734 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2735 capabilities |= CAP_STATUS32;
2737 if (ses->capabilities & CAP_DFS) {
2738 smb_buffer->Flags2 |= SMBFLG2_DFS;
2739 capabilities |= CAP_DFS;
2741 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2743 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2744 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2745 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2746 SecurityBlob->MessageType = NtLmAuthenticate;
2747 bcc_ptr += SecurityBlobLength;
2749 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2750 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2751 0x80000000 | NTLMSSP_NEGOTIATE_128;
2753 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2755 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2757 /* setup pointers to domain name and workstation name */
2759 SecurityBlob->WorkstationName.Buffer = 0;
2760 SecurityBlob->WorkstationName.Length = 0;
2761 SecurityBlob->WorkstationName.MaximumLength = 0;
2762 SecurityBlob->SessionKey.Length = 0;
2763 SecurityBlob->SessionKey.MaximumLength = 0;
2764 SecurityBlob->SessionKey.Buffer = 0;
2766 SecurityBlob->LmChallengeResponse.Length = 0;
2767 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2768 SecurityBlob->LmChallengeResponse.Buffer = 0;
2770 SecurityBlob->NtChallengeResponse.Length =
2771 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2772 SecurityBlob->NtChallengeResponse.MaximumLength =
2773 cpu_to_le16(CIFS_SESSION_KEY_SIZE);
2774 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
2775 SecurityBlob->NtChallengeResponse.Buffer =
2776 cpu_to_le32(SecurityBlobLength);
2777 SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
2778 bcc_ptr += CIFS_SESSION_KEY_SIZE;
2780 if (ses->capabilities & CAP_UNICODE) {
2781 if (domain == NULL) {
2782 SecurityBlob->DomainName.Buffer = 0;
2783 SecurityBlob->DomainName.Length = 0;
2784 SecurityBlob->DomainName.MaximumLength = 0;
2787 cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
2790 SecurityBlob->DomainName.MaximumLength =
2792 SecurityBlob->DomainName.Buffer =
2793 cpu_to_le32(SecurityBlobLength);
2795 SecurityBlobLength += len;
2796 SecurityBlob->DomainName.Length =
2800 SecurityBlob->UserName.Buffer = 0;
2801 SecurityBlob->UserName.Length = 0;
2802 SecurityBlob->UserName.MaximumLength = 0;
2805 cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
2808 SecurityBlob->UserName.MaximumLength =
2810 SecurityBlob->UserName.Buffer =
2811 cpu_to_le32(SecurityBlobLength);
2813 SecurityBlobLength += len;
2814 SecurityBlob->UserName.Length =
2818 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
2819 SecurityBlob->WorkstationName.Length *= 2;
2820 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2821 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2822 bcc_ptr += SecurityBlob->WorkstationName.Length;
2823 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2824 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2826 if ((long) bcc_ptr % 2) {
2831 cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
2833 bcc_ptr += 2 * bytes_returned;
2835 cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
2837 bcc_ptr += 2 * bytes_returned;
2838 bcc_ptr += 2; /* null term version string */
2840 cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
2842 bcc_ptr += 2 * bytes_returned;
2845 bcc_ptr += 2; /* null terminate network opsys string */
2848 bcc_ptr += 2; /* null domain */
2849 } else { /* ASCII */
2850 if (domain == NULL) {
2851 SecurityBlob->DomainName.Buffer = 0;
2852 SecurityBlob->DomainName.Length = 0;
2853 SecurityBlob->DomainName.MaximumLength = 0;
2856 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2857 strncpy(bcc_ptr, domain, 63);
2858 len = strnlen(domain, 64);
2859 SecurityBlob->DomainName.MaximumLength =
2861 SecurityBlob->DomainName.Buffer =
2862 cpu_to_le32(SecurityBlobLength);
2864 SecurityBlobLength += len;
2865 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2868 SecurityBlob->UserName.Buffer = 0;
2869 SecurityBlob->UserName.Length = 0;
2870 SecurityBlob->UserName.MaximumLength = 0;
2873 strncpy(bcc_ptr, user, 63);
2874 len = strnlen(user, 64);
2875 SecurityBlob->UserName.MaximumLength =
2877 SecurityBlob->UserName.Buffer =
2878 cpu_to_le32(SecurityBlobLength);
2880 SecurityBlobLength += len;
2881 SecurityBlob->UserName.Length = cpu_to_le16(len);
2883 /* BB fill in our workstation name if known BB */
2885 strcpy(bcc_ptr, "Linux version ");
2886 bcc_ptr += strlen("Linux version ");
2887 strcpy(bcc_ptr, system_utsname.release);
2888 bcc_ptr += strlen(system_utsname.release) + 1;
2889 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2890 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2891 bcc_ptr++; /* null domain */
2894 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2895 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2896 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2897 smb_buffer->smb_buf_length += count;
2898 pSMB->req.ByteCount = cpu_to_le16(count);
2900 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2901 &bytes_returned, 1);
2903 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2904 } else if ((smb_buffer_response->WordCount == 3)
2905 || (smb_buffer_response->WordCount == 4)) {
2906 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2908 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2909 if (action & GUEST_LOGIN)
2910 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2911 /* if(SecurityBlob2->MessageType != NtLm??){
2912 cFYI("Unexpected message type on auth response is %d "));
2916 ("Does UID on challenge %d match auth response UID %d ",
2917 ses->Suid, smb_buffer_response->Uid));
2918 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
2919 bcc_ptr = pByteArea(smb_buffer_response);
2920 /* response can have either 3 or 4 word count - Samba sends 3 */
2921 if ((pSMBr->resp.hdr.WordCount == 3)
2922 || ((pSMBr->resp.hdr.WordCount == 4)
2924 pSMBr->resp.ByteCount))) {
2925 if (pSMBr->resp.hdr.WordCount == 4) {
2929 ("Security Blob Length %d ",
2934 ("NTLMSSP response to Authenticate "));
2936 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2937 if ((long) (bcc_ptr) % 2) {
2939 (BCC(smb_buffer_response)
2941 bcc_ptr++; /* Unicode strings must be word aligned */
2943 remaining_words = BCC(smb_buffer_response) / 2;
2946 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
2947 /* We look for obvious messed up bcc or strings in response so we do not go off
2948 the end since (at least) WIN2K and Windows XP have a major bug in not null
2949 terminating last Unicode string in response */
2951 kcalloc(1, 2 * (len + 1), GFP_KERNEL);
2952 cifs_strfromUCS_le(ses->serverOS,
2956 bcc_ptr += 2 * (len + 1);
2957 remaining_words -= len + 1;
2958 ses->serverOS[2 * len] = 0;
2959 ses->serverOS[1 + (2 * len)] = 0;
2960 if (remaining_words > 0) {
2961 len = UniStrnlen((wchar_t *)
2966 kcalloc(1, 2 * (len + 1),
2968 cifs_strfromUCS_le(ses->
2974 bcc_ptr += 2 * (len + 1);
2975 ses->serverNOS[2 * len] = 0;
2976 ses->serverNOS[1+(2*len)] = 0;
2977 remaining_words -= len + 1;
2978 if (remaining_words > 0) {
2979 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2980 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3005 } /* else no more room so create dummy domain string */
3007 ses->serverDomain = kcalloc(1, 2,GFP_KERNEL);
3008 } else { /* no room so create dummy domain and NOS string */
3009 ses->serverDomain = kcalloc(1, 2, GFP_KERNEL);
3010 ses->serverNOS = kcalloc(1, 2, GFP_KERNEL);
3012 } else { /* ASCII */
3013 len = strnlen(bcc_ptr, 1024);
3014 if (((long) bcc_ptr + len) -
3015 (long) pByteArea(smb_buffer_response)
3016 <= BCC(smb_buffer_response)) {
3017 ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL);
3018 strncpy(ses->serverOS,bcc_ptr, len);
3021 bcc_ptr[0] = 0; /* null terminate the string */
3024 len = strnlen(bcc_ptr, 1024);
3025 ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL);
3026 strncpy(ses->serverNOS, bcc_ptr, len);
3031 len = strnlen(bcc_ptr, 1024);
3032 ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL);
3033 strncpy(ses->serverDomain, bcc_ptr, len);
3039 ("Variable field of length %d extends beyond end of smb ",
3044 (" Security Blob Length extends beyond end of SMB"));
3047 cERROR(1, ("No session structure passed in."));
3051 (" Invalid Word count %d: ",
3052 smb_buffer_response->WordCount));
3057 cifs_buf_release(smb_buffer);
3063 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3064 const char *tree, struct cifsTconInfo *tcon,
3065 const struct nls_table *nls_codepage)
3067 struct smb_hdr *smb_buffer;
3068 struct smb_hdr *smb_buffer_response;
3071 unsigned char *bcc_ptr;
3079 smb_buffer = cifs_buf_get();
3080 if (smb_buffer == NULL) {
3083 smb_buffer_response = smb_buffer;
3085 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3086 NULL /*no tid */ , 4 /*wct */ );
3087 smb_buffer->Uid = ses->Suid;
3088 pSMB = (TCONX_REQ *) smb_buffer;
3089 pSMBr = (TCONX_RSP *) smb_buffer_response;
3091 pSMB->AndXCommand = 0xFF;
3092 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3093 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3094 bcc_ptr = &pSMB->Password[0];
3095 bcc_ptr++; /* skip password */
3097 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3098 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3100 if (ses->capabilities & CAP_STATUS32) {
3101 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3103 if (ses->capabilities & CAP_DFS) {
3104 smb_buffer->Flags2 |= SMBFLG2_DFS;
3106 if (ses->capabilities & CAP_UNICODE) {
3107 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3109 cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
3110 bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
3111 bcc_ptr += 2; /* skip trailing null */
3112 } else { /* ASCII */
3114 strcpy(bcc_ptr, tree);
3115 bcc_ptr += strlen(tree) + 1;
3117 strcpy(bcc_ptr, "?????");
3118 bcc_ptr += strlen("?????");
3120 count = bcc_ptr - &pSMB->Password[0];
3121 pSMB->hdr.smb_buf_length += count;
3122 pSMB->ByteCount = cpu_to_le16(count);
3124 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3126 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3127 /* above now done in SendReceive */
3128 if ((rc == 0) && (tcon != NULL)) {
3129 tcon->tidStatus = CifsGood;
3130 tcon->tid = smb_buffer_response->Tid;
3131 bcc_ptr = pByteArea(smb_buffer_response);
3132 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3133 /* skip service field (NB: this field is always ASCII) */
3134 bcc_ptr += length + 1;
3135 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3136 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3137 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3138 if ((bcc_ptr + (2 * length)) -
3139 pByteArea(smb_buffer_response) <=
3140 BCC(smb_buffer_response)) {
3141 if(tcon->nativeFileSystem)
3142 kfree(tcon->nativeFileSystem);
3143 tcon->nativeFileSystem =
3144 kcalloc(1, length + 2, GFP_KERNEL);
3145 cifs_strfromUCS_le(tcon->nativeFileSystem,
3146 (wchar_t *) bcc_ptr,
3147 length, nls_codepage);
3148 bcc_ptr += 2 * length;
3149 bcc_ptr[0] = 0; /* null terminate the string */
3153 /* else do not bother copying these informational fields */
3155 length = strnlen(bcc_ptr, 1024);
3156 if ((bcc_ptr + length) -
3157 pByteArea(smb_buffer_response) <=
3158 BCC(smb_buffer_response)) {
3159 if(tcon->nativeFileSystem)
3160 kfree(tcon->nativeFileSystem);
3161 tcon->nativeFileSystem =
3162 kcalloc(1, length + 1, GFP_KERNEL);
3163 strncpy(tcon->nativeFileSystem, bcc_ptr,
3166 /* else do not bother copying these informational fields */
3168 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3169 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3170 } else if ((rc == 0) && tcon == NULL) {
3171 /* all we need to save for IPC$ connection */
3172 ses->ipc_tid = smb_buffer_response->Tid;
3176 cifs_buf_release(smb_buffer);
3181 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3185 struct cifsSesInfo *ses = NULL;
3186 struct task_struct *cifsd_task;
3190 if (cifs_sb->tcon) {
3191 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3192 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3197 tconInfoFree(cifs_sb->tcon);
3198 if ((ses) && (ses->server)) {
3199 /* save off task so we do not refer to ses later */
3200 cifsd_task = ses->server->tsk;
3201 cFYI(1, ("About to do SMBLogoff "));
3202 rc = CIFSSMBLogoff(xid, ses);
3206 } else if (rc == -ESHUTDOWN) {
3207 cFYI(1,("Waking up socket by sending it signal"));
3209 send_sig(SIGKILL,cifsd_task,1);
3211 } /* else - we have an smb session
3212 left on this socket do not kill cifsd */
3214 cFYI(1, ("No session or bad tcon"));
3217 cifs_sb->tcon = NULL;
3219 set_current_state(TASK_INTERRUPTIBLE);
3220 schedule_timeout(HZ / 2);
3226 return rc; /* BB check if we should always return zero here */
3229 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3230 struct nls_table * nls_info)
3233 char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
3234 int ntlmv2_flag = FALSE;
3237 /* what if server changes its buffer size after dropping the session? */
3238 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3239 rc = CIFSSMBNegotiate(xid, pSesInfo);
3240 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3241 rc = CIFSSMBNegotiate(xid, pSesInfo);
3246 spin_lock(&GlobalMid_Lock);
3247 if(pSesInfo->server->tcpStatus != CifsExiting)
3248 pSesInfo->server->tcpStatus = CifsGood;
3251 spin_unlock(&GlobalMid_Lock);
3257 pSesInfo->capabilities = pSesInfo->server->capabilities;
3258 if(linuxExtEnabled == 0)
3259 pSesInfo->capabilities &= (~CAP_UNIX);
3260 /* pSesInfo->sequence_number = 0;*/
3261 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3262 pSesInfo->server->secMode,
3263 pSesInfo->server->capabilities,
3264 pSesInfo->server->timeZone));
3265 if (extended_security
3266 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3267 && (pSesInfo->server->secType == NTLMSSP)) {
3268 cFYI(1, ("New style sesssetup "));
3269 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3270 NULL /* security blob */,
3271 0 /* blob length */,
3273 } else if (extended_security
3274 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3275 && (pSesInfo->server->secType == RawNTLMSSP)) {
3276 cFYI(1, ("NTLMSSP sesssetup "));
3277 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3284 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3285 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3290 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3292 CalcNTLMv2_response(pSesInfo,v2_response);
3294 cifs_calculate_ntlmv2_mac_key(
3295 pSesInfo->server->mac_signing_key,
3296 response, ntlm_session_key, */
3298 /* BB Put dummy sig in SessSetup PDU? */
3305 SMBNTencrypt(pSesInfo->password,
3306 pSesInfo->server->cryptKey,
3310 cifs_calculate_mac_key(
3311 pSesInfo->server->mac_signing_key,
3313 pSesInfo->password);
3315 /* for better security the weaker lanman hash not sent
3316 in AuthSessSetup so we no longer calculate it */
3318 rc = CIFSNTLMSSPAuthSessSetup(xid,
3324 } else { /* old style NTLM 0.12 session setup */
3325 SMBNTencrypt(pSesInfo->password,
3326 pSesInfo->server->cryptKey,
3330 cifs_calculate_mac_key(
3331 pSesInfo->server->mac_signing_key,
3332 ntlm_session_key, pSesInfo->password);
3334 rc = CIFSSessSetup(xid, pSesInfo,
3335 ntlm_session_key, nls_info);
3338 cERROR(1,("Send error in SessSetup = %d",rc));
3340 cFYI(1,("CIFS Session Established successfully"));
3341 pSesInfo->status = CifsGood;