4 * Copyright (C) International Business Machines Corp., 2002,2006
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <linux/net.h>
23 #include <linux/string.h>
24 #include <linux/list.h>
25 #include <linux/wait.h>
26 #include <linux/ipv6.h>
27 #include <linux/pagemap.h>
28 #include <linux/ctype.h>
29 #include <linux/utsname.h>
30 #include <linux/mempool.h>
31 #include <linux/delay.h>
32 #include <linux/completion.h>
33 #include <linux/pagevec.h>
34 #include <asm/uaccess.h>
35 #include <asm/processor.h>
38 #include "cifsproto.h"
39 #include "cifs_unicode.h"
40 #include "cifs_debug.h"
41 #include "cifs_fs_sb.h"
44 #include "rfc1002pdu.h"
48 #define RFC1001_PORT 139
50 static DECLARE_COMPLETION(cifsd_complete);
52 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
55 extern mempool_t *cifs_req_poolp;
63 char *in6_addr; /* ipv6 address as human readable form of in6_addr */
64 char *iocharset; /* local code page for mapping to and from Unicode */
65 char source_rfc1001_name[16]; /* netbios name of client */
66 char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
76 unsigned no_psx_acl:1; /* set if posix acl support should be disabled */
78 unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/
79 unsigned server_ino:1; /* use inode numbers from server ie UniqueId */
81 unsigned remap:1; /* set to remap seven reserved chars in filenames */
82 unsigned posix_paths:1; /* unset to not ask for posix pathnames. */
87 unsigned nullauth:1; /* attempt to authenticate with null user */
89 unsigned seal:1; /* encrypt */
90 unsigned nocase; /* request case insensitive filenames */
91 unsigned nobrl; /* disable sending byte range locks to srv */
95 unsigned short int port;
98 static int ipv4_connect(struct sockaddr_in *psin_server,
99 struct socket **csocket,
101 char * server_netb_name);
102 static int ipv6_connect(struct sockaddr_in6 *psin_server,
103 struct socket **csocket);
107 * cifs tcp session reconnection
109 * mark tcp session as reconnecting so temporarily locked
110 * mark all smb sessions as reconnecting for tcp session
111 * reconnect tcp session
112 * wake up waiters on reconnection? - (not needed currently)
116 cifs_reconnect(struct TCP_Server_Info *server)
119 struct list_head *tmp;
120 struct cifsSesInfo *ses;
121 struct cifsTconInfo *tcon;
122 struct mid_q_entry * mid_entry;
124 spin_lock(&GlobalMid_Lock);
125 if(server->tcpStatus == CifsExiting) {
126 /* the demux thread will exit normally
127 next time through the loop */
128 spin_unlock(&GlobalMid_Lock);
131 server->tcpStatus = CifsNeedReconnect;
132 spin_unlock(&GlobalMid_Lock);
135 cFYI(1, ("Reconnecting tcp session"));
137 /* before reconnecting the tcp session, mark the smb session (uid)
138 and the tid bad so they are not used until reconnected */
139 read_lock(&GlobalSMBSeslock);
140 list_for_each(tmp, &GlobalSMBSessionList) {
141 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
143 if (ses->server == server) {
144 ses->status = CifsNeedReconnect;
148 /* else tcp and smb sessions need reconnection */
150 list_for_each(tmp, &GlobalTreeConnectionList) {
151 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
152 if((tcon) && (tcon->ses) && (tcon->ses->server == server)) {
153 tcon->tidStatus = CifsNeedReconnect;
156 read_unlock(&GlobalSMBSeslock);
157 /* do not want to be sending data on a socket we are freeing */
158 down(&server->tcpSem);
159 if(server->ssocket) {
160 cFYI(1,("State: 0x%x Flags: 0x%lx", server->ssocket->state,
161 server->ssocket->flags));
162 server->ssocket->ops->shutdown(server->ssocket,SEND_SHUTDOWN);
163 cFYI(1,("Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state,
164 server->ssocket->flags));
165 sock_release(server->ssocket);
166 server->ssocket = NULL;
169 spin_lock(&GlobalMid_Lock);
170 list_for_each(tmp, &server->pending_mid_q) {
171 mid_entry = list_entry(tmp, struct
175 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
176 /* Mark other intransit requests as needing
177 retry so we do not immediately mark the
178 session bad again (ie after we reconnect
179 below) as they timeout too */
180 mid_entry->midState = MID_RETRY_NEEDED;
184 spin_unlock(&GlobalMid_Lock);
187 while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood))
189 if(server->protocolType == IPV6) {
190 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
192 rc = ipv4_connect(&server->addr.sockAddr,
194 server->workstation_RFC1001_name,
195 server->server_RFC1001_name);
198 cFYI(1,("reconnect error %d",rc));
201 atomic_inc(&tcpSesReconnectCount);
202 spin_lock(&GlobalMid_Lock);
203 if(server->tcpStatus != CifsExiting)
204 server->tcpStatus = CifsGood;
205 server->sequence_number = 0;
206 spin_unlock(&GlobalMid_Lock);
207 /* atomic_set(&server->inFlight,0);*/
208 wake_up(&server->response_q);
216 0 not a transact2, or all data present
217 >0 transact2 with that much data missing
218 -EINVAL = invalid transact2
221 static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
223 struct smb_t2_rsp * pSMBt;
225 int data_in_this_rsp;
228 if(pSMB->Command != SMB_COM_TRANSACTION2)
231 /* check for plausible wct, bcc and t2 data and parm sizes */
232 /* check for parm and data offset going beyond end of smb */
233 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
234 cFYI(1,("invalid transact2 word count"));
238 pSMBt = (struct smb_t2_rsp *)pSMB;
240 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
241 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
243 remaining = total_data_size - data_in_this_rsp;
247 else if(remaining < 0) {
248 cFYI(1,("total data %d smaller than data in frame %d",
249 total_data_size, data_in_this_rsp));
252 cFYI(1,("missing %d bytes from transact2, check next response",
254 if(total_data_size > maxBufSize) {
255 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
256 total_data_size,maxBufSize));
263 static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
265 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
266 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
271 char * data_area_of_target;
272 char * data_area_of_buf2;
275 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
277 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
278 cFYI(1,("total data sizes of primary and secondary t2 differ"));
281 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
283 remaining = total_data_size - total_in_buf;
288 if(remaining == 0) /* nothing to do, ignore */
291 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
292 if(remaining < total_in_buf2) {
293 cFYI(1,("transact2 2nd response contains too much data"));
296 /* find end of first SMB data area */
297 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
298 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
299 /* validate target area */
301 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
302 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
304 data_area_of_target += total_in_buf;
306 /* copy second buffer into end of first buffer */
307 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
308 total_in_buf += total_in_buf2;
309 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
310 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
311 byte_count += total_in_buf2;
312 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
314 byte_count = pTargetSMB->smb_buf_length;
315 byte_count += total_in_buf2;
317 /* BB also add check that we are not beyond maximum buffer size */
319 pTargetSMB->smb_buf_length = byte_count;
321 if(remaining == total_in_buf2) {
322 cFYI(1,("found the last secondary response"));
323 return 0; /* we are done */
324 } else /* more responses to go */
330 cifs_demultiplex_thread(struct TCP_Server_Info *server)
333 unsigned int pdu_length, total_read;
334 struct smb_hdr *smb_buffer = NULL;
335 struct smb_hdr *bigbuf = NULL;
336 struct smb_hdr *smallbuf = NULL;
337 struct msghdr smb_msg;
339 struct socket *csocket = server->ssocket;
340 struct list_head *tmp;
341 struct cifsSesInfo *ses;
342 struct task_struct *task_to_wake = NULL;
343 struct mid_q_entry *mid_entry;
345 int isLargeBuf = FALSE;
350 allow_signal(SIGKILL);
351 current->flags |= PF_MEMALLOC;
352 server->tsk = current; /* save process info to wake at shutdown */
353 cFYI(1, ("Demultiplex PID: %d", current->pid));
354 write_lock(&GlobalSMBSeslock);
355 atomic_inc(&tcpSesAllocCount);
356 length = tcpSesAllocCount.counter;
357 write_unlock(&GlobalSMBSeslock);
358 complete(&cifsd_complete);
360 mempool_resize(cifs_req_poolp,
361 length + cifs_min_rcv,
365 while (server->tcpStatus != CifsExiting) {
368 if (bigbuf == NULL) {
369 bigbuf = cifs_buf_get();
371 cERROR(1,("No memory for large SMB response"));
373 /* retry will check if exiting */
376 } else if(isLargeBuf) {
377 /* we are reusing a dirtry large buf, clear its start */
378 memset(bigbuf, 0, sizeof (struct smb_hdr));
381 if (smallbuf == NULL) {
382 smallbuf = cifs_small_buf_get();
383 if(smallbuf == NULL) {
384 cERROR(1,("No memory for SMB response"));
386 /* retry will check if exiting */
389 /* beginning of smb buffer is cleared in our buf_get */
390 } else /* if existing small buf clear beginning */
391 memset(smallbuf, 0, sizeof (struct smb_hdr));
395 smb_buffer = smallbuf;
396 iov.iov_base = smb_buffer;
398 smb_msg.msg_control = NULL;
399 smb_msg.msg_controllen = 0;
401 kernel_recvmsg(csocket, &smb_msg,
402 &iov, 1, 4, 0 /* BB see socket.h flags */);
404 if(server->tcpStatus == CifsExiting) {
406 } else if (server->tcpStatus == CifsNeedReconnect) {
407 cFYI(1,("Reconnect after server stopped responding"));
408 cifs_reconnect(server);
409 cFYI(1,("call to reconnect done"));
410 csocket = server->ssocket;
412 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
413 msleep(1); /* minimum sleep to prevent looping
414 allowing socket to clear and app threads to set
415 tcpStatus CifsNeedReconnect if server hung */
417 } else if (length <= 0) {
418 if(server->tcpStatus == CifsNew) {
419 cFYI(1,("tcp session abend after SMBnegprot"));
420 /* some servers kill the TCP session rather than
421 returning an SMB negprot error, in which
422 case reconnecting here is not going to help,
423 and so simply return error to mount */
426 if(length == -EINTR) {
427 cFYI(1,("cifsd thread killed"));
430 cFYI(1,("Reconnect after unexpected peek error %d",
432 cifs_reconnect(server);
433 csocket = server->ssocket;
434 wake_up(&server->response_q);
436 } else if (length < 4) {
438 ("Frame under four bytes received (%d bytes long)",
440 cifs_reconnect(server);
441 csocket = server->ssocket;
442 wake_up(&server->response_q);
446 /* The right amount was read from socket - 4 bytes */
447 /* so we can now interpret the length field */
449 /* the first byte big endian of the length field,
450 is actually not part of the length but the type
451 with the most common, zero, as regular data */
452 temp = *((char *) smb_buffer);
454 /* Note that FC 1001 length is big endian on the wire,
455 but we convert it here so it is always manipulated
456 as host byte order */
457 pdu_length = ntohl(smb_buffer->smb_buf_length);
458 smb_buffer->smb_buf_length = pdu_length;
460 cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
462 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
464 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
465 cFYI(1,("Good RFC 1002 session rsp"));
467 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
468 /* we get this from Windows 98 instead of
469 an error on SMB negprot response */
470 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
472 if(server->tcpStatus == CifsNew) {
473 /* if nack on negprot (rather than
474 ret of smb negprot error) reconnecting
475 not going to help, ret error to mount */
478 /* give server a second to
479 clean up before reconnect attempt */
481 /* always try 445 first on reconnect
482 since we get NACK on some if we ever
483 connected to port 139 (the NACK is
484 since we do not begin with RFC1001
485 session initialize frame) */
486 server->addr.sockAddr.sin_port =
488 cifs_reconnect(server);
489 csocket = server->ssocket;
490 wake_up(&server->response_q);
493 } else if (temp != (char) 0) {
494 cERROR(1,("Unknown RFC 1002 frame"));
495 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
497 cifs_reconnect(server);
498 csocket = server->ssocket;
502 /* else we have an SMB response */
503 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
504 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
505 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
506 length, pdu_length+4));
507 cifs_reconnect(server);
508 csocket = server->ssocket;
509 wake_up(&server->response_q);
516 if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
518 memcpy(bigbuf, smallbuf, 4);
522 iov.iov_base = 4 + (char *)smb_buffer;
523 iov.iov_len = pdu_length;
524 for (total_read = 0; total_read < pdu_length;
525 total_read += length) {
526 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
527 pdu_length - total_read, 0);
528 if((server->tcpStatus == CifsExiting) ||
529 (length == -EINTR)) {
533 } else if (server->tcpStatus == CifsNeedReconnect) {
534 cifs_reconnect(server);
535 csocket = server->ssocket;
536 /* Reconnect wakes up rspns q */
537 /* Now we will reread sock */
540 } else if ((length == -ERESTARTSYS) ||
541 (length == -EAGAIN)) {
542 msleep(1); /* minimum sleep to prevent looping,
543 allowing socket to clear and app
544 threads to set tcpStatus
545 CifsNeedReconnect if server hung*/
547 } else if (length <= 0) {
548 cERROR(1,("Received no data, expecting %d",
549 pdu_length - total_read));
550 cifs_reconnect(server);
551 csocket = server->ssocket;
558 else if(reconnect == 1)
561 length += 4; /* account for rfc1002 hdr */
564 dump_smb(smb_buffer, length);
565 if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
566 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
572 spin_lock(&GlobalMid_Lock);
573 list_for_each(tmp, &server->pending_mid_q) {
574 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
576 if ((mid_entry->mid == smb_buffer->Mid) &&
577 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
578 (mid_entry->command == smb_buffer->Command)) {
579 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
580 /* We have a multipart transact2 resp */
582 if(mid_entry->resp_buf) {
583 /* merge response - fix up 1st*/
584 if(coalesce_t2(smb_buffer,
585 mid_entry->resp_buf)) {
586 mid_entry->multiRsp = 1;
589 /* all parts received */
590 mid_entry->multiEnd = 1;
595 cERROR(1,("1st trans2 resp needs bigbuf"));
596 /* BB maybe we can fix this up, switch
597 to already allocated large buffer? */
599 /* Have first buffer */
600 mid_entry->resp_buf =
602 mid_entry->largeBuf = 1;
608 mid_entry->resp_buf = smb_buffer;
610 mid_entry->largeBuf = 1;
612 mid_entry->largeBuf = 0;
614 task_to_wake = mid_entry->tsk;
615 mid_entry->midState = MID_RESPONSE_RECEIVED;
616 #ifdef CONFIG_CIFS_STATS2
617 mid_entry->when_received = jiffies;
622 spin_unlock(&GlobalMid_Lock);
624 /* Was previous buf put in mpx struct for multi-rsp? */
626 /* smb buffer will be freed by user thread */
632 wake_up_process(task_to_wake);
633 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
634 && (isMultiRsp == FALSE)) {
635 cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter));
636 cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
637 sizeof(struct smb_hdr));
638 #ifdef CONFIG_CIFS_DEBUG2
639 cifs_dump_detail(smb_buffer);
640 cifs_dump_mids(server);
641 #endif /* CIFS_DEBUG2 */
644 } /* end while !EXITING */
646 spin_lock(&GlobalMid_Lock);
647 server->tcpStatus = CifsExiting;
649 /* check if we have blocked requests that need to free */
650 /* Note that cifs_max_pending is normally 50, but
651 can be set at module install time to as little as two */
652 if(atomic_read(&server->inFlight) >= cifs_max_pending)
653 atomic_set(&server->inFlight, cifs_max_pending - 1);
654 /* We do not want to set the max_pending too low or we
655 could end up with the counter going negative */
656 spin_unlock(&GlobalMid_Lock);
657 /* Although there should not be any requests blocked on
658 this queue it can not hurt to be paranoid and try to wake up requests
659 that may haven been blocked when more than 50 at time were on the wire
660 to the same server - they now will see the session is in exit state
661 and get out of SendReceive. */
662 wake_up_all(&server->request_q);
663 /* give those requests time to exit */
666 if(server->ssocket) {
667 sock_release(csocket);
668 server->ssocket = NULL;
670 /* buffer usuallly freed in free_mid - need to free it here on exit */
672 cifs_buf_release(bigbuf);
673 if (smallbuf != NULL)
674 cifs_small_buf_release(smallbuf);
676 read_lock(&GlobalSMBSeslock);
677 if (list_empty(&server->pending_mid_q)) {
678 /* loop through server session structures attached to this and
680 list_for_each(tmp, &GlobalSMBSessionList) {
682 list_entry(tmp, struct cifsSesInfo,
684 if (ses->server == server) {
685 ses->status = CifsExiting;
689 read_unlock(&GlobalSMBSeslock);
691 /* although we can not zero the server struct pointer yet,
692 since there are active requests which may depnd on them,
693 mark the corresponding SMB sessions as exiting too */
694 list_for_each(tmp, &GlobalSMBSessionList) {
695 ses = list_entry(tmp, struct cifsSesInfo,
697 if (ses->server == server) {
698 ses->status = CifsExiting;
702 spin_lock(&GlobalMid_Lock);
703 list_for_each(tmp, &server->pending_mid_q) {
704 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
705 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
707 ("Clearing Mid 0x%x - waking up ",mid_entry->mid));
708 task_to_wake = mid_entry->tsk;
710 wake_up_process(task_to_wake);
714 spin_unlock(&GlobalMid_Lock);
715 read_unlock(&GlobalSMBSeslock);
716 /* 1/8th of sec is more than enough time for them to exit */
720 if (!list_empty(&server->pending_mid_q)) {
721 /* mpx threads have not exited yet give them
722 at least the smb send timeout time for long ops */
723 /* due to delays on oplock break requests, we need
724 to wait at least 45 seconds before giving up
725 on a request getting a response and going ahead
727 cFYI(1, ("Wait for exit from demultiplex thread"));
729 /* if threads still have not exited they are probably never
730 coming home not much else we can do but free the memory */
733 write_lock(&GlobalSMBSeslock);
734 atomic_dec(&tcpSesAllocCount);
735 length = tcpSesAllocCount.counter;
737 /* last chance to mark ses pointers invalid
738 if there are any pointing to this (e.g
739 if a crazy root user tried to kill cifsd
740 kernel thread explicitly this might happen) */
741 list_for_each(tmp, &GlobalSMBSessionList) {
742 ses = list_entry(tmp, struct cifsSesInfo,
744 if (ses->server == server) {
748 write_unlock(&GlobalSMBSeslock);
752 mempool_resize(cifs_req_poolp,
753 length + cifs_min_rcv,
757 complete_and_exit(&cifsd_complete, 0);
762 cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
766 unsigned int temp_len, i, j;
772 memset(vol->source_rfc1001_name,0x20,15);
773 for(i=0;i < strnlen(system_utsname.nodename,15);i++) {
774 /* does not have to be a perfect mapping since the field is
775 informational, only used for servers that do not support
776 port 445 and it can be overridden at mount time */
777 vol->source_rfc1001_name[i] =
778 toupper(system_utsname.nodename[i]);
780 vol->source_rfc1001_name[15] = 0;
781 /* null target name indicates to use *SMBSERVR default called name
782 if we end up sending RFC1001 session initialize */
783 vol->target_rfc1001_name[0] = 0;
784 vol->linux_uid = current->uid; /* current->euid instead? */
785 vol->linux_gid = current->gid;
786 vol->dir_mode = S_IRWXUGO;
787 /* 2767 perms indicate mandatory locking support */
788 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
790 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
793 /* default is always to request posix paths. */
794 vol->posix_paths = 1;
799 if(strncmp(options,"sep=",4) == 0) {
800 if(options[4] != 0) {
801 separator[0] = options[4];
804 cFYI(1,("Null separator not allowed"));
808 while ((data = strsep(&options, separator)) != NULL) {
811 if ((value = strchr(data, '=')) != NULL)
814 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
816 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
818 } else if (strnicmp(data, "user", 4) == 0) {
819 if (!value || !*value) {
821 "CIFS: invalid or missing username\n");
822 return 1; /* needs_arg; */
824 if (strnlen(value, 200) < 200) {
825 vol->username = value;
827 printk(KERN_WARNING "CIFS: username too long\n");
830 } else if (strnicmp(data, "pass", 4) == 0) {
832 vol->password = NULL;
834 } else if(value[0] == 0) {
835 /* check if string begins with double comma
836 since that would mean the password really
837 does start with a comma, and would not
838 indicate an empty string */
839 if(value[1] != separator[0]) {
840 vol->password = NULL;
844 temp_len = strlen(value);
845 /* removed password length check, NTLM passwords
846 can be arbitrarily long */
848 /* if comma in password, the string will be
849 prematurely null terminated. Commas in password are
850 specified across the cifs mount interface by a double
851 comma ie ,, and a comma used as in other cases ie ','
852 as a parameter delimiter/separator is single and due
853 to the strsep above is temporarily zeroed. */
855 /* NB: password legally can have multiple commas and
856 the only illegal character in a password is null */
858 if ((value[temp_len] == 0) &&
859 (value[temp_len+1] == separator[0])) {
861 value[temp_len] = separator[0];
862 temp_len+=2; /* move after the second comma */
863 while(value[temp_len] != 0) {
864 if (value[temp_len] == separator[0]) {
865 if (value[temp_len+1] ==
867 /* skip second comma */
870 /* single comma indicating start
877 if(value[temp_len] == 0) {
881 /* point option to start of next parm */
882 options = value + temp_len + 1;
884 /* go from value to value + temp_len condensing
885 double commas to singles. Note that this ends up
886 allocating a few bytes too many, which is ok */
887 vol->password = kzalloc(temp_len, GFP_KERNEL);
888 if(vol->password == NULL) {
889 printk("CIFS: no memory for pass\n");
892 for(i=0,j=0;i<temp_len;i++,j++) {
893 vol->password[j] = value[i];
894 if(value[i] == separator[0]
895 && value[i+1] == separator[0]) {
896 /* skip second comma */
900 vol->password[j] = 0;
902 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
903 if(vol->password == NULL) {
904 printk("CIFS: no memory for pass\n");
907 strcpy(vol->password, value);
909 } else if (strnicmp(data, "ip", 2) == 0) {
910 if (!value || !*value) {
912 } else if (strnlen(value, 35) < 35) {
915 printk(KERN_WARNING "CIFS: ip address too long\n");
918 } else if (strnicmp(data, "sec", 3) == 0) {
919 if (!value || !*value) {
920 cERROR(1,("no security value specified"));
922 } else if (strnicmp(value, "krb5i", 5) == 0) {
925 } else if (strnicmp(value, "krb5p", 5) == 0) {
928 cERROR(1,("Krb5 cifs privacy not supported"));
930 } else if (strnicmp(value, "krb5", 4) == 0) {
932 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
935 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
937 } else if (strnicmp(value, "ntlmi", 5) == 0) {
940 } else if (strnicmp(value, "ntlm", 4) == 0) {
941 /* ntlm is default so can be turned off too */
943 } else if (strnicmp(value, "nontlm", 6) == 0) {
945 } else if (strnicmp(value, "none", 4) == 0) {
948 cERROR(1,("bad security option: %s", value));
951 } else if ((strnicmp(data, "unc", 3) == 0)
952 || (strnicmp(data, "target", 6) == 0)
953 || (strnicmp(data, "path", 4) == 0)) {
954 if (!value || !*value) {
956 "CIFS: invalid path to network resource\n");
957 return 1; /* needs_arg; */
959 if ((temp_len = strnlen(value, 300)) < 300) {
960 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
963 strcpy(vol->UNC,value);
964 if (strncmp(vol->UNC, "//", 2) == 0) {
967 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
969 "CIFS: UNC Path does not begin with // or \\\\ \n");
973 printk(KERN_WARNING "CIFS: UNC name too long\n");
976 } else if ((strnicmp(data, "domain", 3) == 0)
977 || (strnicmp(data, "workgroup", 5) == 0)) {
978 if (!value || !*value) {
979 printk(KERN_WARNING "CIFS: invalid domain name\n");
980 return 1; /* needs_arg; */
982 /* BB are there cases in which a comma can be valid in
983 a domain name and need special handling? */
984 if (strnlen(value, 256) < 256) {
985 vol->domainname = value;
986 cFYI(1, ("Domain name set"));
988 printk(KERN_WARNING "CIFS: domain name too long\n");
991 } else if (strnicmp(data, "iocharset", 9) == 0) {
992 if (!value || !*value) {
993 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
994 return 1; /* needs_arg; */
996 if (strnlen(value, 65) < 65) {
997 if(strnicmp(value,"default",7))
998 vol->iocharset = value;
999 /* if iocharset not set load_nls_default used by caller */
1000 cFYI(1, ("iocharset set to %s",value));
1002 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
1005 } else if (strnicmp(data, "uid", 3) == 0) {
1006 if (value && *value) {
1008 simple_strtoul(value, &value, 0);
1010 } else if (strnicmp(data, "gid", 3) == 0) {
1011 if (value && *value) {
1013 simple_strtoul(value, &value, 0);
1015 } else if (strnicmp(data, "file_mode", 4) == 0) {
1016 if (value && *value) {
1018 simple_strtoul(value, &value, 0);
1020 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1021 if (value && *value) {
1023 simple_strtoul(value, &value, 0);
1025 } else if (strnicmp(data, "dirmode", 4) == 0) {
1026 if (value && *value) {
1028 simple_strtoul(value, &value, 0);
1030 } else if (strnicmp(data, "port", 4) == 0) {
1031 if (value && *value) {
1033 simple_strtoul(value, &value, 0);
1035 } else if (strnicmp(data, "rsize", 5) == 0) {
1036 if (value && *value) {
1038 simple_strtoul(value, &value, 0);
1040 } else if (strnicmp(data, "wsize", 5) == 0) {
1041 if (value && *value) {
1043 simple_strtoul(value, &value, 0);
1045 } else if (strnicmp(data, "sockopt", 5) == 0) {
1046 if (value && *value) {
1048 simple_strtoul(value, &value, 0);
1050 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1051 if (!value || !*value || (*value == ' ')) {
1052 cFYI(1,("invalid (empty) netbiosname specified"));
1054 memset(vol->source_rfc1001_name,0x20,15);
1056 /* BB are there cases in which a comma can be
1057 valid in this workstation netbios name (and need
1058 special handling)? */
1060 /* We do not uppercase netbiosname for user */
1064 vol->source_rfc1001_name[i] = value[i];
1066 /* The string has 16th byte zero still from
1067 set at top of the function */
1068 if((i==15) && (value[i] != 0))
1069 printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
1071 } else if (strnicmp(data, "servern", 7) == 0) {
1072 /* servernetbiosname specified override *SMBSERVER */
1073 if (!value || !*value || (*value == ' ')) {
1074 cFYI(1,("empty server netbiosname specified"));
1076 /* last byte, type, is 0x20 for servr type */
1077 memset(vol->target_rfc1001_name,0x20,16);
1080 /* BB are there cases in which a comma can be
1081 valid in this workstation netbios name (and need
1082 special handling)? */
1084 /* user or mount helper must uppercase netbiosname */
1088 vol->target_rfc1001_name[i] = value[i];
1090 /* The string has 16th byte zero still from
1091 set at top of the function */
1092 if((i==15) && (value[i] != 0))
1093 printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
1095 } else if (strnicmp(data, "credentials", 4) == 0) {
1097 } else if (strnicmp(data, "version", 3) == 0) {
1099 } else if (strnicmp(data, "guest",5) == 0) {
1101 } else if (strnicmp(data, "rw", 2) == 0) {
1103 } else if ((strnicmp(data, "suid", 4) == 0) ||
1104 (strnicmp(data, "nosuid", 6) == 0) ||
1105 (strnicmp(data, "exec", 4) == 0) ||
1106 (strnicmp(data, "noexec", 6) == 0) ||
1107 (strnicmp(data, "nodev", 5) == 0) ||
1108 (strnicmp(data, "noauto", 6) == 0) ||
1109 (strnicmp(data, "dev", 3) == 0)) {
1110 /* The mount tool or mount.cifs helper (if present)
1111 uses these opts to set flags, and the flags are read
1112 by the kernel vfs layer before we get here (ie
1113 before read super) so there is no point trying to
1114 parse these options again and set anything and it
1115 is ok to just ignore them */
1117 } else if (strnicmp(data, "ro", 2) == 0) {
1119 } else if (strnicmp(data, "hard", 4) == 0) {
1121 } else if (strnicmp(data, "soft", 4) == 0) {
1123 } else if (strnicmp(data, "perm", 4) == 0) {
1125 } else if (strnicmp(data, "noperm", 6) == 0) {
1127 } else if (strnicmp(data, "mapchars", 8) == 0) {
1129 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1131 } else if (strnicmp(data, "sfu", 3) == 0) {
1133 } else if (strnicmp(data, "nosfu", 5) == 0) {
1135 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1136 vol->posix_paths = 1;
1137 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1138 vol->posix_paths = 0;
1139 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1140 (strnicmp(data, "ignorecase", 10) == 0)) {
1142 } else if (strnicmp(data, "brl", 3) == 0) {
1144 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1145 (strnicmp(data, "nolock", 6) == 0)) {
1147 /* turn off mandatory locking in mode
1148 if remote locking is turned off since the
1149 local vfs will do advisory */
1150 if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1151 vol->file_mode = S_IALLUGO;
1152 } else if (strnicmp(data, "setuids", 7) == 0) {
1154 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1156 } else if (strnicmp(data, "nohard", 6) == 0) {
1158 } else if (strnicmp(data, "nosoft", 6) == 0) {
1160 } else if (strnicmp(data, "nointr", 6) == 0) {
1162 } else if (strnicmp(data, "intr", 4) == 0) {
1164 } else if (strnicmp(data, "serverino",7) == 0) {
1165 vol->server_ino = 1;
1166 } else if (strnicmp(data, "noserverino",9) == 0) {
1167 vol->server_ino = 0;
1168 } else if (strnicmp(data, "cifsacl",7) == 0) {
1170 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1172 } else if (strnicmp(data, "acl",3) == 0) {
1173 vol->no_psx_acl = 0;
1174 } else if (strnicmp(data, "noacl",5) == 0) {
1175 vol->no_psx_acl = 1;
1176 } else if (strnicmp(data, "direct",6) == 0) {
1178 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1180 } else if (strnicmp(data, "in6_addr",8) == 0) {
1181 if (!value || !*value) {
1182 vol->in6_addr = NULL;
1183 } else if (strnlen(value, 49) == 48) {
1184 vol->in6_addr = value;
1186 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1189 } else if (strnicmp(data, "noac", 4) == 0) {
1190 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1192 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1194 if (vol->UNC == NULL) {
1195 if(devname == NULL) {
1196 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1199 if ((temp_len = strnlen(devname, 300)) < 300) {
1200 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1201 if(vol->UNC == NULL)
1203 strcpy(vol->UNC,devname);
1204 if (strncmp(vol->UNC, "//", 2) == 0) {
1207 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1208 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1212 printk(KERN_WARNING "CIFS: UNC name too long\n");
1216 if(vol->UNCip == NULL)
1217 vol->UNCip = &vol->UNC[2];
1222 static struct cifsSesInfo *
1223 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1224 struct in6_addr *target_ip6_addr,
1225 char *userName, struct TCP_Server_Info **psrvTcp)
1227 struct list_head *tmp;
1228 struct cifsSesInfo *ses;
1230 read_lock(&GlobalSMBSeslock);
1232 list_for_each(tmp, &GlobalSMBSessionList) {
1233 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1235 if((target_ip_addr &&
1236 (ses->server->addr.sockAddr.sin_addr.s_addr
1237 == target_ip_addr->s_addr)) || (target_ip6_addr
1238 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1239 target_ip6_addr,sizeof(*target_ip6_addr)))){
1240 /* BB lock server and tcp session and increment use count here?? */
1241 *psrvTcp = ses->server; /* found a match on the TCP session */
1242 /* BB check if reconnection needed */
1244 (ses->userName, userName,
1245 MAX_USERNAME_SIZE) == 0){
1246 read_unlock(&GlobalSMBSeslock);
1247 return ses; /* found exact match on both tcp and SMB sessions */
1251 /* else tcp and smb sessions need reconnection */
1253 read_unlock(&GlobalSMBSeslock);
1257 static struct cifsTconInfo *
1258 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1260 struct list_head *tmp;
1261 struct cifsTconInfo *tcon;
1263 read_lock(&GlobalSMBSeslock);
1264 list_for_each(tmp, &GlobalTreeConnectionList) {
1265 cFYI(1, ("Next tcon - "));
1266 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1268 if (tcon->ses->server) {
1270 (" old ip addr: %x == new ip %x ?",
1271 tcon->ses->server->addr.sockAddr.sin_addr.
1272 s_addr, new_target_ip_addr));
1273 if (tcon->ses->server->addr.sockAddr.sin_addr.
1274 s_addr == new_target_ip_addr) {
1275 /* BB lock tcon and server and tcp session and increment use count here? */
1276 /* found a match on the TCP session */
1277 /* BB check if reconnection needed */
1278 cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
1279 tcon->treeName, uncName));
1281 (tcon->treeName, uncName,
1282 MAX_TREE_SIZE) == 0) {
1284 ("Matched UNC, old user: %s == new: %s ?",
1285 tcon->treeName, uncName));
1287 (tcon->ses->userName,
1289 MAX_USERNAME_SIZE) == 0) {
1290 read_unlock(&GlobalSMBSeslock);
1291 return tcon;/* also matched user (smb session)*/
1298 read_unlock(&GlobalSMBSeslock);
1303 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1304 const char *old_path, const struct nls_table *nls_codepage,
1307 unsigned char *referrals = NULL;
1308 unsigned int num_referrals;
1311 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1312 &num_referrals, &referrals, remap);
1314 /* BB Add in code to: if valid refrl, if not ip address contact
1315 the helper that resolves tcp names, mount to it, try to
1316 tcon to it unmount it if fail */
1324 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1325 const char *old_path, const struct nls_table *nls_codepage,
1326 unsigned int *pnum_referrals,
1327 unsigned char ** preferrals, int remap)
1332 *pnum_referrals = 0;
1334 if (pSesInfo->ipc_tid == 0) {
1335 temp_unc = kmalloc(2 /* for slashes */ +
1336 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1337 + 1 + 4 /* slash IPC$ */ + 2,
1339 if (temp_unc == NULL)
1343 strcpy(temp_unc + 2, pSesInfo->serverName);
1344 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1345 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1347 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1351 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1352 pnum_referrals, nls_codepage, remap);
1357 /* See RFC1001 section 14 on representation of Netbios names */
1358 static void rfc1002mangle(char * target,char * source, unsigned int length)
1362 for(i=0,j=0;i<(length);i++) {
1363 /* mask a nibble at a time and encode */
1364 target[j] = 'A' + (0x0F & (source[i] >> 4));
1365 target[j+1] = 'A' + (0x0F & source[i]);
1373 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1374 char * netbios_name, char * target_name)
1378 __be16 orig_port = 0;
1380 if(*csocket == NULL) {
1381 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1383 cERROR(1, ("Error %d creating socket",rc));
1387 /* BB other socket options to set KEEPALIVE, NODELAY? */
1388 cFYI(1,("Socket created"));
1389 (*csocket)->sk->sk_allocation = GFP_NOFS;
1393 psin_server->sin_family = AF_INET;
1394 if(psin_server->sin_port) { /* user overrode default port */
1395 rc = (*csocket)->ops->connect(*csocket,
1396 (struct sockaddr *) psin_server,
1397 sizeof (struct sockaddr_in),0);
1403 /* save original port so we can retry user specified port
1404 later if fall back ports fail this time */
1405 orig_port = psin_server->sin_port;
1407 /* do not retry on the same port we just failed on */
1408 if(psin_server->sin_port != htons(CIFS_PORT)) {
1409 psin_server->sin_port = htons(CIFS_PORT);
1411 rc = (*csocket)->ops->connect(*csocket,
1412 (struct sockaddr *) psin_server,
1413 sizeof (struct sockaddr_in),0);
1419 psin_server->sin_port = htons(RFC1001_PORT);
1420 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1421 psin_server, sizeof (struct sockaddr_in),0);
1426 /* give up here - unless we want to retry on different
1427 protocol families some day */
1430 psin_server->sin_port = orig_port;
1431 cFYI(1,("Error %d connecting to server via ipv4",rc));
1432 sock_release(*csocket);
1436 /* Eventually check for other socket options to change from
1437 the default. sock_setsockopt not used because it expects
1438 user space buffer */
1439 cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf,
1440 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1441 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1442 /* make the bufsizes depend on wsize/rsize and max requests */
1443 if((*csocket)->sk->sk_sndbuf < (200 * 1024))
1444 (*csocket)->sk->sk_sndbuf = 200 * 1024;
1445 if((*csocket)->sk->sk_rcvbuf < (140 * 1024))
1446 (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1448 /* send RFC1001 sessinit */
1449 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1450 /* some servers require RFC1001 sessinit before sending
1451 negprot - BB check reconnection in case where second
1452 sessinit is sent but no second negprot */
1453 struct rfc1002_session_packet * ses_init_buf;
1454 struct smb_hdr * smb_buf;
1455 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1457 ses_init_buf->trailer.session_req.called_len = 32;
1458 if(target_name && (target_name[0] != 0)) {
1459 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1462 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1463 DEFAULT_CIFS_CALLED_NAME,16);
1466 ses_init_buf->trailer.session_req.calling_len = 32;
1467 /* calling name ends in null (byte 16) from old smb
1469 if(netbios_name && (netbios_name[0] !=0)) {
1470 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1473 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1474 "LINUX_CIFS_CLNT",16);
1476 ses_init_buf->trailer.session_req.scope1 = 0;
1477 ses_init_buf->trailer.session_req.scope2 = 0;
1478 smb_buf = (struct smb_hdr *)ses_init_buf;
1479 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1480 smb_buf->smb_buf_length = 0x81000044;
1481 rc = smb_send(*csocket, smb_buf, 0x44,
1482 (struct sockaddr *)psin_server);
1483 kfree(ses_init_buf);
1484 msleep(1); /* RFC1001 layer in at least one server
1485 requires very short break before negprot
1486 presumably because not expecting negprot
1487 to follow so fast. This is a simple
1488 solution that works without
1489 complicating the code and causes no
1490 significant slowing down on mount
1491 for everyone else */
1493 /* else the negprot may still work without this
1494 even though malloc failed */
1502 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1506 __be16 orig_port = 0;
1508 if(*csocket == NULL) {
1509 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1511 cERROR(1, ("Error %d creating ipv6 socket",rc));
1515 /* BB other socket options to set KEEPALIVE, NODELAY? */
1516 cFYI(1,("ipv6 Socket created"));
1517 (*csocket)->sk->sk_allocation = GFP_NOFS;
1521 psin_server->sin6_family = AF_INET6;
1523 if(psin_server->sin6_port) { /* user overrode default port */
1524 rc = (*csocket)->ops->connect(*csocket,
1525 (struct sockaddr *) psin_server,
1526 sizeof (struct sockaddr_in6),0);
1532 /* save original port so we can retry user specified port
1533 later if fall back ports fail this time */
1535 orig_port = psin_server->sin6_port;
1536 /* do not retry on the same port we just failed on */
1537 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1538 psin_server->sin6_port = htons(CIFS_PORT);
1540 rc = (*csocket)->ops->connect(*csocket,
1541 (struct sockaddr *) psin_server,
1542 sizeof (struct sockaddr_in6),0);
1548 psin_server->sin6_port = htons(RFC1001_PORT);
1549 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1550 psin_server, sizeof (struct sockaddr_in6),0);
1555 /* give up here - unless we want to retry on different
1556 protocol families some day */
1559 psin_server->sin6_port = orig_port;
1560 cFYI(1,("Error %d connecting to server via ipv6",rc));
1561 sock_release(*csocket);
1565 /* Eventually check for other socket options to change from
1566 the default. sock_setsockopt not used because it expects
1567 user space buffer */
1568 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1574 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1575 char *mount_data, const char *devname)
1579 int address_type = AF_INET;
1580 struct socket *csocket = NULL;
1581 struct sockaddr_in sin_server;
1582 struct sockaddr_in6 sin_server6;
1583 struct smb_vol volume_info;
1584 struct cifsSesInfo *pSesInfo = NULL;
1585 struct cifsSesInfo *existingCifsSes = NULL;
1586 struct cifsTconInfo *tcon = NULL;
1587 struct TCP_Server_Info *srvTcp = NULL;
1591 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1593 memset(&volume_info,0,sizeof(struct smb_vol));
1594 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1595 kfree(volume_info.UNC);
1596 kfree(volume_info.password);
1601 if (volume_info.username) {
1602 /* BB fixme parse for domain name here */
1603 cFYI(1, ("Username: %s ", volume_info.username));
1606 cifserror("No username specified");
1607 /* In userspace mount helper we can get user name from alternate
1608 locations such as env variables and files on disk */
1609 kfree(volume_info.UNC);
1610 kfree(volume_info.password);
1615 if (volume_info.UNCip && volume_info.UNC) {
1616 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1619 /* not ipv4 address, try ipv6 */
1620 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1622 address_type = AF_INET6;
1624 address_type = AF_INET;
1628 /* we failed translating address */
1629 kfree(volume_info.UNC);
1630 kfree(volume_info.password);
1635 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1638 } else if (volume_info.UNCip){
1639 /* BB using ip addr as server name connect to the DFS root below */
1640 cERROR(1,("Connecting to DFS root not implemented yet"));
1641 kfree(volume_info.UNC);
1642 kfree(volume_info.password);
1645 } else /* which servers DFS root would we conect to */ {
1647 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
1648 kfree(volume_info.UNC);
1649 kfree(volume_info.password);
1654 /* this is needed for ASCII cp to Unicode converts */
1655 if(volume_info.iocharset == NULL) {
1656 cifs_sb->local_nls = load_nls_default();
1657 /* load_nls_default can not return null */
1659 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1660 if(cifs_sb->local_nls == NULL) {
1661 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1662 kfree(volume_info.UNC);
1663 kfree(volume_info.password);
1669 if(address_type == AF_INET)
1670 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1671 NULL /* no ipv6 addr */,
1672 volume_info.username, &srvTcp);
1673 else if(address_type == AF_INET6)
1674 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1675 &sin_server6.sin6_addr,
1676 volume_info.username, &srvTcp);
1678 kfree(volume_info.UNC);
1679 kfree(volume_info.password);
1686 cFYI(1, ("Existing tcp session with server found"));
1687 } else { /* create socket */
1688 if(volume_info.port)
1689 sin_server.sin_port = htons(volume_info.port);
1691 sin_server.sin_port = 0;
1692 rc = ipv4_connect(&sin_server,&csocket,
1693 volume_info.source_rfc1001_name,
1694 volume_info.target_rfc1001_name);
1697 ("Error connecting to IPv4 socket. Aborting operation"));
1699 sock_release(csocket);
1700 kfree(volume_info.UNC);
1701 kfree(volume_info.password);
1706 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1707 if (srvTcp == NULL) {
1709 sock_release(csocket);
1710 kfree(volume_info.UNC);
1711 kfree(volume_info.password);
1715 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1716 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1717 atomic_set(&srvTcp->inFlight,0);
1718 /* BB Add code for ipv6 case too */
1719 srvTcp->ssocket = csocket;
1720 srvTcp->protocolType = IPV4;
1721 init_waitqueue_head(&srvTcp->response_q);
1722 init_waitqueue_head(&srvTcp->request_q);
1723 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1724 /* at this point we are the only ones with the pointer
1725 to the struct since the kernel thread not created yet
1726 so no need to spinlock this init of tcpStatus */
1727 srvTcp->tcpStatus = CifsNew;
1728 init_MUTEX(&srvTcp->tcpSem);
1729 rc = (int)kernel_thread((void *)(void *)cifs_demultiplex_thread, srvTcp,
1730 CLONE_FS | CLONE_FILES | CLONE_VM);
1733 sock_release(csocket);
1734 kfree(volume_info.UNC);
1735 kfree(volume_info.password);
1739 wait_for_completion(&cifsd_complete);
1741 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1742 memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
1743 srvTcp->sequence_number = 0;
1747 if (existingCifsSes) {
1748 pSesInfo = existingCifsSes;
1749 cFYI(1, ("Existing smb sess found"));
1750 kfree(volume_info.password);
1751 /* volume_info.UNC freed at end of function */
1753 cFYI(1, ("Existing smb sess not found"));
1754 pSesInfo = sesInfoAlloc();
1755 if (pSesInfo == NULL)
1758 pSesInfo->server = srvTcp;
1759 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1760 NIPQUAD(sin_server.sin_addr.s_addr));
1764 /* volume_info.password freed at unmount */
1765 if (volume_info.password)
1766 pSesInfo->password = volume_info.password;
1767 if (volume_info.username)
1768 strncpy(pSesInfo->userName,
1769 volume_info.username,MAX_USERNAME_SIZE);
1770 if (volume_info.domainname) {
1771 int len = strlen(volume_info.domainname);
1772 pSesInfo->domainName =
1773 kmalloc(len + 1, GFP_KERNEL);
1774 if(pSesInfo->domainName)
1775 strcpy(pSesInfo->domainName,
1776 volume_info.domainname);
1778 pSesInfo->linux_uid = volume_info.linux_uid;
1779 down(&pSesInfo->sesSem);
1780 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1781 up(&pSesInfo->sesSem);
1783 atomic_inc(&srvTcp->socketUseCount);
1785 kfree(volume_info.password);
1788 /* search for existing tcon to this server share */
1790 if(volume_info.rsize > CIFSMaxBufSize) {
1791 cERROR(1,("rsize %d too large, using MaxBufSize",
1792 volume_info.rsize));
1793 cifs_sb->rsize = CIFSMaxBufSize;
1794 } else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1795 cifs_sb->rsize = volume_info.rsize;
1797 cifs_sb->rsize = CIFSMaxBufSize;
1799 if(volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
1800 cERROR(1,("wsize %d too large using 4096 instead",
1801 volume_info.wsize));
1802 cifs_sb->wsize = 4096;
1803 } else if(volume_info.wsize)
1804 cifs_sb->wsize = volume_info.wsize;
1807 min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
1809 /* old default of CIFSMaxBufSize was too small now
1810 that SMB Write2 can send multiple pages in kvec.
1811 RFC1001 does not describe what happens when frame
1812 bigger than 128K is sent so use that as max in
1813 conjunction with 52K kvec constraint on arch with 4K
1816 if(cifs_sb->rsize < 2048) {
1817 cifs_sb->rsize = 2048;
1818 /* Windows ME may prefer this */
1819 cFYI(1,("readsize set to minimum 2048"));
1821 cifs_sb->mnt_uid = volume_info.linux_uid;
1822 cifs_sb->mnt_gid = volume_info.linux_gid;
1823 cifs_sb->mnt_file_mode = volume_info.file_mode;
1824 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1825 cFYI(1,("file mode: 0x%x dir mode: 0x%x",
1826 cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1828 if(volume_info.noperm)
1829 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1830 if(volume_info.setuids)
1831 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1832 if(volume_info.server_ino)
1833 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1834 if(volume_info.remap)
1835 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1836 if(volume_info.no_xattr)
1837 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1838 if(volume_info.sfu_emul)
1839 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1840 if(volume_info.nobrl)
1841 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1842 if(volume_info.cifs_acl)
1843 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
1845 if(volume_info.direct_io) {
1846 cFYI(1,("mounting share using direct i/o"));
1847 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
1851 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
1852 volume_info.username);
1854 cFYI(1, ("Found match on UNC path"));
1855 /* we can have only one retry value for a connection
1856 to a share so for resources mounted more than once
1857 to the same server share the last value passed in
1858 for the retry flag is used */
1859 tcon->retry = volume_info.retry;
1860 tcon->nocase = volume_info.nocase;
1862 tcon = tconInfoAlloc();
1866 /* check for null share name ie connect to dfs root */
1868 /* BB check if this works for exactly length three strings */
1869 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
1870 && (strchr(volume_info.UNC + 3, '/') ==
1872 rc = connect_to_dfs_path(xid, pSesInfo,
1873 "", cifs_sb->local_nls,
1874 cifs_sb->mnt_cifs_flags &
1875 CIFS_MOUNT_MAP_SPECIAL_CHR);
1876 kfree(volume_info.UNC);
1880 rc = CIFSTCon(xid, pSesInfo,
1882 tcon, cifs_sb->local_nls);
1883 cFYI(1, ("CIFS Tcon rc = %d", rc));
1886 atomic_inc(&pSesInfo->inUse);
1887 tcon->retry = volume_info.retry;
1888 tcon->nocase = volume_info.nocase;
1894 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
1895 sb->s_maxbytes = (u64) 1 << 63;
1897 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
1900 sb->s_time_gran = 100;
1902 /* on error free sesinfo and tcon struct if needed */
1904 /* if session setup failed, use count is zero but
1905 we still need to free cifsd thread */
1906 if(atomic_read(&srvTcp->socketUseCount) == 0) {
1907 spin_lock(&GlobalMid_Lock);
1908 srvTcp->tcpStatus = CifsExiting;
1909 spin_unlock(&GlobalMid_Lock);
1911 send_sig(SIGKILL,srvTcp->tsk,1);
1912 wait_for_completion(&cifsd_complete);
1915 /* If find_unc succeeded then rc == 0 so we can not end */
1916 if (tcon) /* up accidently freeing someone elses tcon struct */
1918 if (existingCifsSes == NULL) {
1920 if ((pSesInfo->server) &&
1921 (pSesInfo->status == CifsGood)) {
1923 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
1924 /* if the socketUseCount is now zero */
1925 if((temp_rc == -ESHUTDOWN) &&
1926 (pSesInfo->server->tsk)) {
1927 send_sig(SIGKILL,pSesInfo->server->tsk,1);
1928 wait_for_completion(&cifsd_complete);
1931 cFYI(1, ("No session or bad tcon"));
1932 sesInfoFree(pSesInfo);
1933 /* pSesInfo = NULL; */
1937 atomic_inc(&tcon->useCount);
1938 cifs_sb->tcon = tcon;
1939 tcon->ses = pSesInfo;
1941 /* do not care if following two calls succeed - informational */
1942 CIFSSMBQFSDeviceInfo(xid, tcon);
1943 CIFSSMBQFSAttributeInfo(xid, tcon);
1945 if (tcon->ses->capabilities & CAP_UNIX) {
1946 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1948 le64_to_cpu(tcon->fsUnixInfo.Capability);
1949 cap &= CIFS_UNIX_CAP_MASK;
1950 if(volume_info.no_psx_acl)
1951 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1952 else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
1953 cFYI(1,("negotiated posix acl support"));
1954 sb->s_flags |= MS_POSIXACL;
1957 if(volume_info.posix_paths == 0)
1958 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1959 else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
1960 cFYI(1,("negotiate posix pathnames"));
1961 cifs_sb->mnt_cifs_flags |=
1962 CIFS_MOUNT_POSIX_PATHS;
1965 cFYI(1,("Negotiate caps 0x%x",(int)cap));
1967 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1968 cFYI(1,("setting capabilities failed"));
1972 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
1973 cifs_sb->wsize = min(cifs_sb->wsize,
1974 (tcon->ses->server->maxBuf -
1975 MAX_CIFS_HDR_SIZE));
1976 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
1977 cifs_sb->rsize = min(cifs_sb->rsize,
1978 (tcon->ses->server->maxBuf -
1979 MAX_CIFS_HDR_SIZE));
1982 /* volume_info.password is freed above when existing session found
1983 (in which case it is not needed anymore) but when new sesion is created
1984 the password ptr is put in the new session structure (in which case the
1985 password will be freed at unmount time) */
1986 kfree(volume_info.UNC);
1992 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
1993 char session_key[CIFS_SESS_KEY_SIZE],
1994 const struct nls_table *nls_codepage)
1996 struct smb_hdr *smb_buffer;
1997 struct smb_hdr *smb_buffer_response;
1998 SESSION_SETUP_ANDX *pSMB;
1999 SESSION_SETUP_ANDX *pSMBr;
2004 int remaining_words = 0;
2005 int bytes_returned = 0;
2010 cFYI(1, ("In sesssetup"));
2013 user = ses->userName;
2014 domain = ses->domainName;
2015 smb_buffer = cifs_buf_get();
2016 if (smb_buffer == NULL) {
2019 smb_buffer_response = smb_buffer;
2020 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2022 /* send SMBsessionSetup here */
2023 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2024 NULL /* no tCon exists yet */ , 13 /* wct */ );
2026 smb_buffer->Mid = GetNextMid(ses->server);
2027 pSMB->req_no_secext.AndXCommand = 0xFF;
2028 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2029 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2031 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2032 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2034 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2035 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
2036 if (ses->capabilities & CAP_UNICODE) {
2037 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2038 capabilities |= CAP_UNICODE;
2040 if (ses->capabilities & CAP_STATUS32) {
2041 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2042 capabilities |= CAP_STATUS32;
2044 if (ses->capabilities & CAP_DFS) {
2045 smb_buffer->Flags2 |= SMBFLG2_DFS;
2046 capabilities |= CAP_DFS;
2048 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2050 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2051 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2053 pSMB->req_no_secext.CaseSensitivePasswordLength =
2054 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2055 bcc_ptr = pByteArea(smb_buffer);
2056 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2057 bcc_ptr += CIFS_SESS_KEY_SIZE;
2058 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2059 bcc_ptr += CIFS_SESS_KEY_SIZE;
2061 if (ses->capabilities & CAP_UNICODE) {
2062 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
2067 bytes_returned = 0; /* skip null user */
2070 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
2072 /* convert number of 16 bit words to bytes */
2073 bcc_ptr += 2 * bytes_returned;
2074 bcc_ptr += 2; /* trailing null */
2077 cifs_strtoUCS((__le16 *) bcc_ptr,
2078 "CIFS_LINUX_DOM", 32, nls_codepage);
2081 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2083 bcc_ptr += 2 * bytes_returned;
2086 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2088 bcc_ptr += 2 * bytes_returned;
2090 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
2092 bcc_ptr += 2 * bytes_returned;
2095 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2097 bcc_ptr += 2 * bytes_returned;
2101 strncpy(bcc_ptr, user, 200);
2102 bcc_ptr += strnlen(user, 200);
2106 if (domain == NULL) {
2107 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2108 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2110 strncpy(bcc_ptr, domain, 64);
2111 bcc_ptr += strnlen(domain, 64);
2115 strcpy(bcc_ptr, "Linux version ");
2116 bcc_ptr += strlen("Linux version ");
2117 strcpy(bcc_ptr, system_utsname.release);
2118 bcc_ptr += strlen(system_utsname.release) + 1;
2119 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2120 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2122 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2123 smb_buffer->smb_buf_length += count;
2124 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2126 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2127 &bytes_returned, 1);
2129 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2130 } else if ((smb_buffer_response->WordCount == 3)
2131 || (smb_buffer_response->WordCount == 4)) {
2132 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2133 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2134 if (action & GUEST_LOGIN)
2135 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
2136 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2137 cFYI(1, ("UID = %d ", ses->Suid));
2138 /* response can have either 3 or 4 word count - Samba sends 3 */
2139 bcc_ptr = pByteArea(smb_buffer_response);
2140 if ((pSMBr->resp.hdr.WordCount == 3)
2141 || ((pSMBr->resp.hdr.WordCount == 4)
2142 && (blob_len < pSMBr->resp.ByteCount))) {
2143 if (pSMBr->resp.hdr.WordCount == 4)
2144 bcc_ptr += blob_len;
2146 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2147 if ((long) (bcc_ptr) % 2) {
2149 (BCC(smb_buffer_response) - 1) /2;
2150 bcc_ptr++; /* Unicode strings must be word aligned */
2153 BCC(smb_buffer_response) / 2;
2156 UniStrnlen((wchar_t *) bcc_ptr,
2157 remaining_words - 1);
2158 /* We look for obvious messed up bcc or strings in response so we do not go off
2159 the end since (at least) WIN2K and Windows XP have a major bug in not null
2160 terminating last Unicode string in response */
2162 kfree(ses->serverOS);
2163 ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
2164 if(ses->serverOS == NULL)
2165 goto sesssetup_nomem;
2166 cifs_strfromUCS_le(ses->serverOS,
2167 (__le16 *)bcc_ptr, len,nls_codepage);
2168 bcc_ptr += 2 * (len + 1);
2169 remaining_words -= len + 1;
2170 ses->serverOS[2 * len] = 0;
2171 ses->serverOS[1 + (2 * len)] = 0;
2172 if (remaining_words > 0) {
2173 len = UniStrnlen((wchar_t *)bcc_ptr,
2176 kfree(ses->serverNOS);
2177 ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
2178 if(ses->serverNOS == NULL)
2179 goto sesssetup_nomem;
2180 cifs_strfromUCS_le(ses->serverNOS,
2181 (__le16 *)bcc_ptr,len,nls_codepage);
2182 bcc_ptr += 2 * (len + 1);
2183 ses->serverNOS[2 * len] = 0;
2184 ses->serverNOS[1 + (2 * len)] = 0;
2185 if(strncmp(ses->serverNOS,
2186 "NT LAN Manager 4",16) == 0) {
2187 cFYI(1,("NT4 server"));
2188 ses->flags |= CIFS_SES_NT4;
2190 remaining_words -= len + 1;
2191 if (remaining_words > 0) {
2192 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2193 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2194 if(ses->serverDomain)
2195 kfree(ses->serverDomain);
2197 kzalloc(2*(len+1),GFP_KERNEL);
2198 if(ses->serverDomain == NULL)
2199 goto sesssetup_nomem;
2200 cifs_strfromUCS_le(ses->serverDomain,
2201 (__le16 *)bcc_ptr,len,nls_codepage);
2202 bcc_ptr += 2 * (len + 1);
2203 ses->serverDomain[2*len] = 0;
2204 ses->serverDomain[1+(2*len)] = 0;
2205 } /* else no more room so create dummy domain string */
2207 if(ses->serverDomain)
2208 kfree(ses->serverDomain);
2210 kzalloc(2, GFP_KERNEL);
2212 } else { /* no room so create dummy domain and NOS string */
2213 /* if these kcallocs fail not much we
2214 can do, but better to not fail the
2216 if(ses->serverDomain)
2217 kfree(ses->serverDomain);
2219 kzalloc(2, GFP_KERNEL);
2221 kfree(ses->serverNOS);
2223 kzalloc(2, GFP_KERNEL);
2225 } else { /* ASCII */
2226 len = strnlen(bcc_ptr, 1024);
2227 if (((long) bcc_ptr + len) - (long)
2228 pByteArea(smb_buffer_response)
2229 <= BCC(smb_buffer_response)) {
2231 kfree(ses->serverOS);
2232 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
2233 if(ses->serverOS == NULL)
2234 goto sesssetup_nomem;
2235 strncpy(ses->serverOS,bcc_ptr, len);
2238 bcc_ptr[0] = 0; /* null terminate the string */
2241 len = strnlen(bcc_ptr, 1024);
2243 kfree(ses->serverNOS);
2244 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2245 if(ses->serverNOS == NULL)
2246 goto sesssetup_nomem;
2247 strncpy(ses->serverNOS, bcc_ptr, len);
2252 len = strnlen(bcc_ptr, 1024);
2253 if(ses->serverDomain)
2254 kfree(ses->serverDomain);
2255 ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
2256 if(ses->serverDomain == NULL)
2257 goto sesssetup_nomem;
2258 strncpy(ses->serverDomain, bcc_ptr, len);
2264 ("Variable field of length %d extends beyond end of smb ",
2269 (" Security Blob Length extends beyond end of SMB"));
2273 (" Invalid Word count %d: ",
2274 smb_buffer_response->WordCount));
2277 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2278 since that could make reconnection harder, and
2279 reconnection might be needed to free memory */
2281 cifs_buf_release(smb_buffer);
2287 CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2288 char *SecurityBlob,int SecurityBlobLength,
2289 const struct nls_table *nls_codepage)
2291 struct smb_hdr *smb_buffer;
2292 struct smb_hdr *smb_buffer_response;
2293 SESSION_SETUP_ANDX *pSMB;
2294 SESSION_SETUP_ANDX *pSMBr;
2299 int remaining_words = 0;
2300 int bytes_returned = 0;
2305 cFYI(1, ("In spnego sesssetup "));
2308 user = ses->userName;
2309 domain = ses->domainName;
2311 smb_buffer = cifs_buf_get();
2312 if (smb_buffer == NULL) {
2315 smb_buffer_response = smb_buffer;
2316 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2318 /* send SMBsessionSetup here */
2319 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2320 NULL /* no tCon exists yet */ , 12 /* wct */ );
2322 smb_buffer->Mid = GetNextMid(ses->server);
2323 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2324 pSMB->req.AndXCommand = 0xFF;
2325 if(ses->server->maxBuf > 64*1024)
2326 ses->server->maxBuf = (64*1023);
2327 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2328 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2330 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2331 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2333 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2334 CAP_EXTENDED_SECURITY;
2335 if (ses->capabilities & CAP_UNICODE) {
2336 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2337 capabilities |= CAP_UNICODE;
2339 if (ses->capabilities & CAP_STATUS32) {
2340 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2341 capabilities |= CAP_STATUS32;
2343 if (ses->capabilities & CAP_DFS) {
2344 smb_buffer->Flags2 |= SMBFLG2_DFS;
2345 capabilities |= CAP_DFS;
2347 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2349 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2350 bcc_ptr = pByteArea(smb_buffer);
2351 memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
2352 bcc_ptr += SecurityBlobLength;
2354 if (ses->capabilities & CAP_UNICODE) {
2355 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode strings */
2360 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage);
2361 bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
2362 bcc_ptr += 2; /* trailing null */
2365 cifs_strtoUCS((__le16 *) bcc_ptr,
2366 "CIFS_LINUX_DOM", 32, nls_codepage);
2369 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2371 bcc_ptr += 2 * bytes_returned;
2374 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2376 bcc_ptr += 2 * bytes_returned;
2378 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2380 bcc_ptr += 2 * bytes_returned;
2383 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2385 bcc_ptr += 2 * bytes_returned;
2388 strncpy(bcc_ptr, user, 200);
2389 bcc_ptr += strnlen(user, 200);
2392 if (domain == NULL) {
2393 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2394 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2396 strncpy(bcc_ptr, domain, 64);
2397 bcc_ptr += strnlen(domain, 64);
2401 strcpy(bcc_ptr, "Linux version ");
2402 bcc_ptr += strlen("Linux version ");
2403 strcpy(bcc_ptr, system_utsname.release);
2404 bcc_ptr += strlen(system_utsname.release) + 1;
2405 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2406 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2408 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2409 smb_buffer->smb_buf_length += count;
2410 pSMB->req.ByteCount = cpu_to_le16(count);
2412 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2413 &bytes_returned, 1);
2415 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2416 } else if ((smb_buffer_response->WordCount == 3)
2417 || (smb_buffer_response->WordCount == 4)) {
2418 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2420 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2421 if (action & GUEST_LOGIN)
2422 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2424 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2425 cFYI(1, ("UID = %d ", ses->Suid));
2426 bcc_ptr = pByteArea(smb_buffer_response); /* response can have either 3 or 4 word count - Samba sends 3 */
2428 /* BB Fix below to make endian neutral !! */
2430 if ((pSMBr->resp.hdr.WordCount == 3)
2431 || ((pSMBr->resp.hdr.WordCount == 4)
2433 pSMBr->resp.ByteCount))) {
2434 if (pSMBr->resp.hdr.WordCount == 4) {
2438 ("Security Blob Length %d ",
2442 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2443 if ((long) (bcc_ptr) % 2) {
2445 (BCC(smb_buffer_response)
2447 bcc_ptr++; /* Unicode strings must be word aligned */
2451 (smb_buffer_response) / 2;
2454 UniStrnlen((wchar_t *) bcc_ptr,
2455 remaining_words - 1);
2456 /* We look for obvious messed up bcc or strings in response so we do not go off
2457 the end since (at least) WIN2K and Windows XP have a major bug in not null
2458 terminating last Unicode string in response */
2460 kfree(ses->serverOS);
2462 kzalloc(2 * (len + 1), GFP_KERNEL);
2463 cifs_strfromUCS_le(ses->serverOS,
2467 bcc_ptr += 2 * (len + 1);
2468 remaining_words -= len + 1;
2469 ses->serverOS[2 * len] = 0;
2470 ses->serverOS[1 + (2 * len)] = 0;
2471 if (remaining_words > 0) {
2472 len = UniStrnlen((wchar_t *)bcc_ptr,
2476 kfree(ses->serverNOS);
2478 kzalloc(2 * (len + 1),
2480 cifs_strfromUCS_le(ses->serverNOS,
2484 bcc_ptr += 2 * (len + 1);
2485 ses->serverNOS[2 * len] = 0;
2486 ses->serverNOS[1 + (2 * len)] = 0;
2487 remaining_words -= len + 1;
2488 if (remaining_words > 0) {
2489 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2490 /* last string not null terminated (e.g.Windows XP/2000) */
2491 if(ses->serverDomain)
2492 kfree(ses->serverDomain);
2493 ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
2494 cifs_strfromUCS_le(ses->serverDomain,
2497 bcc_ptr += 2*(len+1);
2498 ses->serverDomain[2*len] = 0;
2499 ses->serverDomain[1+(2*len)] = 0;
2500 } /* else no more room so create dummy domain string */
2502 if(ses->serverDomain)
2503 kfree(ses->serverDomain);
2505 kzalloc(2,GFP_KERNEL);
2507 } else {/* no room use dummy domain&NOS */
2508 if(ses->serverDomain)
2509 kfree(ses->serverDomain);
2510 ses->serverDomain = kzalloc(2, GFP_KERNEL);
2512 kfree(ses->serverNOS);
2513 ses->serverNOS = kzalloc(2, GFP_KERNEL);
2515 } else { /* ASCII */
2517 len = strnlen(bcc_ptr, 1024);
2518 if (((long) bcc_ptr + len) - (long)
2519 pByteArea(smb_buffer_response)
2520 <= BCC(smb_buffer_response)) {
2522 kfree(ses->serverOS);
2523 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
2524 strncpy(ses->serverOS, bcc_ptr, len);
2527 bcc_ptr[0] = 0; /* null terminate the string */
2530 len = strnlen(bcc_ptr, 1024);
2532 kfree(ses->serverNOS);
2533 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2534 strncpy(ses->serverNOS, bcc_ptr, len);
2539 len = strnlen(bcc_ptr, 1024);
2540 if(ses->serverDomain)
2541 kfree(ses->serverDomain);
2542 ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
2543 strncpy(ses->serverDomain, bcc_ptr, len);
2549 ("Variable field of length %d extends beyond end of smb ",
2554 (" Security Blob Length extends beyond end of SMB"));
2557 cERROR(1, ("No session structure passed in."));
2561 (" Invalid Word count %d: ",
2562 smb_buffer_response->WordCount));
2567 cifs_buf_release(smb_buffer);
2573 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2574 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2575 const struct nls_table *nls_codepage)
2577 struct smb_hdr *smb_buffer;
2578 struct smb_hdr *smb_buffer_response;
2579 SESSION_SETUP_ANDX *pSMB;
2580 SESSION_SETUP_ANDX *pSMBr;
2584 int remaining_words = 0;
2585 int bytes_returned = 0;
2587 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2588 PNEGOTIATE_MESSAGE SecurityBlob;
2589 PCHALLENGE_MESSAGE SecurityBlob2;
2590 __u32 negotiate_flags, capabilities;
2593 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
2596 domain = ses->domainName;
2597 *pNTLMv2_flag = FALSE;
2598 smb_buffer = cifs_buf_get();
2599 if (smb_buffer == NULL) {
2602 smb_buffer_response = smb_buffer;
2603 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2604 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2606 /* send SMBsessionSetup here */
2607 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2608 NULL /* no tCon exists yet */ , 12 /* wct */ );
2610 smb_buffer->Mid = GetNextMid(ses->server);
2611 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2612 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2614 pSMB->req.AndXCommand = 0xFF;
2615 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2616 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2618 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2619 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2621 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2622 CAP_EXTENDED_SECURITY;
2623 if (ses->capabilities & CAP_UNICODE) {
2624 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2625 capabilities |= CAP_UNICODE;
2627 if (ses->capabilities & CAP_STATUS32) {
2628 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2629 capabilities |= CAP_STATUS32;
2631 if (ses->capabilities & CAP_DFS) {
2632 smb_buffer->Flags2 |= SMBFLG2_DFS;
2633 capabilities |= CAP_DFS;
2635 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2637 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2638 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2639 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2640 SecurityBlob->MessageType = NtLmNegotiate;
2642 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2643 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2644 NTLMSSP_NEGOTIATE_56 |
2645 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2647 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2648 /* if(ntlmv2_support)
2649 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2650 /* setup pointers to domain name and workstation name */
2651 bcc_ptr += SecurityBlobLength;
2653 SecurityBlob->WorkstationName.Buffer = 0;
2654 SecurityBlob->WorkstationName.Length = 0;
2655 SecurityBlob->WorkstationName.MaximumLength = 0;
2657 /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2658 along with username on auth request (ie the response to challenge) */
2659 SecurityBlob->DomainName.Buffer = 0;
2660 SecurityBlob->DomainName.Length = 0;
2661 SecurityBlob->DomainName.MaximumLength = 0;
2662 if (ses->capabilities & CAP_UNICODE) {
2663 if ((long) bcc_ptr % 2) {
2669 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2671 bcc_ptr += 2 * bytes_returned;
2673 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
2675 bcc_ptr += 2 * bytes_returned;
2676 bcc_ptr += 2; /* null terminate Linux version */
2678 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2680 bcc_ptr += 2 * bytes_returned;
2683 bcc_ptr += 2; /* null terminate network opsys string */
2686 bcc_ptr += 2; /* null domain */
2687 } else { /* ASCII */
2688 strcpy(bcc_ptr, "Linux version ");
2689 bcc_ptr += strlen("Linux version ");
2690 strcpy(bcc_ptr, system_utsname.release);
2691 bcc_ptr += strlen(system_utsname.release) + 1;
2692 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2693 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2694 bcc_ptr++; /* empty domain field */
2697 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2698 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2699 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2700 smb_buffer->smb_buf_length += count;
2701 pSMB->req.ByteCount = cpu_to_le16(count);
2703 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2704 &bytes_returned, 1);
2706 if (smb_buffer_response->Status.CifsError ==
2707 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2711 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2712 } else if ((smb_buffer_response->WordCount == 3)
2713 || (smb_buffer_response->WordCount == 4)) {
2714 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2715 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2717 if (action & GUEST_LOGIN)
2718 cFYI(1, (" Guest login"));
2719 /* Do we want to set anything in SesInfo struct when guest login? */
2721 bcc_ptr = pByteArea(smb_buffer_response);
2722 /* response can have either 3 or 4 word count - Samba sends 3 */
2724 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2725 if (SecurityBlob2->MessageType != NtLmChallenge) {
2727 ("Unexpected NTLMSSP message type received %d",
2728 SecurityBlob2->MessageType));
2730 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2731 cFYI(1, ("UID = %d", ses->Suid));
2732 if ((pSMBr->resp.hdr.WordCount == 3)
2733 || ((pSMBr->resp.hdr.WordCount == 4)
2735 pSMBr->resp.ByteCount))) {
2737 if (pSMBr->resp.hdr.WordCount == 4) {
2738 bcc_ptr += blob_len;
2739 cFYI(1, ("Security Blob Length %d",
2743 cFYI(1, ("NTLMSSP Challenge rcvd"));
2745 memcpy(ses->server->cryptKey,
2746 SecurityBlob2->Challenge,
2747 CIFS_CRYPTO_KEY_SIZE);
2748 if(SecurityBlob2->NegotiateFlags &
2749 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2750 *pNTLMv2_flag = TRUE;
2752 if((SecurityBlob2->NegotiateFlags &
2753 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2754 || (sign_CIFS_PDUs > 1))
2755 ses->server->secMode |=
2756 SECMODE_SIGN_REQUIRED;
2757 if ((SecurityBlob2->NegotiateFlags &
2758 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2759 ses->server->secMode |=
2760 SECMODE_SIGN_ENABLED;
2762 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2763 if ((long) (bcc_ptr) % 2) {
2765 (BCC(smb_buffer_response)
2767 bcc_ptr++; /* Unicode strings must be word aligned */
2771 (smb_buffer_response) / 2;
2774 UniStrnlen((wchar_t *) bcc_ptr,
2775 remaining_words - 1);
2776 /* We look for obvious messed up bcc or strings in response so we do not go off
2777 the end since (at least) WIN2K and Windows XP have a major bug in not null
2778 terminating last Unicode string in response */
2780 kfree(ses->serverOS);
2782 kzalloc(2 * (len + 1), GFP_KERNEL);
2783 cifs_strfromUCS_le(ses->serverOS,
2787 bcc_ptr += 2 * (len + 1);
2788 remaining_words -= len + 1;
2789 ses->serverOS[2 * len] = 0;
2790 ses->serverOS[1 + (2 * len)] = 0;
2791 if (remaining_words > 0) {
2792 len = UniStrnlen((wchar_t *)
2797 kfree(ses->serverNOS);
2799 kzalloc(2 * (len + 1),
2801 cifs_strfromUCS_le(ses->
2807 bcc_ptr += 2 * (len + 1);
2808 ses->serverNOS[2 * len] = 0;
2811 remaining_words -= len + 1;
2812 if (remaining_words > 0) {
2813 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2814 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2815 if(ses->serverDomain)
2816 kfree(ses->serverDomain);
2828 ses->serverDomain[2*len]
2833 } /* else no more room so create dummy domain string */
2835 if(ses->serverDomain)
2836 kfree(ses->serverDomain);
2841 } else { /* no room so create dummy domain and NOS string */
2842 if(ses->serverDomain);
2843 kfree(ses->serverDomain);
2845 kzalloc(2, GFP_KERNEL);
2847 kfree(ses->serverNOS);
2849 kzalloc(2, GFP_KERNEL);
2851 } else { /* ASCII */
2852 len = strnlen(bcc_ptr, 1024);
2853 if (((long) bcc_ptr + len) - (long)
2854 pByteArea(smb_buffer_response)
2855 <= BCC(smb_buffer_response)) {
2857 kfree(ses->serverOS);
2861 strncpy(ses->serverOS,
2865 bcc_ptr[0] = 0; /* null terminate string */
2868 len = strnlen(bcc_ptr, 1024);
2870 kfree(ses->serverNOS);
2874 strncpy(ses->serverNOS, bcc_ptr, len);
2879 len = strnlen(bcc_ptr, 1024);
2880 if(ses->serverDomain)
2881 kfree(ses->serverDomain);
2885 strncpy(ses->serverDomain, bcc_ptr, len);
2891 ("Variable field of length %d extends beyond end of smb",
2896 (" Security Blob Length extends beyond end of SMB"));
2899 cERROR(1, ("No session structure passed in."));
2903 (" Invalid Word count %d:",
2904 smb_buffer_response->WordCount));
2909 cifs_buf_release(smb_buffer);
2914 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2915 char *ntlm_session_key, int ntlmv2_flag,
2916 const struct nls_table *nls_codepage)
2918 struct smb_hdr *smb_buffer;
2919 struct smb_hdr *smb_buffer_response;
2920 SESSION_SETUP_ANDX *pSMB;
2921 SESSION_SETUP_ANDX *pSMBr;
2926 int remaining_words = 0;
2927 int bytes_returned = 0;
2929 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2930 PAUTHENTICATE_MESSAGE SecurityBlob;
2931 __u32 negotiate_flags, capabilities;
2934 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2937 user = ses->userName;
2938 domain = ses->domainName;
2939 smb_buffer = cifs_buf_get();
2940 if (smb_buffer == NULL) {
2943 smb_buffer_response = smb_buffer;
2944 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2945 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2947 /* send SMBsessionSetup here */
2948 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2949 NULL /* no tCon exists yet */ , 12 /* wct */ );
2951 smb_buffer->Mid = GetNextMid(ses->server);
2952 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2953 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2954 pSMB->req.AndXCommand = 0xFF;
2955 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2956 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2958 pSMB->req.hdr.Uid = ses->Suid;
2960 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2961 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2963 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2964 CAP_EXTENDED_SECURITY;
2965 if (ses->capabilities & CAP_UNICODE) {
2966 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2967 capabilities |= CAP_UNICODE;
2969 if (ses->capabilities & CAP_STATUS32) {
2970 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2971 capabilities |= CAP_STATUS32;
2973 if (ses->capabilities & CAP_DFS) {
2974 smb_buffer->Flags2 |= SMBFLG2_DFS;
2975 capabilities |= CAP_DFS;
2977 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2979 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2980 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2981 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2982 SecurityBlob->MessageType = NtLmAuthenticate;
2983 bcc_ptr += SecurityBlobLength;
2985 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2986 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2987 0x80000000 | NTLMSSP_NEGOTIATE_128;
2989 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2991 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2993 /* setup pointers to domain name and workstation name */
2995 SecurityBlob->WorkstationName.Buffer = 0;
2996 SecurityBlob->WorkstationName.Length = 0;
2997 SecurityBlob->WorkstationName.MaximumLength = 0;
2998 SecurityBlob->SessionKey.Length = 0;
2999 SecurityBlob->SessionKey.MaximumLength = 0;
3000 SecurityBlob->SessionKey.Buffer = 0;
3002 SecurityBlob->LmChallengeResponse.Length = 0;
3003 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
3004 SecurityBlob->LmChallengeResponse.Buffer = 0;
3006 SecurityBlob->NtChallengeResponse.Length =
3007 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3008 SecurityBlob->NtChallengeResponse.MaximumLength =
3009 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3010 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
3011 SecurityBlob->NtChallengeResponse.Buffer =
3012 cpu_to_le32(SecurityBlobLength);
3013 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
3014 bcc_ptr += CIFS_SESS_KEY_SIZE;
3016 if (ses->capabilities & CAP_UNICODE) {
3017 if (domain == NULL) {
3018 SecurityBlob->DomainName.Buffer = 0;
3019 SecurityBlob->DomainName.Length = 0;
3020 SecurityBlob->DomainName.MaximumLength = 0;
3023 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
3026 SecurityBlob->DomainName.MaximumLength =
3028 SecurityBlob->DomainName.Buffer =
3029 cpu_to_le32(SecurityBlobLength);
3031 SecurityBlobLength += len;
3032 SecurityBlob->DomainName.Length =
3036 SecurityBlob->UserName.Buffer = 0;
3037 SecurityBlob->UserName.Length = 0;
3038 SecurityBlob->UserName.MaximumLength = 0;
3041 cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
3044 SecurityBlob->UserName.MaximumLength =
3046 SecurityBlob->UserName.Buffer =
3047 cpu_to_le32(SecurityBlobLength);
3049 SecurityBlobLength += len;
3050 SecurityBlob->UserName.Length =
3054 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
3055 SecurityBlob->WorkstationName.Length *= 2;
3056 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
3057 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
3058 bcc_ptr += SecurityBlob->WorkstationName.Length;
3059 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
3060 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
3062 if ((long) bcc_ptr % 2) {
3067 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
3069 bcc_ptr += 2 * bytes_returned;
3071 cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
3073 bcc_ptr += 2 * bytes_returned;
3074 bcc_ptr += 2; /* null term version string */
3076 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
3078 bcc_ptr += 2 * bytes_returned;
3081 bcc_ptr += 2; /* null terminate network opsys string */
3084 bcc_ptr += 2; /* null domain */
3085 } else { /* ASCII */
3086 if (domain == NULL) {
3087 SecurityBlob->DomainName.Buffer = 0;
3088 SecurityBlob->DomainName.Length = 0;
3089 SecurityBlob->DomainName.MaximumLength = 0;
3092 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3093 strncpy(bcc_ptr, domain, 63);
3094 len = strnlen(domain, 64);
3095 SecurityBlob->DomainName.MaximumLength =
3097 SecurityBlob->DomainName.Buffer =
3098 cpu_to_le32(SecurityBlobLength);
3100 SecurityBlobLength += len;
3101 SecurityBlob->DomainName.Length = cpu_to_le16(len);
3104 SecurityBlob->UserName.Buffer = 0;
3105 SecurityBlob->UserName.Length = 0;
3106 SecurityBlob->UserName.MaximumLength = 0;
3109 strncpy(bcc_ptr, user, 63);
3110 len = strnlen(user, 64);
3111 SecurityBlob->UserName.MaximumLength =
3113 SecurityBlob->UserName.Buffer =
3114 cpu_to_le32(SecurityBlobLength);
3116 SecurityBlobLength += len;
3117 SecurityBlob->UserName.Length = cpu_to_le16(len);
3119 /* BB fill in our workstation name if known BB */
3121 strcpy(bcc_ptr, "Linux version ");
3122 bcc_ptr += strlen("Linux version ");
3123 strcpy(bcc_ptr, system_utsname.release);
3124 bcc_ptr += strlen(system_utsname.release) + 1;
3125 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3126 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3127 bcc_ptr++; /* null domain */
3130 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3131 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3132 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3133 smb_buffer->smb_buf_length += count;
3134 pSMB->req.ByteCount = cpu_to_le16(count);
3136 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3137 &bytes_returned, 1);
3139 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
3140 } else if ((smb_buffer_response->WordCount == 3)
3141 || (smb_buffer_response->WordCount == 4)) {
3142 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3144 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3145 if (action & GUEST_LOGIN)
3146 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
3147 /* if(SecurityBlob2->MessageType != NtLm??){
3148 cFYI("Unexpected message type on auth response is %d "));
3152 ("Does UID on challenge %d match auth response UID %d ",
3153 ses->Suid, smb_buffer_response->Uid));
3154 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
3155 bcc_ptr = pByteArea(smb_buffer_response);
3156 /* response can have either 3 or 4 word count - Samba sends 3 */
3157 if ((pSMBr->resp.hdr.WordCount == 3)
3158 || ((pSMBr->resp.hdr.WordCount == 4)
3160 pSMBr->resp.ByteCount))) {
3161 if (pSMBr->resp.hdr.WordCount == 4) {
3165 ("Security Blob Length %d ",
3170 ("NTLMSSP response to Authenticate "));
3172 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3173 if ((long) (bcc_ptr) % 2) {
3175 (BCC(smb_buffer_response)
3177 bcc_ptr++; /* Unicode strings must be word aligned */
3179 remaining_words = BCC(smb_buffer_response) / 2;
3182 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
3183 /* We look for obvious messed up bcc or strings in response so we do not go off
3184 the end since (at least) WIN2K and Windows XP have a major bug in not null
3185 terminating last Unicode string in response */
3187 kfree(ses->serverOS);
3189 kzalloc(2 * (len + 1), GFP_KERNEL);
3190 cifs_strfromUCS_le(ses->serverOS,
3194 bcc_ptr += 2 * (len + 1);
3195 remaining_words -= len + 1;
3196 ses->serverOS[2 * len] = 0;
3197 ses->serverOS[1 + (2 * len)] = 0;
3198 if (remaining_words > 0) {
3199 len = UniStrnlen((wchar_t *)
3204 kfree(ses->serverNOS);
3206 kzalloc(2 * (len + 1),
3208 cifs_strfromUCS_le(ses->
3214 bcc_ptr += 2 * (len + 1);
3215 ses->serverNOS[2 * len] = 0;
3216 ses->serverNOS[1+(2*len)] = 0;
3217 remaining_words -= len + 1;
3218 if (remaining_words > 0) {
3219 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3220 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3221 if(ses->serverDomain)
3222 kfree(ses->serverDomain);
3247 } /* else no more room so create dummy domain string */
3249 if(ses->serverDomain)
3250 kfree(ses->serverDomain);
3251 ses->serverDomain = kzalloc(2,GFP_KERNEL);
3253 } else { /* no room so create dummy domain and NOS string */
3254 if(ses->serverDomain)
3255 kfree(ses->serverDomain);
3256 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3258 kfree(ses->serverNOS);
3259 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3261 } else { /* ASCII */
3262 len = strnlen(bcc_ptr, 1024);
3263 if (((long) bcc_ptr + len) -
3264 (long) pByteArea(smb_buffer_response)
3265 <= BCC(smb_buffer_response)) {
3267 kfree(ses->serverOS);
3268 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
3269 strncpy(ses->serverOS,bcc_ptr, len);
3272 bcc_ptr[0] = 0; /* null terminate the string */
3275 len = strnlen(bcc_ptr, 1024);
3277 kfree(ses->serverNOS);
3278 ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
3279 strncpy(ses->serverNOS, bcc_ptr, len);
3284 len = strnlen(bcc_ptr, 1024);
3285 if(ses->serverDomain)
3286 kfree(ses->serverDomain);
3287 ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
3288 strncpy(ses->serverDomain, bcc_ptr, len);
3294 ("Variable field of length %d extends beyond end of smb ",
3299 (" Security Blob Length extends beyond end of SMB"));
3302 cERROR(1, ("No session structure passed in."));
3306 (" Invalid Word count %d: ",
3307 smb_buffer_response->WordCount));
3312 cifs_buf_release(smb_buffer);
3318 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3319 const char *tree, struct cifsTconInfo *tcon,
3320 const struct nls_table *nls_codepage)
3322 struct smb_hdr *smb_buffer;
3323 struct smb_hdr *smb_buffer_response;
3326 unsigned char *bcc_ptr;
3334 smb_buffer = cifs_buf_get();
3335 if (smb_buffer == NULL) {
3338 smb_buffer_response = smb_buffer;
3340 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3341 NULL /*no tid */ , 4 /*wct */ );
3343 smb_buffer->Mid = GetNextMid(ses->server);
3344 smb_buffer->Uid = ses->Suid;
3345 pSMB = (TCONX_REQ *) smb_buffer;
3346 pSMBr = (TCONX_RSP *) smb_buffer_response;
3348 pSMB->AndXCommand = 0xFF;
3349 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3350 bcc_ptr = &pSMB->Password[0];
3351 if((ses->server->secMode) & SECMODE_USER) {
3352 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3353 *bcc_ptr = 0; /* password is null byte */
3354 bcc_ptr++; /* skip password */
3355 /* already aligned so no need to do it below */
3357 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
3358 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3359 specified as required (when that support is added to
3360 the vfs in the future) as only NTLM or the much
3361 weaker LANMAN (which we do not send by default) is accepted
3362 by Samba (not sure whether other servers allow
3363 NTLMv2 password here) */
3364 #ifdef CONFIG_CIFS_WEAK_PW_HASH
3365 if((extended_security & CIFSSEC_MAY_LANMAN) &&
3366 (ses->server->secType == LANMAN))
3367 calc_lanman_hash(ses, bcc_ptr);
3369 #endif /* CIFS_WEAK_PW_HASH */
3370 SMBNTencrypt(ses->password,
3371 ses->server->cryptKey,
3374 bcc_ptr += CIFS_SESS_KEY_SIZE;
3375 if(ses->capabilities & CAP_UNICODE) {
3376 /* must align unicode strings */
3377 *bcc_ptr = 0; /* null byte password */
3382 if(ses->server->secMode &
3383 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3384 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3386 if (ses->capabilities & CAP_STATUS32) {
3387 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3389 if (ses->capabilities & CAP_DFS) {
3390 smb_buffer->Flags2 |= SMBFLG2_DFS;
3392 if (ses->capabilities & CAP_UNICODE) {
3393 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3395 cifs_strtoUCS((__le16 *) bcc_ptr, tree,
3396 6 /* max utf8 char length in bytes */ *
3397 (/* server len*/ + 256 /* share len */), nls_codepage);
3398 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
3399 bcc_ptr += 2; /* skip trailing null */
3400 } else { /* ASCII */
3401 strcpy(bcc_ptr, tree);
3402 bcc_ptr += strlen(tree) + 1;
3404 strcpy(bcc_ptr, "?????");
3405 bcc_ptr += strlen("?????");
3407 count = bcc_ptr - &pSMB->Password[0];
3408 pSMB->hdr.smb_buf_length += count;
3409 pSMB->ByteCount = cpu_to_le16(count);
3411 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3413 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3414 /* above now done in SendReceive */
3415 if ((rc == 0) && (tcon != NULL)) {
3416 tcon->tidStatus = CifsGood;
3417 tcon->tid = smb_buffer_response->Tid;
3418 bcc_ptr = pByteArea(smb_buffer_response);
3419 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3420 /* skip service field (NB: this field is always ASCII) */
3421 bcc_ptr += length + 1;
3422 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3423 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3424 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3425 if ((bcc_ptr + (2 * length)) -
3426 pByteArea(smb_buffer_response) <=
3427 BCC(smb_buffer_response)) {
3428 kfree(tcon->nativeFileSystem);
3429 tcon->nativeFileSystem =
3430 kzalloc(length + 2, GFP_KERNEL);
3431 cifs_strfromUCS_le(tcon->nativeFileSystem,
3433 length, nls_codepage);
3434 bcc_ptr += 2 * length;
3435 bcc_ptr[0] = 0; /* null terminate the string */
3439 /* else do not bother copying these informational fields */
3441 length = strnlen(bcc_ptr, 1024);
3442 if ((bcc_ptr + length) -
3443 pByteArea(smb_buffer_response) <=
3444 BCC(smb_buffer_response)) {
3445 kfree(tcon->nativeFileSystem);
3446 tcon->nativeFileSystem =
3447 kzalloc(length + 1, GFP_KERNEL);
3448 strncpy(tcon->nativeFileSystem, bcc_ptr,
3451 /* else do not bother copying these informational fields */
3453 if(smb_buffer_response->WordCount == 3)
3454 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3457 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3458 } else if ((rc == 0) && tcon == NULL) {
3459 /* all we need to save for IPC$ connection */
3460 ses->ipc_tid = smb_buffer_response->Tid;
3464 cifs_buf_release(smb_buffer);
3469 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3473 struct cifsSesInfo *ses = NULL;
3474 struct task_struct *cifsd_task;
3478 if (cifs_sb->tcon) {
3479 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3480 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3485 tconInfoFree(cifs_sb->tcon);
3486 if ((ses) && (ses->server)) {
3487 /* save off task so we do not refer to ses later */
3488 cifsd_task = ses->server->tsk;
3489 cFYI(1, ("About to do SMBLogoff "));
3490 rc = CIFSSMBLogoff(xid, ses);
3494 } else if (rc == -ESHUTDOWN) {
3495 cFYI(1,("Waking up socket by sending it signal"));
3497 send_sig(SIGKILL,cifsd_task,1);
3498 wait_for_completion(&cifsd_complete);
3501 } /* else - we have an smb session
3502 left on this socket do not kill cifsd */
3504 cFYI(1, ("No session or bad tcon"));
3507 cifs_sb->tcon = NULL;
3509 schedule_timeout_interruptible(msecs_to_jiffies(500));
3514 return rc; /* BB check if we should always return zero here */
3517 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3518 struct nls_table * nls_info)
3521 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3522 int ntlmv2_flag = FALSE;
3525 /* what if server changes its buffer size after dropping the session? */
3526 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3527 rc = CIFSSMBNegotiate(xid, pSesInfo);
3528 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3529 rc = CIFSSMBNegotiate(xid, pSesInfo);
3534 spin_lock(&GlobalMid_Lock);
3535 if(pSesInfo->server->tcpStatus != CifsExiting)
3536 pSesInfo->server->tcpStatus = CifsGood;
3539 spin_unlock(&GlobalMid_Lock);
3545 pSesInfo->capabilities = pSesInfo->server->capabilities;
3546 if(linuxExtEnabled == 0)
3547 pSesInfo->capabilities &= (~CAP_UNIX);
3548 /* pSesInfo->sequence_number = 0;*/
3549 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
3550 pSesInfo->server->secMode,
3551 pSesInfo->server->capabilities,
3552 pSesInfo->server->timeZone));
3553 #ifdef CONFIG_CIFS_EXPERIMENTAL
3554 if(experimEnabled > 1)
3555 rc = CIFS_SessSetup(xid, pSesInfo,
3556 first_time, nls_info);
3559 if (extended_security
3560 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3561 && (pSesInfo->server->secType == NTLMSSP)) {
3562 cFYI(1, ("New style sesssetup"));
3563 rc = CIFSSpnegoSessSetup(xid, pSesInfo,
3564 NULL /* security blob */,
3565 0 /* blob length */,
3567 } else if (extended_security
3568 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3569 && (pSesInfo->server->secType == RawNTLMSSP)) {
3570 cFYI(1, ("NTLMSSP sesssetup"));
3571 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3578 cFYI(1,("Can use more secure NTLM version 2 password hash"));
3579 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3584 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3586 CalcNTLMv2_response(pSesInfo,v2_response);
3588 cifs_calculate_ntlmv2_mac_key(
3589 pSesInfo->server->mac_signing_key,
3590 response, ntlm_session_key, */
3592 /* BB Put dummy sig in SessSetup PDU? */
3599 SMBNTencrypt(pSesInfo->password,
3600 pSesInfo->server->cryptKey,
3604 cifs_calculate_mac_key(
3605 pSesInfo->server->mac_signing_key,
3607 pSesInfo->password);
3609 /* for better security the weaker lanman hash not sent
3610 in AuthSessSetup so we no longer calculate it */
3612 rc = CIFSNTLMSSPAuthSessSetup(xid,
3618 } else { /* old style NTLM 0.12 session setup */
3619 SMBNTencrypt(pSesInfo->password,
3620 pSesInfo->server->cryptKey,
3624 cifs_calculate_mac_key(
3625 pSesInfo->server->mac_signing_key,
3626 ntlm_session_key, pSesInfo->password);
3628 rc = CIFSSessSetup(xid, pSesInfo,
3629 ntlm_session_key, nls_info);
3632 cERROR(1,("Send error in SessSetup = %d",rc));
3634 cFYI(1,("CIFS Session Established successfully"));
3635 pSesInfo->status = CifsGood;