[CIFS] Add nodfs mount option
[linux-2.6/verdex.git] / fs / cifs / connect.c
blob17ca8ce81bb78de0e14cc91259b2c4bb3ac0f02b
1 /*
2 * fs/cifs/connect.c
4 * Copyright (C) International Business Machines Corp., 2002,2008
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
21 #include <linux/fs.h>
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/kthread.h>
34 #include <linux/pagevec.h>
35 #include <linux/freezer.h>
36 #include <asm/uaccess.h>
37 #include <asm/processor.h>
38 #include "cifspdu.h"
39 #include "cifsglob.h"
40 #include "cifsproto.h"
41 #include "cifs_unicode.h"
42 #include "cifs_debug.h"
43 #include "cifs_fs_sb.h"
44 #include "ntlmssp.h"
45 #include "nterr.h"
46 #include "rfc1002pdu.h"
47 #include "cn_cifs.h"
49 #define CIFS_PORT 445
50 #define RFC1001_PORT 139
52 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
53 unsigned char *p24);
55 extern mempool_t *cifs_req_poolp;
57 struct smb_vol {
58 char *username;
59 char *password;
60 char *domainname;
61 char *UNC;
62 char *UNCip;
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 */
67 uid_t linux_uid;
68 gid_t linux_gid;
69 mode_t file_mode;
70 mode_t dir_mode;
71 unsigned secFlg;
72 bool rw:1;
73 bool retry:1;
74 bool intr:1;
75 bool setuids:1;
76 bool override_uid:1;
77 bool override_gid:1;
78 bool dynperm:1;
79 bool noperm:1;
80 bool no_psx_acl:1; /* set if posix acl support should be disabled */
81 bool cifs_acl:1;
82 bool no_xattr:1; /* set if xattr (EA) support should be disabled*/
83 bool server_ino:1; /* use inode numbers from server ie UniqueId */
84 bool direct_io:1;
85 bool remap:1; /* set to remap seven reserved chars in filenames */
86 bool posix_paths:1; /* unset to not ask for posix pathnames. */
87 bool no_linux_ext:1;
88 bool sfu_emul:1;
89 bool nullauth:1; /* attempt to authenticate with null user */
90 bool nocase:1; /* request case insensitive filenames */
91 bool nobrl:1; /* disable sending byte range locks to srv */
92 bool seal:1; /* request transport encryption on share */
93 bool nodfs:1;
94 unsigned int rsize;
95 unsigned int wsize;
96 unsigned int sockopt;
97 unsigned short int port;
98 char *prepath;
101 static int ipv4_connect(struct sockaddr_in *psin_server,
102 struct socket **csocket,
103 char *netb_name,
104 char *server_netb_name);
105 static int ipv6_connect(struct sockaddr_in6 *psin_server,
106 struct socket **csocket);
110 * cifs tcp session reconnection
112 * mark tcp session as reconnecting so temporarily locked
113 * mark all smb sessions as reconnecting for tcp session
114 * reconnect tcp session
115 * wake up waiters on reconnection? - (not needed currently)
118 static int
119 cifs_reconnect(struct TCP_Server_Info *server)
121 int rc = 0;
122 struct list_head *tmp;
123 struct cifsSesInfo *ses;
124 struct cifsTconInfo *tcon;
125 struct mid_q_entry *mid_entry;
127 spin_lock(&GlobalMid_Lock);
128 if (kthread_should_stop()) {
129 /* the demux thread will exit normally
130 next time through the loop */
131 spin_unlock(&GlobalMid_Lock);
132 return rc;
133 } else
134 server->tcpStatus = CifsNeedReconnect;
135 spin_unlock(&GlobalMid_Lock);
136 server->maxBuf = 0;
138 cFYI(1, ("Reconnecting tcp session"));
140 /* before reconnecting the tcp session, mark the smb session (uid)
141 and the tid bad so they are not used until reconnected */
142 read_lock(&GlobalSMBSeslock);
143 list_for_each(tmp, &GlobalSMBSessionList) {
144 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
145 if (ses->server) {
146 if (ses->server == server) {
147 ses->status = CifsNeedReconnect;
148 ses->ipc_tid = 0;
151 /* else tcp and smb sessions need reconnection */
153 list_for_each(tmp, &GlobalTreeConnectionList) {
154 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
155 if ((tcon->ses) && (tcon->ses->server == server))
156 tcon->tidStatus = CifsNeedReconnect;
158 read_unlock(&GlobalSMBSeslock);
159 /* do not want to be sending data on a socket we are freeing */
160 down(&server->tcpSem);
161 if (server->ssocket) {
162 cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state,
163 server->ssocket->flags));
164 kernel_sock_shutdown(server->ssocket, SHUT_WR);
165 cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx",
166 server->ssocket->state,
167 server->ssocket->flags));
168 sock_release(server->ssocket);
169 server->ssocket = NULL;
172 spin_lock(&GlobalMid_Lock);
173 list_for_each(tmp, &server->pending_mid_q) {
174 mid_entry = list_entry(tmp, struct
175 mid_q_entry,
176 qhead);
177 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
178 /* Mark other intransit requests as needing
179 retry so we do not immediately mark the
180 session bad again (ie after we reconnect
181 below) as they timeout too */
182 mid_entry->midState = MID_RETRY_NEEDED;
185 spin_unlock(&GlobalMid_Lock);
186 up(&server->tcpSem);
188 while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
189 try_to_freeze();
190 if (server->protocolType == IPV6) {
191 rc = ipv6_connect(&server->addr.sockAddr6,
192 &server->ssocket);
193 } else {
194 rc = ipv4_connect(&server->addr.sockAddr,
195 &server->ssocket,
196 server->workstation_RFC1001_name,
197 server->server_RFC1001_name);
199 if (rc) {
200 cFYI(1, ("reconnect error %d", rc));
201 msleep(3000);
202 } else {
203 atomic_inc(&tcpSesReconnectCount);
204 spin_lock(&GlobalMid_Lock);
205 if (!kthread_should_stop())
206 server->tcpStatus = CifsGood;
207 server->sequence_number = 0;
208 spin_unlock(&GlobalMid_Lock);
209 /* atomic_set(&server->inFlight,0);*/
210 wake_up(&server->response_q);
213 return rc;
217 return codes:
218 0 not a transact2, or all data present
219 >0 transact2 with that much data missing
220 -EINVAL = invalid transact2
223 static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize)
225 struct smb_t2_rsp *pSMBt;
226 int total_data_size;
227 int data_in_this_rsp;
228 int remaining;
230 if (pSMB->Command != SMB_COM_TRANSACTION2)
231 return 0;
233 /* check for plausible wct, bcc and t2 data and parm sizes */
234 /* check for parm and data offset going beyond end of smb */
235 if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
236 cFYI(1, ("invalid transact2 word count"));
237 return -EINVAL;
240 pSMBt = (struct smb_t2_rsp *)pSMB;
242 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
243 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
245 remaining = total_data_size - data_in_this_rsp;
247 if (remaining == 0)
248 return 0;
249 else if (remaining < 0) {
250 cFYI(1, ("total data %d smaller than data in frame %d",
251 total_data_size, data_in_this_rsp));
252 return -EINVAL;
253 } else {
254 cFYI(1, ("missing %d bytes from transact2, check next response",
255 remaining));
256 if (total_data_size > maxBufSize) {
257 cERROR(1, ("TotalDataSize %d is over maximum buffer %d",
258 total_data_size, maxBufSize));
259 return -EINVAL;
261 return remaining;
265 static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
267 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
268 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
269 int total_data_size;
270 int total_in_buf;
271 int remaining;
272 int total_in_buf2;
273 char *data_area_of_target;
274 char *data_area_of_buf2;
275 __u16 byte_count;
277 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
279 if (total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
280 cFYI(1, ("total data size of primary and secondary t2 differ"));
283 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
285 remaining = total_data_size - total_in_buf;
287 if (remaining < 0)
288 return -EINVAL;
290 if (remaining == 0) /* nothing to do, ignore */
291 return 0;
293 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
294 if (remaining < total_in_buf2) {
295 cFYI(1, ("transact2 2nd response contains too much data"));
298 /* find end of first SMB data area */
299 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
300 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
301 /* validate target area */
303 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
304 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
306 data_area_of_target += total_in_buf;
308 /* copy second buffer into end of first buffer */
309 memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
310 total_in_buf += total_in_buf2;
311 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
312 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
313 byte_count += total_in_buf2;
314 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
316 byte_count = pTargetSMB->smb_buf_length;
317 byte_count += total_in_buf2;
319 /* BB also add check that we are not beyond maximum buffer size */
321 pTargetSMB->smb_buf_length = byte_count;
323 if (remaining == total_in_buf2) {
324 cFYI(1, ("found the last secondary response"));
325 return 0; /* we are done */
326 } else /* more responses to go */
327 return 1;
331 static int
332 cifs_demultiplex_thread(struct TCP_Server_Info *server)
334 int length;
335 unsigned int pdu_length, total_read;
336 struct smb_hdr *smb_buffer = NULL;
337 struct smb_hdr *bigbuf = NULL;
338 struct smb_hdr *smallbuf = NULL;
339 struct msghdr smb_msg;
340 struct kvec iov;
341 struct socket *csocket = server->ssocket;
342 struct list_head *tmp;
343 struct cifsSesInfo *ses;
344 struct task_struct *task_to_wake = NULL;
345 struct mid_q_entry *mid_entry;
346 char temp;
347 bool isLargeBuf = false;
348 bool isMultiRsp;
349 int reconnect;
351 current->flags |= PF_MEMALLOC;
352 cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
354 length = atomic_inc_return(&tcpSesAllocCount);
355 if (length > 1)
356 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
357 GFP_KERNEL);
359 set_freezable();
360 while (!kthread_should_stop()) {
361 if (try_to_freeze())
362 continue;
363 if (bigbuf == NULL) {
364 bigbuf = cifs_buf_get();
365 if (!bigbuf) {
366 cERROR(1, ("No memory for large SMB response"));
367 msleep(3000);
368 /* retry will check if exiting */
369 continue;
371 } else if (isLargeBuf) {
372 /* we are reusing a dirty large buf, clear its start */
373 memset(bigbuf, 0, sizeof(struct smb_hdr));
376 if (smallbuf == NULL) {
377 smallbuf = cifs_small_buf_get();
378 if (!smallbuf) {
379 cERROR(1, ("No memory for SMB response"));
380 msleep(1000);
381 /* retry will check if exiting */
382 continue;
384 /* beginning of smb buffer is cleared in our buf_get */
385 } else /* if existing small buf clear beginning */
386 memset(smallbuf, 0, sizeof(struct smb_hdr));
388 isLargeBuf = false;
389 isMultiRsp = false;
390 smb_buffer = smallbuf;
391 iov.iov_base = smb_buffer;
392 iov.iov_len = 4;
393 smb_msg.msg_control = NULL;
394 smb_msg.msg_controllen = 0;
395 pdu_length = 4; /* enough to get RFC1001 header */
396 incomplete_rcv:
397 length =
398 kernel_recvmsg(csocket, &smb_msg,
399 &iov, 1, pdu_length, 0 /* BB other flags? */);
401 if (kthread_should_stop()) {
402 break;
403 } else if (server->tcpStatus == CifsNeedReconnect) {
404 cFYI(1, ("Reconnect after server stopped responding"));
405 cifs_reconnect(server);
406 cFYI(1, ("call to reconnect done"));
407 csocket = server->ssocket;
408 continue;
409 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
410 msleep(1); /* minimum sleep to prevent looping
411 allowing socket to clear and app threads to set
412 tcpStatus CifsNeedReconnect if server hung */
413 if (pdu_length < 4)
414 goto incomplete_rcv;
415 else
416 continue;
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 */
424 break;
426 if (!try_to_freeze() && (length == -EINTR)) {
427 cFYI(1, ("cifsd thread killed"));
428 break;
430 cFYI(1, ("Reconnect after unexpected peek error %d",
431 length));
432 cifs_reconnect(server);
433 csocket = server->ssocket;
434 wake_up(&server->response_q);
435 continue;
436 } else if (length < pdu_length) {
437 cFYI(1, ("requested %d bytes but only got %d bytes",
438 pdu_length, length));
439 pdu_length -= length;
440 msleep(1);
441 goto incomplete_rcv;
444 /* The right amount was read from socket - 4 bytes */
445 /* so we can now interpret the length field */
447 /* the first byte big endian of the length field,
448 is actually not part of the length but the type
449 with the most common, zero, as regular data */
450 temp = *((char *) smb_buffer);
452 /* Note that FC 1001 length is big endian on the wire,
453 but we convert it here so it is always manipulated
454 as host byte order */
455 pdu_length = be32_to_cpu((__force __be32)smb_buffer->smb_buf_length);
456 smb_buffer->smb_buf_length = pdu_length;
458 cFYI(1, ("rfc1002 length 0x%x", pdu_length+4));
460 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
461 continue;
462 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
463 cFYI(1, ("Good RFC 1002 session rsp"));
464 continue;
465 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
466 /* we get this from Windows 98 instead of
467 an error on SMB negprot response */
468 cFYI(1, ("Negative RFC1002 Session Response Error 0x%x)",
469 pdu_length));
470 if (server->tcpStatus == CifsNew) {
471 /* if nack on negprot (rather than
472 ret of smb negprot error) reconnecting
473 not going to help, ret error to mount */
474 break;
475 } else {
476 /* give server a second to
477 clean up before reconnect attempt */
478 msleep(1000);
479 /* always try 445 first on reconnect
480 since we get NACK on some if we ever
481 connected to port 139 (the NACK is
482 since we do not begin with RFC1001
483 session initialize frame) */
484 server->addr.sockAddr.sin_port =
485 htons(CIFS_PORT);
486 cifs_reconnect(server);
487 csocket = server->ssocket;
488 wake_up(&server->response_q);
489 continue;
491 } else if (temp != (char) 0) {
492 cERROR(1, ("Unknown RFC 1002 frame"));
493 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
494 length);
495 cifs_reconnect(server);
496 csocket = server->ssocket;
497 continue;
500 /* else we have an SMB response */
501 if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
502 (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
503 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
504 length, pdu_length+4));
505 cifs_reconnect(server);
506 csocket = server->ssocket;
507 wake_up(&server->response_q);
508 continue;
511 /* else length ok */
512 reconnect = 0;
514 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
515 isLargeBuf = true;
516 memcpy(bigbuf, smallbuf, 4);
517 smb_buffer = bigbuf;
519 length = 0;
520 iov.iov_base = 4 + (char *)smb_buffer;
521 iov.iov_len = pdu_length;
522 for (total_read = 0; total_read < pdu_length;
523 total_read += length) {
524 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
525 pdu_length - total_read, 0);
526 if (kthread_should_stop() ||
527 (length == -EINTR)) {
528 /* then will exit */
529 reconnect = 2;
530 break;
531 } else if (server->tcpStatus == CifsNeedReconnect) {
532 cifs_reconnect(server);
533 csocket = server->ssocket;
534 /* Reconnect wakes up rspns q */
535 /* Now we will reread sock */
536 reconnect = 1;
537 break;
538 } else if ((length == -ERESTARTSYS) ||
539 (length == -EAGAIN)) {
540 msleep(1); /* minimum sleep to prevent looping,
541 allowing socket to clear and app
542 threads to set tcpStatus
543 CifsNeedReconnect if server hung*/
544 length = 0;
545 continue;
546 } else if (length <= 0) {
547 cERROR(1, ("Received no data, expecting %d",
548 pdu_length - total_read));
549 cifs_reconnect(server);
550 csocket = server->ssocket;
551 reconnect = 1;
552 break;
555 if (reconnect == 2)
556 break;
557 else if (reconnect == 1)
558 continue;
560 length += 4; /* account for rfc1002 hdr */
563 dump_smb(smb_buffer, length);
564 if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
565 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
566 continue;
570 task_to_wake = NULL;
571 spin_lock(&GlobalMid_Lock);
572 list_for_each(tmp, &server->pending_mid_q) {
573 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
575 if ((mid_entry->mid == smb_buffer->Mid) &&
576 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
577 (mid_entry->command == smb_buffer->Command)) {
578 if (check2ndT2(smb_buffer,server->maxBuf) > 0) {
579 /* We have a multipart transact2 resp */
580 isMultiRsp = true;
581 if (mid_entry->resp_buf) {
582 /* merge response - fix up 1st*/
583 if (coalesce_t2(smb_buffer,
584 mid_entry->resp_buf)) {
585 mid_entry->multiRsp =
586 true;
587 break;
588 } else {
589 /* all parts received */
590 mid_entry->multiEnd =
591 true;
592 goto multi_t2_fnd;
594 } else {
595 if (!isLargeBuf) {
596 cERROR(1,("1st trans2 resp needs bigbuf"));
597 /* BB maybe we can fix this up, switch
598 to already allocated large buffer? */
599 } else {
600 /* Have first buffer */
601 mid_entry->resp_buf =
602 smb_buffer;
603 mid_entry->largeBuf =
604 true;
605 bigbuf = NULL;
608 break;
610 mid_entry->resp_buf = smb_buffer;
611 mid_entry->largeBuf = isLargeBuf;
612 multi_t2_fnd:
613 task_to_wake = mid_entry->tsk;
614 mid_entry->midState = MID_RESPONSE_RECEIVED;
615 #ifdef CONFIG_CIFS_STATS2
616 mid_entry->when_received = jiffies;
617 #endif
618 /* so we do not time out requests to server
619 which is still responding (since server could
620 be busy but not dead) */
621 server->lstrp = jiffies;
622 break;
625 spin_unlock(&GlobalMid_Lock);
626 if (task_to_wake) {
627 /* Was previous buf put in mpx struct for multi-rsp? */
628 if (!isMultiRsp) {
629 /* smb buffer will be freed by user thread */
630 if (isLargeBuf)
631 bigbuf = NULL;
632 else
633 smallbuf = NULL;
635 wake_up_process(task_to_wake);
636 } else if (!is_valid_oplock_break(smb_buffer, server) &&
637 !isMultiRsp) {
638 cERROR(1, ("No task to wake, unknown frame received! "
639 "NumMids %d", midCount.counter));
640 cifs_dump_mem("Received Data is: ", (char *)smb_buffer,
641 sizeof(struct smb_hdr));
642 #ifdef CONFIG_CIFS_DEBUG2
643 cifs_dump_detail(smb_buffer);
644 cifs_dump_mids(server);
645 #endif /* CIFS_DEBUG2 */
648 } /* end while !EXITING */
650 spin_lock(&GlobalMid_Lock);
651 server->tcpStatus = CifsExiting;
652 spin_unlock(&GlobalMid_Lock);
653 wake_up_all(&server->response_q);
655 /* don't exit until kthread_stop is called */
656 set_current_state(TASK_UNINTERRUPTIBLE);
657 while (!kthread_should_stop()) {
658 schedule();
659 set_current_state(TASK_UNINTERRUPTIBLE);
661 set_current_state(TASK_RUNNING);
663 /* check if we have blocked requests that need to free */
664 /* Note that cifs_max_pending is normally 50, but
665 can be set at module install time to as little as two */
666 spin_lock(&GlobalMid_Lock);
667 if (atomic_read(&server->inFlight) >= cifs_max_pending)
668 atomic_set(&server->inFlight, cifs_max_pending - 1);
669 /* We do not want to set the max_pending too low or we
670 could end up with the counter going negative */
671 spin_unlock(&GlobalMid_Lock);
672 /* Although there should not be any requests blocked on
673 this queue it can not hurt to be paranoid and try to wake up requests
674 that may haven been blocked when more than 50 at time were on the wire
675 to the same server - they now will see the session is in exit state
676 and get out of SendReceive. */
677 wake_up_all(&server->request_q);
678 /* give those requests time to exit */
679 msleep(125);
681 if (server->ssocket) {
682 sock_release(csocket);
683 server->ssocket = NULL;
685 /* buffer usuallly freed in free_mid - need to free it here on exit */
686 cifs_buf_release(bigbuf);
687 if (smallbuf) /* no sense logging a debug message if NULL */
688 cifs_small_buf_release(smallbuf);
690 read_lock(&GlobalSMBSeslock);
691 if (list_empty(&server->pending_mid_q)) {
692 /* loop through server session structures attached to this and
693 mark them dead */
694 list_for_each(tmp, &GlobalSMBSessionList) {
695 ses =
696 list_entry(tmp, struct cifsSesInfo,
697 cifsSessionList);
698 if (ses->server == server) {
699 ses->status = CifsExiting;
700 ses->server = NULL;
703 read_unlock(&GlobalSMBSeslock);
704 } else {
705 /* although we can not zero the server struct pointer yet,
706 since there are active requests which may depnd on them,
707 mark the corresponding SMB sessions as exiting too */
708 list_for_each(tmp, &GlobalSMBSessionList) {
709 ses = list_entry(tmp, struct cifsSesInfo,
710 cifsSessionList);
711 if (ses->server == server)
712 ses->status = CifsExiting;
715 spin_lock(&GlobalMid_Lock);
716 list_for_each(tmp, &server->pending_mid_q) {
717 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
718 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
719 cFYI(1, ("Clearing Mid 0x%x - waking up ",
720 mid_entry->mid));
721 task_to_wake = mid_entry->tsk;
722 if (task_to_wake)
723 wake_up_process(task_to_wake);
726 spin_unlock(&GlobalMid_Lock);
727 read_unlock(&GlobalSMBSeslock);
728 /* 1/8th of sec is more than enough time for them to exit */
729 msleep(125);
732 if (!list_empty(&server->pending_mid_q)) {
733 /* mpx threads have not exited yet give them
734 at least the smb send timeout time for long ops */
735 /* due to delays on oplock break requests, we need
736 to wait at least 45 seconds before giving up
737 on a request getting a response and going ahead
738 and killing cifsd */
739 cFYI(1, ("Wait for exit from demultiplex thread"));
740 msleep(46000);
741 /* if threads still have not exited they are probably never
742 coming home not much else we can do but free the memory */
745 /* last chance to mark ses pointers invalid
746 if there are any pointing to this (e.g
747 if a crazy root user tried to kill cifsd
748 kernel thread explicitly this might happen) */
749 write_lock(&GlobalSMBSeslock);
750 list_for_each(tmp, &GlobalSMBSessionList) {
751 ses = list_entry(tmp, struct cifsSesInfo,
752 cifsSessionList);
753 if (ses->server == server)
754 ses->server = NULL;
756 write_unlock(&GlobalSMBSeslock);
758 kfree(server->hostname);
759 kfree(server);
761 length = atomic_dec_return(&tcpSesAllocCount);
762 if (length > 0)
763 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
764 GFP_KERNEL);
766 return 0;
769 /* extract the host portion of the UNC string */
770 static char *
771 extract_hostname(const char *unc)
773 const char *src;
774 char *dst, *delim;
775 unsigned int len;
777 /* skip double chars at beginning of string */
778 /* BB: check validity of these bytes? */
779 src = unc + 2;
781 /* delimiter between hostname and sharename is always '\\' now */
782 delim = strchr(src, '\\');
783 if (!delim)
784 return ERR_PTR(-EINVAL);
786 len = delim - src;
787 dst = kmalloc((len + 1), GFP_KERNEL);
788 if (dst == NULL)
789 return ERR_PTR(-ENOMEM);
791 memcpy(dst, src, len);
792 dst[len] = '\0';
794 return dst;
797 static int
798 cifs_parse_mount_options(char *options, const char *devname,
799 struct smb_vol *vol)
801 char *value;
802 char *data;
803 unsigned int temp_len, i, j;
804 char separator[2];
806 separator[0] = ',';
807 separator[1] = 0;
809 if (Local_System_Name[0] != 0)
810 memcpy(vol->source_rfc1001_name, Local_System_Name, 15);
811 else {
812 char *nodename = utsname()->nodename;
813 int n = strnlen(nodename, 15);
814 memset(vol->source_rfc1001_name, 0x20, 15);
815 for (i = 0; i < n; i++) {
816 /* does not have to be perfect mapping since field is
817 informational, only used for servers that do not support
818 port 445 and it can be overridden at mount time */
819 vol->source_rfc1001_name[i] = toupper(nodename[i]);
822 vol->source_rfc1001_name[15] = 0;
823 /* null target name indicates to use *SMBSERVR default called name
824 if we end up sending RFC1001 session initialize */
825 vol->target_rfc1001_name[0] = 0;
826 vol->linux_uid = current->uid; /* current->euid instead? */
827 vol->linux_gid = current->gid;
828 vol->dir_mode = S_IRWXUGO;
829 /* 2767 perms indicate mandatory locking support */
830 vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);
832 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
833 vol->rw = true;
834 /* default is always to request posix paths. */
835 vol->posix_paths = 1;
837 if (!options)
838 return 1;
840 if (strncmp(options, "sep=", 4) == 0) {
841 if (options[4] != 0) {
842 separator[0] = options[4];
843 options += 5;
844 } else {
845 cFYI(1, ("Null separator not allowed"));
849 while ((data = strsep(&options, separator)) != NULL) {
850 if (!*data)
851 continue;
852 if ((value = strchr(data, '=')) != NULL)
853 *value++ = '\0';
855 /* Have to parse this before we parse for "user" */
856 if (strnicmp(data, "user_xattr", 10) == 0) {
857 vol->no_xattr = 0;
858 } else if (strnicmp(data, "nouser_xattr", 12) == 0) {
859 vol->no_xattr = 1;
860 } else if (strnicmp(data, "user", 4) == 0) {
861 if (!value) {
862 printk(KERN_WARNING
863 "CIFS: invalid or missing username\n");
864 return 1; /* needs_arg; */
865 } else if (!*value) {
866 /* null user, ie anonymous, authentication */
867 vol->nullauth = 1;
869 if (strnlen(value, 200) < 200) {
870 vol->username = value;
871 } else {
872 printk(KERN_WARNING "CIFS: username too long\n");
873 return 1;
875 } else if (strnicmp(data, "pass", 4) == 0) {
876 if (!value) {
877 vol->password = NULL;
878 continue;
879 } else if (value[0] == 0) {
880 /* check if string begins with double comma
881 since that would mean the password really
882 does start with a comma, and would not
883 indicate an empty string */
884 if (value[1] != separator[0]) {
885 vol->password = NULL;
886 continue;
889 temp_len = strlen(value);
890 /* removed password length check, NTLM passwords
891 can be arbitrarily long */
893 /* if comma in password, the string will be
894 prematurely null terminated. Commas in password are
895 specified across the cifs mount interface by a double
896 comma ie ,, and a comma used as in other cases ie ','
897 as a parameter delimiter/separator is single and due
898 to the strsep above is temporarily zeroed. */
900 /* NB: password legally can have multiple commas and
901 the only illegal character in a password is null */
903 if ((value[temp_len] == 0) &&
904 (value[temp_len+1] == separator[0])) {
905 /* reinsert comma */
906 value[temp_len] = separator[0];
907 temp_len += 2; /* move after second comma */
908 while (value[temp_len] != 0) {
909 if (value[temp_len] == separator[0]) {
910 if (value[temp_len+1] ==
911 separator[0]) {
912 /* skip second comma */
913 temp_len++;
914 } else {
915 /* single comma indicating start
916 of next parm */
917 break;
920 temp_len++;
922 if (value[temp_len] == 0) {
923 options = NULL;
924 } else {
925 value[temp_len] = 0;
926 /* point option to start of next parm */
927 options = value + temp_len + 1;
929 /* go from value to value + temp_len condensing
930 double commas to singles. Note that this ends up
931 allocating a few bytes too many, which is ok */
932 vol->password = kzalloc(temp_len, GFP_KERNEL);
933 if (vol->password == NULL) {
934 printk(KERN_WARNING "CIFS: no memory "
935 "for password\n");
936 return 1;
938 for (i = 0, j = 0; i < temp_len; i++, j++) {
939 vol->password[j] = value[i];
940 if (value[i] == separator[0]
941 && value[i+1] == separator[0]) {
942 /* skip second comma */
943 i++;
946 vol->password[j] = 0;
947 } else {
948 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
949 if (vol->password == NULL) {
950 printk(KERN_WARNING "CIFS: no memory "
951 "for password\n");
952 return 1;
954 strcpy(vol->password, value);
956 } else if (strnicmp(data, "ip", 2) == 0) {
957 if (!value || !*value) {
958 vol->UNCip = NULL;
959 } else if (strnlen(value, 35) < 35) {
960 vol->UNCip = value;
961 } else {
962 printk(KERN_WARNING "CIFS: ip address "
963 "too long\n");
964 return 1;
966 } else if (strnicmp(data, "sec", 3) == 0) {
967 if (!value || !*value) {
968 cERROR(1, ("no security value specified"));
969 continue;
970 } else if (strnicmp(value, "krb5i", 5) == 0) {
971 vol->secFlg |= CIFSSEC_MAY_KRB5 |
972 CIFSSEC_MUST_SIGN;
973 } else if (strnicmp(value, "krb5p", 5) == 0) {
974 /* vol->secFlg |= CIFSSEC_MUST_SEAL |
975 CIFSSEC_MAY_KRB5; */
976 cERROR(1, ("Krb5 cifs privacy not supported"));
977 return 1;
978 } else if (strnicmp(value, "krb5", 4) == 0) {
979 vol->secFlg |= CIFSSEC_MAY_KRB5;
980 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
981 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
982 CIFSSEC_MUST_SIGN;
983 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
984 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
985 } else if (strnicmp(value, "ntlmi", 5) == 0) {
986 vol->secFlg |= CIFSSEC_MAY_NTLM |
987 CIFSSEC_MUST_SIGN;
988 } else if (strnicmp(value, "ntlm", 4) == 0) {
989 /* ntlm is default so can be turned off too */
990 vol->secFlg |= CIFSSEC_MAY_NTLM;
991 } else if (strnicmp(value, "nontlm", 6) == 0) {
992 /* BB is there a better way to do this? */
993 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
994 #ifdef CONFIG_CIFS_WEAK_PW_HASH
995 } else if (strnicmp(value, "lanman", 6) == 0) {
996 vol->secFlg |= CIFSSEC_MAY_LANMAN;
997 #endif
998 } else if (strnicmp(value, "none", 4) == 0) {
999 vol->nullauth = 1;
1000 } else {
1001 cERROR(1, ("bad security option: %s", value));
1002 return 1;
1004 } else if ((strnicmp(data, "unc", 3) == 0)
1005 || (strnicmp(data, "target", 6) == 0)
1006 || (strnicmp(data, "path", 4) == 0)) {
1007 if (!value || !*value) {
1008 printk(KERN_WARNING "CIFS: invalid path to "
1009 "network resource\n");
1010 return 1; /* needs_arg; */
1012 if ((temp_len = strnlen(value, 300)) < 300) {
1013 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1014 if (vol->UNC == NULL)
1015 return 1;
1016 strcpy(vol->UNC, value);
1017 if (strncmp(vol->UNC, "//", 2) == 0) {
1018 vol->UNC[0] = '\\';
1019 vol->UNC[1] = '\\';
1020 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1021 printk(KERN_WARNING
1022 "CIFS: UNC Path does not begin "
1023 "with // or \\\\ \n");
1024 return 1;
1026 } else {
1027 printk(KERN_WARNING "CIFS: UNC name too long\n");
1028 return 1;
1030 } else if ((strnicmp(data, "domain", 3) == 0)
1031 || (strnicmp(data, "workgroup", 5) == 0)) {
1032 if (!value || !*value) {
1033 printk(KERN_WARNING "CIFS: invalid domain name\n");
1034 return 1; /* needs_arg; */
1036 /* BB are there cases in which a comma can be valid in
1037 a domain name and need special handling? */
1038 if (strnlen(value, 256) < 256) {
1039 vol->domainname = value;
1040 cFYI(1, ("Domain name set"));
1041 } else {
1042 printk(KERN_WARNING "CIFS: domain name too "
1043 "long\n");
1044 return 1;
1046 } else if (strnicmp(data, "prefixpath", 10) == 0) {
1047 if (!value || !*value) {
1048 printk(KERN_WARNING
1049 "CIFS: invalid path prefix\n");
1050 return 1; /* needs_argument */
1052 if ((temp_len = strnlen(value, 1024)) < 1024) {
1053 if (value[0] != '/')
1054 temp_len++; /* missing leading slash */
1055 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1056 if (vol->prepath == NULL)
1057 return 1;
1058 if (value[0] != '/') {
1059 vol->prepath[0] = '/';
1060 strcpy(vol->prepath+1, value);
1061 } else
1062 strcpy(vol->prepath, value);
1063 cFYI(1, ("prefix path %s", vol->prepath));
1064 } else {
1065 printk(KERN_WARNING "CIFS: prefix too long\n");
1066 return 1;
1068 } else if (strnicmp(data, "iocharset", 9) == 0) {
1069 if (!value || !*value) {
1070 printk(KERN_WARNING "CIFS: invalid iocharset "
1071 "specified\n");
1072 return 1; /* needs_arg; */
1074 if (strnlen(value, 65) < 65) {
1075 if (strnicmp(value, "default", 7))
1076 vol->iocharset = value;
1077 /* if iocharset not set then load_nls_default
1078 is used by caller */
1079 cFYI(1, ("iocharset set to %s", value));
1080 } else {
1081 printk(KERN_WARNING "CIFS: iocharset name "
1082 "too long.\n");
1083 return 1;
1085 } else if (strnicmp(data, "uid", 3) == 0) {
1086 if (value && *value) {
1087 vol->linux_uid =
1088 simple_strtoul(value, &value, 0);
1089 vol->override_uid = 1;
1091 } else if (strnicmp(data, "gid", 3) == 0) {
1092 if (value && *value) {
1093 vol->linux_gid =
1094 simple_strtoul(value, &value, 0);
1095 vol->override_gid = 1;
1097 } else if (strnicmp(data, "file_mode", 4) == 0) {
1098 if (value && *value) {
1099 vol->file_mode =
1100 simple_strtoul(value, &value, 0);
1102 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1103 if (value && *value) {
1104 vol->dir_mode =
1105 simple_strtoul(value, &value, 0);
1107 } else if (strnicmp(data, "dirmode", 4) == 0) {
1108 if (value && *value) {
1109 vol->dir_mode =
1110 simple_strtoul(value, &value, 0);
1112 } else if (strnicmp(data, "port", 4) == 0) {
1113 if (value && *value) {
1114 vol->port =
1115 simple_strtoul(value, &value, 0);
1117 } else if (strnicmp(data, "rsize", 5) == 0) {
1118 if (value && *value) {
1119 vol->rsize =
1120 simple_strtoul(value, &value, 0);
1122 } else if (strnicmp(data, "wsize", 5) == 0) {
1123 if (value && *value) {
1124 vol->wsize =
1125 simple_strtoul(value, &value, 0);
1127 } else if (strnicmp(data, "sockopt", 5) == 0) {
1128 if (value && *value) {
1129 vol->sockopt =
1130 simple_strtoul(value, &value, 0);
1132 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1133 if (!value || !*value || (*value == ' ')) {
1134 cFYI(1, ("invalid (empty) netbiosname"));
1135 } else {
1136 memset(vol->source_rfc1001_name, 0x20, 15);
1137 for (i = 0; i < 15; i++) {
1138 /* BB are there cases in which a comma can be
1139 valid in this workstation netbios name (and need
1140 special handling)? */
1142 /* We do not uppercase netbiosname for user */
1143 if (value[i] == 0)
1144 break;
1145 else
1146 vol->source_rfc1001_name[i] =
1147 value[i];
1149 /* The string has 16th byte zero still from
1150 set at top of the function */
1151 if ((i == 15) && (value[i] != 0))
1152 printk(KERN_WARNING "CIFS: netbiosname"
1153 " longer than 15 truncated.\n");
1155 } else if (strnicmp(data, "servern", 7) == 0) {
1156 /* servernetbiosname specified override *SMBSERVER */
1157 if (!value || !*value || (*value == ' ')) {
1158 cFYI(1, ("empty server netbiosname specified"));
1159 } else {
1160 /* last byte, type, is 0x20 for servr type */
1161 memset(vol->target_rfc1001_name, 0x20, 16);
1163 for (i = 0; i < 15; i++) {
1164 /* BB are there cases in which a comma can be
1165 valid in this workstation netbios name
1166 (and need special handling)? */
1168 /* user or mount helper must uppercase
1169 the netbiosname */
1170 if (value[i] == 0)
1171 break;
1172 else
1173 vol->target_rfc1001_name[i] =
1174 value[i];
1176 /* The string has 16th byte zero still from
1177 set at top of the function */
1178 if ((i == 15) && (value[i] != 0))
1179 printk(KERN_WARNING "CIFS: server net"
1180 "biosname longer than 15 truncated.\n");
1182 } else if (strnicmp(data, "credentials", 4) == 0) {
1183 /* ignore */
1184 } else if (strnicmp(data, "version", 3) == 0) {
1185 /* ignore */
1186 } else if (strnicmp(data, "guest", 5) == 0) {
1187 /* ignore */
1188 } else if (strnicmp(data, "rw", 2) == 0) {
1189 vol->rw = true;
1190 } else if ((strnicmp(data, "suid", 4) == 0) ||
1191 (strnicmp(data, "nosuid", 6) == 0) ||
1192 (strnicmp(data, "exec", 4) == 0) ||
1193 (strnicmp(data, "noexec", 6) == 0) ||
1194 (strnicmp(data, "nodev", 5) == 0) ||
1195 (strnicmp(data, "noauto", 6) == 0) ||
1196 (strnicmp(data, "dev", 3) == 0)) {
1197 /* The mount tool or mount.cifs helper (if present)
1198 uses these opts to set flags, and the flags are read
1199 by the kernel vfs layer before we get here (ie
1200 before read super) so there is no point trying to
1201 parse these options again and set anything and it
1202 is ok to just ignore them */
1203 continue;
1204 } else if (strnicmp(data, "ro", 2) == 0) {
1205 vol->rw = false;
1206 } else if (strnicmp(data, "hard", 4) == 0) {
1207 vol->retry = 1;
1208 } else if (strnicmp(data, "soft", 4) == 0) {
1209 vol->retry = 0;
1210 } else if (strnicmp(data, "perm", 4) == 0) {
1211 vol->noperm = 0;
1212 } else if (strnicmp(data, "noperm", 6) == 0) {
1213 vol->noperm = 1;
1214 } else if (strnicmp(data, "mapchars", 8) == 0) {
1215 vol->remap = 1;
1216 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1217 vol->remap = 0;
1218 } else if (strnicmp(data, "sfu", 3) == 0) {
1219 vol->sfu_emul = 1;
1220 } else if (strnicmp(data, "nosfu", 5) == 0) {
1221 vol->sfu_emul = 0;
1222 } else if (strnicmp(data, "nodfs", 5) == 0) {
1223 vol->nodfs = 1;
1224 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1225 vol->posix_paths = 1;
1226 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1227 vol->posix_paths = 0;
1228 } else if (strnicmp(data, "nounix", 6) == 0) {
1229 vol->no_linux_ext = 1;
1230 } else if (strnicmp(data, "nolinux", 7) == 0) {
1231 vol->no_linux_ext = 1;
1232 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1233 (strnicmp(data, "ignorecase", 10) == 0)) {
1234 vol->nocase = 1;
1235 } else if (strnicmp(data, "brl", 3) == 0) {
1236 vol->nobrl = 0;
1237 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1238 (strnicmp(data, "nolock", 6) == 0)) {
1239 vol->nobrl = 1;
1240 /* turn off mandatory locking in mode
1241 if remote locking is turned off since the
1242 local vfs will do advisory */
1243 if (vol->file_mode ==
1244 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1245 vol->file_mode = S_IALLUGO;
1246 } else if (strnicmp(data, "setuids", 7) == 0) {
1247 vol->setuids = 1;
1248 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1249 vol->setuids = 0;
1250 } else if (strnicmp(data, "dynperm", 7) == 0) {
1251 vol->dynperm = true;
1252 } else if (strnicmp(data, "nodynperm", 9) == 0) {
1253 vol->dynperm = false;
1254 } else if (strnicmp(data, "nohard", 6) == 0) {
1255 vol->retry = 0;
1256 } else if (strnicmp(data, "nosoft", 6) == 0) {
1257 vol->retry = 1;
1258 } else if (strnicmp(data, "nointr", 6) == 0) {
1259 vol->intr = 0;
1260 } else if (strnicmp(data, "intr", 4) == 0) {
1261 vol->intr = 1;
1262 } else if (strnicmp(data, "serverino", 7) == 0) {
1263 vol->server_ino = 1;
1264 } else if (strnicmp(data, "noserverino", 9) == 0) {
1265 vol->server_ino = 0;
1266 } else if (strnicmp(data, "cifsacl", 7) == 0) {
1267 vol->cifs_acl = 1;
1268 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1269 vol->cifs_acl = 0;
1270 } else if (strnicmp(data, "acl", 3) == 0) {
1271 vol->no_psx_acl = 0;
1272 } else if (strnicmp(data, "noacl", 5) == 0) {
1273 vol->no_psx_acl = 1;
1274 } else if (strnicmp(data, "sign", 4) == 0) {
1275 vol->secFlg |= CIFSSEC_MUST_SIGN;
1276 } else if (strnicmp(data, "seal", 4) == 0) {
1277 /* we do not do the following in secFlags because seal
1278 is a per tree connection (mount) not a per socket
1279 or per-smb connection option in the protocol */
1280 /* vol->secFlg |= CIFSSEC_MUST_SEAL; */
1281 vol->seal = 1;
1282 } else if (strnicmp(data, "direct", 6) == 0) {
1283 vol->direct_io = 1;
1284 } else if (strnicmp(data, "forcedirectio", 13) == 0) {
1285 vol->direct_io = 1;
1286 } else if (strnicmp(data, "in6_addr", 8) == 0) {
1287 if (!value || !*value) {
1288 vol->in6_addr = NULL;
1289 } else if (strnlen(value, 49) == 48) {
1290 vol->in6_addr = value;
1291 } else {
1292 printk(KERN_WARNING "CIFS: ip v6 address not "
1293 "48 characters long\n");
1294 return 1;
1296 } else if (strnicmp(data, "noac", 4) == 0) {
1297 printk(KERN_WARNING "CIFS: Mount option noac not "
1298 "supported. Instead set "
1299 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
1300 } else
1301 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
1302 data);
1304 if (vol->UNC == NULL) {
1305 if (devname == NULL) {
1306 printk(KERN_WARNING "CIFS: Missing UNC name for mount "
1307 "target\n");
1308 return 1;
1310 if ((temp_len = strnlen(devname, 300)) < 300) {
1311 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1312 if (vol->UNC == NULL)
1313 return 1;
1314 strcpy(vol->UNC, devname);
1315 if (strncmp(vol->UNC, "//", 2) == 0) {
1316 vol->UNC[0] = '\\';
1317 vol->UNC[1] = '\\';
1318 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1319 printk(KERN_WARNING "CIFS: UNC Path does not "
1320 "begin with // or \\\\ \n");
1321 return 1;
1323 value = strpbrk(vol->UNC+2, "/\\");
1324 if (value)
1325 *value = '\\';
1326 } else {
1327 printk(KERN_WARNING "CIFS: UNC name too long\n");
1328 return 1;
1331 if (vol->UNCip == NULL)
1332 vol->UNCip = &vol->UNC[2];
1334 return 0;
1337 static struct cifsSesInfo *
1338 cifs_find_tcp_session(struct in_addr *target_ip_addr,
1339 struct in6_addr *target_ip6_addr,
1340 char *userName, struct TCP_Server_Info **psrvTcp)
1342 struct list_head *tmp;
1343 struct cifsSesInfo *ses;
1345 *psrvTcp = NULL;
1347 read_lock(&GlobalSMBSeslock);
1348 list_for_each(tmp, &GlobalSMBSessionList) {
1349 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1350 if (!ses->server)
1351 continue;
1353 if (target_ip_addr &&
1354 ses->server->addr.sockAddr.sin_addr.s_addr != target_ip_addr->s_addr)
1355 continue;
1356 else if (target_ip6_addr &&
1357 memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1358 target_ip6_addr, sizeof(*target_ip6_addr)))
1359 continue;
1360 /* BB lock server and tcp session; increment use count here?? */
1362 /* found a match on the TCP session */
1363 *psrvTcp = ses->server;
1365 /* BB check if reconnection needed */
1366 if (strncmp(ses->userName, userName, MAX_USERNAME_SIZE) == 0) {
1367 read_unlock(&GlobalSMBSeslock);
1368 /* Found exact match on both TCP and
1369 SMB sessions */
1370 return ses;
1372 /* else tcp and smb sessions need reconnection */
1374 read_unlock(&GlobalSMBSeslock);
1376 return NULL;
1379 static struct cifsTconInfo *
1380 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1382 struct list_head *tmp;
1383 struct cifsTconInfo *tcon;
1384 __be32 old_ip;
1386 read_lock(&GlobalSMBSeslock);
1388 list_for_each(tmp, &GlobalTreeConnectionList) {
1389 cFYI(1, ("Next tcon"));
1390 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1391 if (!tcon->ses || !tcon->ses->server)
1392 continue;
1394 old_ip = tcon->ses->server->addr.sockAddr.sin_addr.s_addr;
1395 cFYI(1, ("old ip addr: %x == new ip %x ?",
1396 old_ip, new_target_ip_addr));
1398 if (old_ip != new_target_ip_addr)
1399 continue;
1401 /* BB lock tcon, server, tcp session and increment use count? */
1402 /* found a match on the TCP session */
1403 /* BB check if reconnection needed */
1404 cFYI(1, ("IP match, old UNC: %s new: %s",
1405 tcon->treeName, uncName));
1407 if (strncmp(tcon->treeName, uncName, MAX_TREE_SIZE))
1408 continue;
1410 cFYI(1, ("and old usr: %s new: %s",
1411 tcon->treeName, uncName));
1413 if (strncmp(tcon->ses->userName, userName, MAX_USERNAME_SIZE))
1414 continue;
1416 /* matched smb session (user name) */
1417 read_unlock(&GlobalSMBSeslock);
1418 return tcon;
1421 read_unlock(&GlobalSMBSeslock);
1422 return NULL;
1426 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
1427 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
1428 struct dfs_info3_param **preferrals, int remap)
1430 char *temp_unc;
1431 int rc = 0;
1433 *pnum_referrals = 0;
1434 *preferrals = NULL;
1436 if (pSesInfo->ipc_tid == 0) {
1437 temp_unc = kmalloc(2 /* for slashes */ +
1438 strnlen(pSesInfo->serverName,
1439 SERVER_NAME_LEN_WITH_NULL * 2)
1440 + 1 + 4 /* slash IPC$ */ + 2,
1441 GFP_KERNEL);
1442 if (temp_unc == NULL)
1443 return -ENOMEM;
1444 temp_unc[0] = '\\';
1445 temp_unc[1] = '\\';
1446 strcpy(temp_unc + 2, pSesInfo->serverName);
1447 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1448 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1449 cFYI(1,
1450 ("CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid));
1451 kfree(temp_unc);
1453 if (rc == 0)
1454 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1455 pnum_referrals, nls_codepage, remap);
1456 /* BB map targetUNCs to dfs_info3 structures, here or
1457 in CIFSGetDFSRefer BB */
1459 return rc;
1462 #ifdef CONFIG_DEBUG_LOCK_ALLOC
1463 static struct lock_class_key cifs_key[2];
1464 static struct lock_class_key cifs_slock_key[2];
1466 static inline void
1467 cifs_reclassify_socket4(struct socket *sock)
1469 struct sock *sk = sock->sk;
1470 BUG_ON(sock_owned_by_user(sk));
1471 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
1472 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
1475 static inline void
1476 cifs_reclassify_socket6(struct socket *sock)
1478 struct sock *sk = sock->sk;
1479 BUG_ON(sock_owned_by_user(sk));
1480 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
1481 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
1483 #else
1484 static inline void
1485 cifs_reclassify_socket4(struct socket *sock)
1489 static inline void
1490 cifs_reclassify_socket6(struct socket *sock)
1493 #endif
1495 /* See RFC1001 section 14 on representation of Netbios names */
1496 static void rfc1002mangle(char *target, char *source, unsigned int length)
1498 unsigned int i, j;
1500 for (i = 0, j = 0; i < (length); i++) {
1501 /* mask a nibble at a time and encode */
1502 target[j] = 'A' + (0x0F & (source[i] >> 4));
1503 target[j+1] = 'A' + (0x0F & source[i]);
1504 j += 2;
1510 static int
1511 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1512 char *netbios_name, char *target_name)
1514 int rc = 0;
1515 int connected = 0;
1516 __be16 orig_port = 0;
1518 if (*csocket == NULL) {
1519 rc = sock_create_kern(PF_INET, SOCK_STREAM,
1520 IPPROTO_TCP, csocket);
1521 if (rc < 0) {
1522 cERROR(1, ("Error %d creating socket", rc));
1523 *csocket = NULL;
1524 return rc;
1525 } else {
1526 /* BB other socket options to set KEEPALIVE, NODELAY? */
1527 cFYI(1, ("Socket created"));
1528 (*csocket)->sk->sk_allocation = GFP_NOFS;
1529 cifs_reclassify_socket4(*csocket);
1533 psin_server->sin_family = AF_INET;
1534 if (psin_server->sin_port) { /* user overrode default port */
1535 rc = (*csocket)->ops->connect(*csocket,
1536 (struct sockaddr *) psin_server,
1537 sizeof(struct sockaddr_in), 0);
1538 if (rc >= 0)
1539 connected = 1;
1542 if (!connected) {
1543 /* save original port so we can retry user specified port
1544 later if fall back ports fail this time */
1545 orig_port = psin_server->sin_port;
1547 /* do not retry on the same port we just failed on */
1548 if (psin_server->sin_port != htons(CIFS_PORT)) {
1549 psin_server->sin_port = htons(CIFS_PORT);
1551 rc = (*csocket)->ops->connect(*csocket,
1552 (struct sockaddr *) psin_server,
1553 sizeof(struct sockaddr_in), 0);
1554 if (rc >= 0)
1555 connected = 1;
1558 if (!connected) {
1559 psin_server->sin_port = htons(RFC1001_PORT);
1560 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1561 psin_server,
1562 sizeof(struct sockaddr_in), 0);
1563 if (rc >= 0)
1564 connected = 1;
1567 /* give up here - unless we want to retry on different
1568 protocol families some day */
1569 if (!connected) {
1570 if (orig_port)
1571 psin_server->sin_port = orig_port;
1572 cFYI(1, ("Error %d connecting to server via ipv4", rc));
1573 sock_release(*csocket);
1574 *csocket = NULL;
1575 return rc;
1577 /* Eventually check for other socket options to change from
1578 the default. sock_setsockopt not used because it expects
1579 user space buffer */
1580 cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
1581 (*csocket)->sk->sk_sndbuf,
1582 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1583 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1584 /* make the bufsizes depend on wsize/rsize and max requests */
1585 if ((*csocket)->sk->sk_sndbuf < (200 * 1024))
1586 (*csocket)->sk->sk_sndbuf = 200 * 1024;
1587 if ((*csocket)->sk->sk_rcvbuf < (140 * 1024))
1588 (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1590 /* send RFC1001 sessinit */
1591 if (psin_server->sin_port == htons(RFC1001_PORT)) {
1592 /* some servers require RFC1001 sessinit before sending
1593 negprot - BB check reconnection in case where second
1594 sessinit is sent but no second negprot */
1595 struct rfc1002_session_packet *ses_init_buf;
1596 struct smb_hdr *smb_buf;
1597 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
1598 GFP_KERNEL);
1599 if (ses_init_buf) {
1600 ses_init_buf->trailer.session_req.called_len = 32;
1601 if (target_name && (target_name[0] != 0)) {
1602 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1603 target_name, 16);
1604 } else {
1605 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1606 DEFAULT_CIFS_CALLED_NAME, 16);
1609 ses_init_buf->trailer.session_req.calling_len = 32;
1610 /* calling name ends in null (byte 16) from old smb
1611 convention. */
1612 if (netbios_name && (netbios_name[0] != 0)) {
1613 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1614 netbios_name, 16);
1615 } else {
1616 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1617 "LINUX_CIFS_CLNT", 16);
1619 ses_init_buf->trailer.session_req.scope1 = 0;
1620 ses_init_buf->trailer.session_req.scope2 = 0;
1621 smb_buf = (struct smb_hdr *)ses_init_buf;
1622 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1623 smb_buf->smb_buf_length = 0x81000044;
1624 rc = smb_send(*csocket, smb_buf, 0x44,
1625 (struct sockaddr *)psin_server);
1626 kfree(ses_init_buf);
1627 msleep(1); /* RFC1001 layer in at least one server
1628 requires very short break before negprot
1629 presumably because not expecting negprot
1630 to follow so fast. This is a simple
1631 solution that works without
1632 complicating the code and causes no
1633 significant slowing down on mount
1634 for everyone else */
1636 /* else the negprot may still work without this
1637 even though malloc failed */
1641 return rc;
1644 static int
1645 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1647 int rc = 0;
1648 int connected = 0;
1649 __be16 orig_port = 0;
1651 if (*csocket == NULL) {
1652 rc = sock_create_kern(PF_INET6, SOCK_STREAM,
1653 IPPROTO_TCP, csocket);
1654 if (rc < 0) {
1655 cERROR(1, ("Error %d creating ipv6 socket", rc));
1656 *csocket = NULL;
1657 return rc;
1658 } else {
1659 /* BB other socket options to set KEEPALIVE, NODELAY? */
1660 cFYI(1, ("ipv6 Socket created"));
1661 (*csocket)->sk->sk_allocation = GFP_NOFS;
1662 cifs_reclassify_socket6(*csocket);
1666 psin_server->sin6_family = AF_INET6;
1668 if (psin_server->sin6_port) { /* user overrode default port */
1669 rc = (*csocket)->ops->connect(*csocket,
1670 (struct sockaddr *) psin_server,
1671 sizeof(struct sockaddr_in6), 0);
1672 if (rc >= 0)
1673 connected = 1;
1676 if (!connected) {
1677 /* save original port so we can retry user specified port
1678 later if fall back ports fail this time */
1680 orig_port = psin_server->sin6_port;
1681 /* do not retry on the same port we just failed on */
1682 if (psin_server->sin6_port != htons(CIFS_PORT)) {
1683 psin_server->sin6_port = htons(CIFS_PORT);
1685 rc = (*csocket)->ops->connect(*csocket,
1686 (struct sockaddr *) psin_server,
1687 sizeof(struct sockaddr_in6), 0);
1688 if (rc >= 0)
1689 connected = 1;
1692 if (!connected) {
1693 psin_server->sin6_port = htons(RFC1001_PORT);
1694 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1695 psin_server, sizeof(struct sockaddr_in6), 0);
1696 if (rc >= 0)
1697 connected = 1;
1700 /* give up here - unless we want to retry on different
1701 protocol families some day */
1702 if (!connected) {
1703 if (orig_port)
1704 psin_server->sin6_port = orig_port;
1705 cFYI(1, ("Error %d connecting to server via ipv6", rc));
1706 sock_release(*csocket);
1707 *csocket = NULL;
1708 return rc;
1710 /* Eventually check for other socket options to change from
1711 the default. sock_setsockopt not used because it expects
1712 user space buffer */
1713 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1715 return rc;
1718 void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
1719 struct super_block *sb, struct smb_vol *vol_info)
1721 /* if we are reconnecting then should we check to see if
1722 * any requested capabilities changed locally e.g. via
1723 * remount but we can not do much about it here
1724 * if they have (even if we could detect it by the following)
1725 * Perhaps we could add a backpointer to array of sb from tcon
1726 * or if we change to make all sb to same share the same
1727 * sb as NFS - then we only have one backpointer to sb.
1728 * What if we wanted to mount the server share twice once with
1729 * and once without posixacls or posix paths? */
1730 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1732 if (vol_info && vol_info->no_linux_ext) {
1733 tcon->fsUnixInfo.Capability = 0;
1734 tcon->unix_ext = 0; /* Unix Extensions disabled */
1735 cFYI(1, ("Linux protocol extensions disabled"));
1736 return;
1737 } else if (vol_info)
1738 tcon->unix_ext = 1; /* Unix Extensions supported */
1740 if (tcon->unix_ext == 0) {
1741 cFYI(1, ("Unix extensions disabled so not set on reconnect"));
1742 return;
1745 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
1746 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1748 /* check for reconnect case in which we do not
1749 want to change the mount behavior if we can avoid it */
1750 if (vol_info == NULL) {
1751 /* turn off POSIX ACL and PATHNAMES if not set
1752 originally at mount time */
1753 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
1754 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1755 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
1756 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
1757 cERROR(1, ("POSIXPATH support change"));
1758 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1759 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
1760 cERROR(1, ("possible reconnect error"));
1761 cERROR(1,
1762 ("server disabled POSIX path support"));
1766 cap &= CIFS_UNIX_CAP_MASK;
1767 if (vol_info && vol_info->no_psx_acl)
1768 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1769 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
1770 cFYI(1, ("negotiated posix acl support"));
1771 if (sb)
1772 sb->s_flags |= MS_POSIXACL;
1775 if (vol_info && vol_info->posix_paths == 0)
1776 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1777 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
1778 cFYI(1, ("negotiate posix pathnames"));
1779 if (sb)
1780 CIFS_SB(sb)->mnt_cifs_flags |=
1781 CIFS_MOUNT_POSIX_PATHS;
1784 /* We might be setting the path sep back to a different
1785 form if we are reconnecting and the server switched its
1786 posix path capability for this share */
1787 if (sb && (CIFS_SB(sb)->prepathlen > 0))
1788 CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
1790 if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {
1791 if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
1792 CIFS_SB(sb)->rsize = 127 * 1024;
1793 cFYI(DBG2,
1794 ("larger reads not supported by srv"));
1799 cFYI(1, ("Negotiate caps 0x%x", (int)cap));
1800 #ifdef CONFIG_CIFS_DEBUG2
1801 if (cap & CIFS_UNIX_FCNTL_CAP)
1802 cFYI(1, ("FCNTL cap"));
1803 if (cap & CIFS_UNIX_EXTATTR_CAP)
1804 cFYI(1, ("EXTATTR cap"));
1805 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
1806 cFYI(1, ("POSIX path cap"));
1807 if (cap & CIFS_UNIX_XATTR_CAP)
1808 cFYI(1, ("XATTR cap"));
1809 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
1810 cFYI(1, ("POSIX ACL cap"));
1811 if (cap & CIFS_UNIX_LARGE_READ_CAP)
1812 cFYI(1, ("very large read cap"));
1813 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
1814 cFYI(1, ("very large write cap"));
1815 #endif /* CIFS_DEBUG2 */
1816 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1817 if (vol_info == NULL) {
1818 cFYI(1, ("resetting capabilities failed"));
1819 } else
1820 cERROR(1, ("Negotiating Unix capabilities "
1821 "with the server failed. Consider "
1822 "mounting with the Unix Extensions\n"
1823 "disabled, if problems are found, "
1824 "by specifying the nounix mount "
1825 "option."));
1831 static void
1832 convert_delimiter(char *path, char delim)
1834 int i;
1835 char old_delim;
1837 if (path == NULL)
1838 return;
1840 if (delim == '/')
1841 old_delim = '\\';
1842 else
1843 old_delim = '/';
1845 for (i = 0; path[i] != '\0'; i++) {
1846 if (path[i] == old_delim)
1847 path[i] = delim;
1852 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1853 char *mount_data, const char *devname)
1855 int rc = 0;
1856 int xid;
1857 int address_type = AF_INET;
1858 struct socket *csocket = NULL;
1859 struct sockaddr_in sin_server;
1860 struct sockaddr_in6 sin_server6;
1861 struct smb_vol volume_info;
1862 struct cifsSesInfo *pSesInfo = NULL;
1863 struct cifsSesInfo *existingCifsSes = NULL;
1864 struct cifsTconInfo *tcon = NULL;
1865 struct TCP_Server_Info *srvTcp = NULL;
1867 xid = GetXid();
1869 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1871 memset(&volume_info, 0, sizeof(struct smb_vol));
1872 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1873 rc = -EINVAL;
1874 goto out;
1877 if (volume_info.nullauth) {
1878 cFYI(1, ("null user"));
1879 volume_info.username = "";
1880 } else if (volume_info.username) {
1881 /* BB fixme parse for domain name here */
1882 cFYI(1, ("Username: %s", volume_info.username));
1883 } else {
1884 cifserror("No username specified");
1885 /* In userspace mount helper we can get user name from alternate
1886 locations such as env variables and files on disk */
1887 rc = -EINVAL;
1888 goto out;
1891 if (volume_info.UNCip && volume_info.UNC) {
1892 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,
1893 &sin_server.sin_addr.s_addr);
1895 if (rc <= 0) {
1896 /* not ipv4 address, try ipv6 */
1897 rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,
1898 &sin_server6.sin6_addr.in6_u);
1899 if (rc > 0)
1900 address_type = AF_INET6;
1901 } else {
1902 address_type = AF_INET;
1905 if (rc <= 0) {
1906 /* we failed translating address */
1907 rc = -EINVAL;
1908 goto out;
1911 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1912 /* success */
1913 rc = 0;
1914 } else if (volume_info.UNCip) {
1915 /* BB using ip addr as server name to connect to the
1916 DFS root below */
1917 cERROR(1, ("Connecting to DFS root not implemented yet"));
1918 rc = -EINVAL;
1919 goto out;
1920 } else /* which servers DFS root would we conect to */ {
1921 cERROR(1,
1922 ("CIFS mount error: No UNC path (e.g. -o "
1923 "unc=//192.168.1.100/public) specified"));
1924 rc = -EINVAL;
1925 goto out;
1928 /* this is needed for ASCII cp to Unicode converts */
1929 if (volume_info.iocharset == NULL) {
1930 cifs_sb->local_nls = load_nls_default();
1931 /* load_nls_default can not return null */
1932 } else {
1933 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1934 if (cifs_sb->local_nls == NULL) {
1935 cERROR(1, ("CIFS mount error: iocharset %s not found",
1936 volume_info.iocharset));
1937 rc = -ELIBACC;
1938 goto out;
1942 if (address_type == AF_INET)
1943 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1944 NULL /* no ipv6 addr */,
1945 volume_info.username, &srvTcp);
1946 else if (address_type == AF_INET6) {
1947 cFYI(1, ("looking for ipv6 address"));
1948 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1949 &sin_server6.sin6_addr,
1950 volume_info.username, &srvTcp);
1951 } else {
1952 rc = -EINVAL;
1953 goto out;
1956 if (srvTcp) {
1957 cFYI(1, ("Existing tcp session with server found"));
1958 } else { /* create socket */
1959 if (volume_info.port)
1960 sin_server.sin_port = htons(volume_info.port);
1961 else
1962 sin_server.sin_port = 0;
1963 if (address_type == AF_INET6) {
1964 cFYI(1, ("attempting ipv6 connect"));
1965 /* BB should we allow ipv6 on port 139? */
1966 /* other OS never observed in Wild doing 139 with v6 */
1967 rc = ipv6_connect(&sin_server6, &csocket);
1968 } else
1969 rc = ipv4_connect(&sin_server, &csocket,
1970 volume_info.source_rfc1001_name,
1971 volume_info.target_rfc1001_name);
1972 if (rc < 0) {
1973 cERROR(1, ("Error connecting to IPv4 socket. "
1974 "Aborting operation"));
1975 if (csocket != NULL)
1976 sock_release(csocket);
1977 goto out;
1980 srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
1981 if (!srvTcp) {
1982 rc = -ENOMEM;
1983 sock_release(csocket);
1984 goto out;
1985 } else {
1986 memcpy(&srvTcp->addr.sockAddr, &sin_server,
1987 sizeof(struct sockaddr_in));
1988 atomic_set(&srvTcp->inFlight, 0);
1989 /* BB Add code for ipv6 case too */
1990 srvTcp->ssocket = csocket;
1991 srvTcp->protocolType = IPV4;
1992 srvTcp->hostname = extract_hostname(volume_info.UNC);
1993 if (IS_ERR(srvTcp->hostname)) {
1994 rc = PTR_ERR(srvTcp->hostname);
1995 sock_release(csocket);
1996 goto out;
1998 init_waitqueue_head(&srvTcp->response_q);
1999 init_waitqueue_head(&srvTcp->request_q);
2000 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
2001 /* at this point we are the only ones with the pointer
2002 to the struct since the kernel thread not created yet
2003 so no need to spinlock this init of tcpStatus */
2004 srvTcp->tcpStatus = CifsNew;
2005 init_MUTEX(&srvTcp->tcpSem);
2006 srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd");
2007 if (IS_ERR(srvTcp->tsk)) {
2008 rc = PTR_ERR(srvTcp->tsk);
2009 cERROR(1, ("error %d create cifsd thread", rc));
2010 srvTcp->tsk = NULL;
2011 sock_release(csocket);
2012 kfree(srvTcp->hostname);
2013 goto out;
2015 rc = 0;
2016 memcpy(srvTcp->workstation_RFC1001_name,
2017 volume_info.source_rfc1001_name, 16);
2018 memcpy(srvTcp->server_RFC1001_name,
2019 volume_info.target_rfc1001_name, 16);
2020 srvTcp->sequence_number = 0;
2024 if (existingCifsSes) {
2025 pSesInfo = existingCifsSes;
2026 cFYI(1, ("Existing smb sess found (status=%d)",
2027 pSesInfo->status));
2028 down(&pSesInfo->sesSem);
2029 if (pSesInfo->status == CifsNeedReconnect) {
2030 cFYI(1, ("Session needs reconnect"));
2031 rc = cifs_setup_session(xid, pSesInfo,
2032 cifs_sb->local_nls);
2034 up(&pSesInfo->sesSem);
2035 } else if (!rc) {
2036 cFYI(1, ("Existing smb sess not found"));
2037 pSesInfo = sesInfoAlloc();
2038 if (pSesInfo == NULL)
2039 rc = -ENOMEM;
2040 else {
2041 pSesInfo->server = srvTcp;
2042 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
2043 NIPQUAD(sin_server.sin_addr.s_addr));
2046 if (!rc) {
2047 /* volume_info.password freed at unmount */
2048 if (volume_info.password) {
2049 pSesInfo->password = volume_info.password;
2050 /* set to NULL to prevent freeing on exit */
2051 volume_info.password = NULL;
2053 if (volume_info.username)
2054 strncpy(pSesInfo->userName,
2055 volume_info.username,
2056 MAX_USERNAME_SIZE);
2057 if (volume_info.domainname) {
2058 int len = strlen(volume_info.domainname);
2059 pSesInfo->domainName =
2060 kmalloc(len + 1, GFP_KERNEL);
2061 if (pSesInfo->domainName)
2062 strcpy(pSesInfo->domainName,
2063 volume_info.domainname);
2065 pSesInfo->linux_uid = volume_info.linux_uid;
2066 pSesInfo->overrideSecFlg = volume_info.secFlg;
2067 down(&pSesInfo->sesSem);
2068 /* BB FIXME need to pass vol->secFlgs BB */
2069 rc = cifs_setup_session(xid, pSesInfo,
2070 cifs_sb->local_nls);
2071 up(&pSesInfo->sesSem);
2072 if (!rc)
2073 atomic_inc(&srvTcp->socketUseCount);
2077 /* search for existing tcon to this server share */
2078 if (!rc) {
2079 if (volume_info.rsize > CIFSMaxBufSize) {
2080 cERROR(1, ("rsize %d too large, using MaxBufSize",
2081 volume_info.rsize));
2082 cifs_sb->rsize = CIFSMaxBufSize;
2083 } else if ((volume_info.rsize) &&
2084 (volume_info.rsize <= CIFSMaxBufSize))
2085 cifs_sb->rsize = volume_info.rsize;
2086 else /* default */
2087 cifs_sb->rsize = CIFSMaxBufSize;
2089 if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
2090 cERROR(1, ("wsize %d too large, using 4096 instead",
2091 volume_info.wsize));
2092 cifs_sb->wsize = 4096;
2093 } else if (volume_info.wsize)
2094 cifs_sb->wsize = volume_info.wsize;
2095 else
2096 cifs_sb->wsize =
2097 min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
2098 127*1024);
2099 /* old default of CIFSMaxBufSize was too small now
2100 that SMB Write2 can send multiple pages in kvec.
2101 RFC1001 does not describe what happens when frame
2102 bigger than 128K is sent so use that as max in
2103 conjunction with 52K kvec constraint on arch with 4K
2104 page size */
2106 if (cifs_sb->rsize < 2048) {
2107 cifs_sb->rsize = 2048;
2108 /* Windows ME may prefer this */
2109 cFYI(1, ("readsize set to minimum: 2048"));
2111 /* calculate prepath */
2112 cifs_sb->prepath = volume_info.prepath;
2113 if (cifs_sb->prepath) {
2114 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
2115 /* we can not convert the / to \ in the path
2116 separators in the prefixpath yet because we do not
2117 know (until reset_cifs_unix_caps is called later)
2118 whether POSIX PATH CAP is available. We normalize
2119 the / to \ after reset_cifs_unix_caps is called */
2120 volume_info.prepath = NULL;
2121 } else
2122 cifs_sb->prepathlen = 0;
2123 cifs_sb->mnt_uid = volume_info.linux_uid;
2124 cifs_sb->mnt_gid = volume_info.linux_gid;
2125 cifs_sb->mnt_file_mode = volume_info.file_mode;
2126 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
2127 cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
2128 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
2130 if (volume_info.noperm)
2131 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
2132 if (volume_info.setuids)
2133 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
2134 if (volume_info.server_ino)
2135 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
2136 if (volume_info.remap)
2137 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
2138 if (volume_info.no_xattr)
2139 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
2140 if (volume_info.sfu_emul)
2141 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
2142 if (volume_info.nobrl)
2143 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
2144 if (volume_info.cifs_acl)
2145 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
2146 if (volume_info.override_uid)
2147 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
2148 if (volume_info.override_gid)
2149 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2150 if (volume_info.dynperm)
2151 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
2152 if (volume_info.direct_io) {
2153 cFYI(1, ("mounting share using direct i/o"));
2154 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
2157 if ((volume_info.cifs_acl) && (volume_info.dynperm))
2158 cERROR(1, ("mount option dynperm ignored if cifsacl "
2159 "mount option supported"));
2161 tcon =
2162 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
2163 volume_info.username);
2164 if (tcon) {
2165 cFYI(1, ("Found match on UNC path"));
2166 /* we can have only one retry value for a connection
2167 to a share so for resources mounted more than once
2168 to the same server share the last value passed in
2169 for the retry flag is used */
2170 tcon->retry = volume_info.retry;
2171 tcon->nocase = volume_info.nocase;
2172 if (tcon->seal != volume_info.seal)
2173 cERROR(1, ("transport encryption setting "
2174 "conflicts with existing tid"));
2175 } else {
2176 tcon = tconInfoAlloc();
2177 if (tcon == NULL)
2178 rc = -ENOMEM;
2179 else {
2180 /* check for null share name ie connecting to
2181 * dfs root */
2183 /* BB check if this works for exactly length
2184 * three strings */
2185 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
2186 && (strchr(volume_info.UNC + 3, '/') ==
2187 NULL)) {
2188 /* rc = connect_to_dfs_path(xid, pSesInfo,
2189 "", cifs_sb->local_nls,
2190 cifs_sb->mnt_cifs_flags &
2191 CIFS_MOUNT_MAP_SPECIAL_CHR);*/
2192 cFYI(1, ("DFS root not supported"));
2193 rc = -ENODEV;
2194 goto out;
2195 } else {
2196 /* BB Do we need to wrap sesSem around
2197 * this TCon call and Unix SetFS as
2198 * we do on SessSetup and reconnect? */
2199 rc = CIFSTCon(xid, pSesInfo,
2200 volume_info.UNC,
2201 tcon, cifs_sb->local_nls);
2202 cFYI(1, ("CIFS Tcon rc = %d", rc));
2203 if (volume_info.nodfs) {
2204 tcon->Flags &=
2205 ~SMB_SHARE_IS_IN_DFS;
2206 cFYI(1, ("DFS disabled (%d)",
2207 tcon->Flags));
2210 if (!rc) {
2211 atomic_inc(&pSesInfo->inUse);
2212 tcon->retry = volume_info.retry;
2213 tcon->nocase = volume_info.nocase;
2214 tcon->seal = volume_info.seal;
2219 if (pSesInfo) {
2220 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
2221 sb->s_maxbytes = (u64) 1 << 63;
2222 } else
2223 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
2226 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
2227 sb->s_time_gran = 100;
2229 /* on error free sesinfo and tcon struct if needed */
2230 if (rc) {
2231 /* if session setup failed, use count is zero but
2232 we still need to free cifsd thread */
2233 if (atomic_read(&srvTcp->socketUseCount) == 0) {
2234 spin_lock(&GlobalMid_Lock);
2235 srvTcp->tcpStatus = CifsExiting;
2236 spin_unlock(&GlobalMid_Lock);
2237 if (srvTcp->tsk) {
2238 /* If we could verify that kthread_stop would
2239 always wake up processes blocked in
2240 tcp in recv_mesg then we could remove the
2241 send_sig call */
2242 force_sig(SIGKILL, srvTcp->tsk);
2243 kthread_stop(srvTcp->tsk);
2246 /* If find_unc succeeded then rc == 0 so we can not end */
2247 if (tcon) /* up accidently freeing someone elses tcon struct */
2248 tconInfoFree(tcon);
2249 if (existingCifsSes == NULL) {
2250 if (pSesInfo) {
2251 if ((pSesInfo->server) &&
2252 (pSesInfo->status == CifsGood)) {
2253 int temp_rc;
2254 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
2255 /* if the socketUseCount is now zero */
2256 if ((temp_rc == -ESHUTDOWN) &&
2257 (pSesInfo->server) &&
2258 (pSesInfo->server->tsk)) {
2259 force_sig(SIGKILL,
2260 pSesInfo->server->tsk);
2261 kthread_stop(pSesInfo->server->tsk);
2263 } else {
2264 cFYI(1, ("No session or bad tcon"));
2265 if ((pSesInfo->server) &&
2266 (pSesInfo->server->tsk)) {
2267 force_sig(SIGKILL,
2268 pSesInfo->server->tsk);
2269 kthread_stop(pSesInfo->server->tsk);
2272 sesInfoFree(pSesInfo);
2273 /* pSesInfo = NULL; */
2276 } else {
2277 atomic_inc(&tcon->useCount);
2278 cifs_sb->tcon = tcon;
2279 tcon->ses = pSesInfo;
2281 /* do not care if following two calls succeed - informational */
2282 if (!tcon->ipc) {
2283 CIFSSMBQFSDeviceInfo(xid, tcon);
2284 CIFSSMBQFSAttributeInfo(xid, tcon);
2287 /* tell server which Unix caps we support */
2288 if (tcon->ses->capabilities & CAP_UNIX)
2289 /* reset of caps checks mount to see if unix extensions
2290 disabled for just this mount */
2291 reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
2292 else
2293 tcon->unix_ext = 0; /* server does not support them */
2295 /* convert forward to back slashes in prepath here if needed */
2296 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
2297 convert_delimiter(cifs_sb->prepath,
2298 CIFS_DIR_SEP(cifs_sb));
2300 if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
2301 cifs_sb->rsize = 1024 * 127;
2302 cFYI(DBG2,
2303 ("no very large read support, rsize now 127K"));
2305 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
2306 cifs_sb->wsize = min(cifs_sb->wsize,
2307 (tcon->ses->server->maxBuf -
2308 MAX_CIFS_HDR_SIZE));
2309 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
2310 cifs_sb->rsize = min(cifs_sb->rsize,
2311 (tcon->ses->server->maxBuf -
2312 MAX_CIFS_HDR_SIZE));
2315 /* volume_info.password is freed above when existing session found
2316 (in which case it is not needed anymore) but when new sesion is created
2317 the password ptr is put in the new session structure (in which case the
2318 password will be freed at unmount time) */
2319 out:
2320 /* zero out password before freeing */
2321 if (volume_info.password != NULL) {
2322 memset(volume_info.password, 0, strlen(volume_info.password));
2323 kfree(volume_info.password);
2325 kfree(volume_info.UNC);
2326 kfree(volume_info.prepath);
2327 FreeXid(xid);
2328 return rc;
2331 static int
2332 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2333 char session_key[CIFS_SESS_KEY_SIZE],
2334 const struct nls_table *nls_codepage)
2336 struct smb_hdr *smb_buffer;
2337 struct smb_hdr *smb_buffer_response;
2338 SESSION_SETUP_ANDX *pSMB;
2339 SESSION_SETUP_ANDX *pSMBr;
2340 char *bcc_ptr;
2341 char *user;
2342 char *domain;
2343 int rc = 0;
2344 int remaining_words = 0;
2345 int bytes_returned = 0;
2346 int len;
2347 __u32 capabilities;
2348 __u16 count;
2350 cFYI(1, ("In sesssetup"));
2351 if (ses == NULL)
2352 return -EINVAL;
2353 user = ses->userName;
2354 domain = ses->domainName;
2355 smb_buffer = cifs_buf_get();
2357 if (smb_buffer == NULL)
2358 return -ENOMEM;
2360 smb_buffer_response = smb_buffer;
2361 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2363 /* send SMBsessionSetup here */
2364 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2365 NULL /* no tCon exists yet */ , 13 /* wct */ );
2367 smb_buffer->Mid = GetNextMid(ses->server);
2368 pSMB->req_no_secext.AndXCommand = 0xFF;
2369 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2370 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2372 if (ses->server->secMode &
2373 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2374 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2376 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2377 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
2378 if (ses->capabilities & CAP_UNICODE) {
2379 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2380 capabilities |= CAP_UNICODE;
2382 if (ses->capabilities & CAP_STATUS32) {
2383 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2384 capabilities |= CAP_STATUS32;
2386 if (ses->capabilities & CAP_DFS) {
2387 smb_buffer->Flags2 |= SMBFLG2_DFS;
2388 capabilities |= CAP_DFS;
2390 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2392 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2393 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2395 pSMB->req_no_secext.CaseSensitivePasswordLength =
2396 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2397 bcc_ptr = pByteArea(smb_buffer);
2398 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2399 bcc_ptr += CIFS_SESS_KEY_SIZE;
2400 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2401 bcc_ptr += CIFS_SESS_KEY_SIZE;
2403 if (ses->capabilities & CAP_UNICODE) {
2404 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
2405 *bcc_ptr = 0;
2406 bcc_ptr++;
2408 if (user == NULL)
2409 bytes_returned = 0; /* skip null user */
2410 else
2411 bytes_returned =
2412 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
2413 nls_codepage);
2414 /* convert number of 16 bit words to bytes */
2415 bcc_ptr += 2 * bytes_returned;
2416 bcc_ptr += 2; /* trailing null */
2417 if (domain == NULL)
2418 bytes_returned =
2419 cifs_strtoUCS((__le16 *) bcc_ptr,
2420 "CIFS_LINUX_DOM", 32, nls_codepage);
2421 else
2422 bytes_returned =
2423 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2424 nls_codepage);
2425 bcc_ptr += 2 * bytes_returned;
2426 bcc_ptr += 2;
2427 bytes_returned =
2428 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2429 32, nls_codepage);
2430 bcc_ptr += 2 * bytes_returned;
2431 bytes_returned =
2432 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release,
2433 32, nls_codepage);
2434 bcc_ptr += 2 * bytes_returned;
2435 bcc_ptr += 2;
2436 bytes_returned =
2437 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2438 64, nls_codepage);
2439 bcc_ptr += 2 * bytes_returned;
2440 bcc_ptr += 2;
2441 } else {
2442 if (user != NULL) {
2443 strncpy(bcc_ptr, user, 200);
2444 bcc_ptr += strnlen(user, 200);
2446 *bcc_ptr = 0;
2447 bcc_ptr++;
2448 if (domain == NULL) {
2449 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2450 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2451 } else {
2452 strncpy(bcc_ptr, domain, 64);
2453 bcc_ptr += strnlen(domain, 64);
2454 *bcc_ptr = 0;
2455 bcc_ptr++;
2457 strcpy(bcc_ptr, "Linux version ");
2458 bcc_ptr += strlen("Linux version ");
2459 strcpy(bcc_ptr, utsname()->release);
2460 bcc_ptr += strlen(utsname()->release) + 1;
2461 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2462 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2464 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2465 smb_buffer->smb_buf_length += count;
2466 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2468 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2469 &bytes_returned, CIFS_LONG_OP);
2470 if (rc) {
2471 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2472 } else if ((smb_buffer_response->WordCount == 3)
2473 || (smb_buffer_response->WordCount == 4)) {
2474 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2475 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2476 if (action & GUEST_LOGIN)
2477 cFYI(1, (" Guest login")); /* BB mark SesInfo struct? */
2478 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format
2479 (little endian) */
2480 cFYI(1, ("UID = %d ", ses->Suid));
2481 /* response can have either 3 or 4 word count - Samba sends 3 */
2482 bcc_ptr = pByteArea(smb_buffer_response);
2483 if ((pSMBr->resp.hdr.WordCount == 3)
2484 || ((pSMBr->resp.hdr.WordCount == 4)
2485 && (blob_len < pSMBr->resp.ByteCount))) {
2486 if (pSMBr->resp.hdr.WordCount == 4)
2487 bcc_ptr += blob_len;
2489 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2490 if ((long) (bcc_ptr) % 2) {
2491 remaining_words =
2492 (BCC(smb_buffer_response) - 1) / 2;
2493 /* Unicode strings must be word
2494 aligned */
2495 bcc_ptr++;
2496 } else {
2497 remaining_words =
2498 BCC(smb_buffer_response) / 2;
2500 len =
2501 UniStrnlen((wchar_t *) bcc_ptr,
2502 remaining_words - 1);
2503 /* We look for obvious messed up bcc or strings in response so we do not go off
2504 the end since (at least) WIN2K and Windows XP have a major bug in not null
2505 terminating last Unicode string in response */
2506 if (ses->serverOS)
2507 kfree(ses->serverOS);
2508 ses->serverOS = kzalloc(2 * (len + 1),
2509 GFP_KERNEL);
2510 if (ses->serverOS == NULL)
2511 goto sesssetup_nomem;
2512 cifs_strfromUCS_le(ses->serverOS,
2513 (__le16 *)bcc_ptr,
2514 len, nls_codepage);
2515 bcc_ptr += 2 * (len + 1);
2516 remaining_words -= len + 1;
2517 ses->serverOS[2 * len] = 0;
2518 ses->serverOS[1 + (2 * len)] = 0;
2519 if (remaining_words > 0) {
2520 len = UniStrnlen((wchar_t *)bcc_ptr,
2521 remaining_words-1);
2522 kfree(ses->serverNOS);
2523 ses->serverNOS = kzalloc(2 * (len + 1),
2524 GFP_KERNEL);
2525 if (ses->serverNOS == NULL)
2526 goto sesssetup_nomem;
2527 cifs_strfromUCS_le(ses->serverNOS,
2528 (__le16 *)bcc_ptr,
2529 len, nls_codepage);
2530 bcc_ptr += 2 * (len + 1);
2531 ses->serverNOS[2 * len] = 0;
2532 ses->serverNOS[1 + (2 * len)] = 0;
2533 if (strncmp(ses->serverNOS,
2534 "NT LAN Manager 4", 16) == 0) {
2535 cFYI(1, ("NT4 server"));
2536 ses->flags |= CIFS_SES_NT4;
2538 remaining_words -= len + 1;
2539 if (remaining_words > 0) {
2540 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2541 /* last string is not always null terminated
2542 (for e.g. for Windows XP & 2000) */
2543 if (ses->serverDomain)
2544 kfree(ses->serverDomain);
2545 ses->serverDomain =
2546 kzalloc(2*(len+1),
2547 GFP_KERNEL);
2548 if (ses->serverDomain == NULL)
2549 goto sesssetup_nomem;
2550 cifs_strfromUCS_le(ses->serverDomain,
2551 (__le16 *)bcc_ptr,
2552 len, nls_codepage);
2553 bcc_ptr += 2 * (len + 1);
2554 ses->serverDomain[2*len] = 0;
2555 ses->serverDomain[1+(2*len)] = 0;
2556 } else { /* else no more room so create
2557 dummy domain string */
2558 if (ses->serverDomain)
2559 kfree(ses->serverDomain);
2560 ses->serverDomain =
2561 kzalloc(2, GFP_KERNEL);
2563 } else { /* no room so create dummy domain
2564 and NOS string */
2566 /* if these kcallocs fail not much we
2567 can do, but better to not fail the
2568 sesssetup itself */
2569 kfree(ses->serverDomain);
2570 ses->serverDomain =
2571 kzalloc(2, GFP_KERNEL);
2572 kfree(ses->serverNOS);
2573 ses->serverNOS =
2574 kzalloc(2, GFP_KERNEL);
2576 } else { /* ASCII */
2577 len = strnlen(bcc_ptr, 1024);
2578 if (((long) bcc_ptr + len) - (long)
2579 pByteArea(smb_buffer_response)
2580 <= BCC(smb_buffer_response)) {
2581 kfree(ses->serverOS);
2582 ses->serverOS = kzalloc(len + 1,
2583 GFP_KERNEL);
2584 if (ses->serverOS == NULL)
2585 goto sesssetup_nomem;
2586 strncpy(ses->serverOS, bcc_ptr, len);
2588 bcc_ptr += len;
2589 /* null terminate the string */
2590 bcc_ptr[0] = 0;
2591 bcc_ptr++;
2593 len = strnlen(bcc_ptr, 1024);
2594 kfree(ses->serverNOS);
2595 ses->serverNOS = kzalloc(len + 1,
2596 GFP_KERNEL);
2597 if (ses->serverNOS == NULL)
2598 goto sesssetup_nomem;
2599 strncpy(ses->serverNOS, bcc_ptr, len);
2600 bcc_ptr += len;
2601 bcc_ptr[0] = 0;
2602 bcc_ptr++;
2604 len = strnlen(bcc_ptr, 1024);
2605 if (ses->serverDomain)
2606 kfree(ses->serverDomain);
2607 ses->serverDomain = kzalloc(len + 1,
2608 GFP_KERNEL);
2609 if (ses->serverDomain == NULL)
2610 goto sesssetup_nomem;
2611 strncpy(ses->serverDomain, bcc_ptr,
2612 len);
2613 bcc_ptr += len;
2614 bcc_ptr[0] = 0;
2615 bcc_ptr++;
2616 } else
2617 cFYI(1,
2618 ("Variable field of length %d "
2619 "extends beyond end of smb ",
2620 len));
2622 } else {
2623 cERROR(1,
2624 (" Security Blob Length extends beyond "
2625 "end of SMB"));
2627 } else {
2628 cERROR(1,
2629 (" Invalid Word count %d: ",
2630 smb_buffer_response->WordCount));
2631 rc = -EIO;
2633 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2634 since that could make reconnection harder, and
2635 reconnection might be needed to free memory */
2636 cifs_buf_release(smb_buffer);
2638 return rc;
2641 static int
2642 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2643 struct cifsSesInfo *ses, bool *pNTLMv2_flag,
2644 const struct nls_table *nls_codepage)
2646 struct smb_hdr *smb_buffer;
2647 struct smb_hdr *smb_buffer_response;
2648 SESSION_SETUP_ANDX *pSMB;
2649 SESSION_SETUP_ANDX *pSMBr;
2650 char *bcc_ptr;
2651 char *domain;
2652 int rc = 0;
2653 int remaining_words = 0;
2654 int bytes_returned = 0;
2655 int len;
2656 int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
2657 PNEGOTIATE_MESSAGE SecurityBlob;
2658 PCHALLENGE_MESSAGE SecurityBlob2;
2659 __u32 negotiate_flags, capabilities;
2660 __u16 count;
2662 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
2663 if (ses == NULL)
2664 return -EINVAL;
2665 domain = ses->domainName;
2666 *pNTLMv2_flag = false;
2667 smb_buffer = cifs_buf_get();
2668 if (smb_buffer == NULL) {
2669 return -ENOMEM;
2671 smb_buffer_response = smb_buffer;
2672 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2673 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2675 /* send SMBsessionSetup here */
2676 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2677 NULL /* no tCon exists yet */ , 12 /* wct */ );
2679 smb_buffer->Mid = GetNextMid(ses->server);
2680 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2681 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2683 pSMB->req.AndXCommand = 0xFF;
2684 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2685 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2687 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2688 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2690 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2691 CAP_EXTENDED_SECURITY;
2692 if (ses->capabilities & CAP_UNICODE) {
2693 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2694 capabilities |= CAP_UNICODE;
2696 if (ses->capabilities & CAP_STATUS32) {
2697 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2698 capabilities |= CAP_STATUS32;
2700 if (ses->capabilities & CAP_DFS) {
2701 smb_buffer->Flags2 |= SMBFLG2_DFS;
2702 capabilities |= CAP_DFS;
2704 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2706 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2707 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2708 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2709 SecurityBlob->MessageType = NtLmNegotiate;
2710 negotiate_flags =
2711 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2712 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2713 NTLMSSP_NEGOTIATE_56 |
2714 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2715 if (sign_CIFS_PDUs)
2716 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2717 /* if (ntlmv2_support)
2718 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2719 /* setup pointers to domain name and workstation name */
2720 bcc_ptr += SecurityBlobLength;
2722 SecurityBlob->WorkstationName.Buffer = 0;
2723 SecurityBlob->WorkstationName.Length = 0;
2724 SecurityBlob->WorkstationName.MaximumLength = 0;
2726 /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2727 along with username on auth request (ie the response to challenge) */
2728 SecurityBlob->DomainName.Buffer = 0;
2729 SecurityBlob->DomainName.Length = 0;
2730 SecurityBlob->DomainName.MaximumLength = 0;
2731 if (ses->capabilities & CAP_UNICODE) {
2732 if ((long) bcc_ptr % 2) {
2733 *bcc_ptr = 0;
2734 bcc_ptr++;
2737 bytes_returned =
2738 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2739 32, nls_codepage);
2740 bcc_ptr += 2 * bytes_returned;
2741 bytes_returned =
2742 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
2743 nls_codepage);
2744 bcc_ptr += 2 * bytes_returned;
2745 bcc_ptr += 2; /* null terminate Linux version */
2746 bytes_returned =
2747 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2748 64, nls_codepage);
2749 bcc_ptr += 2 * bytes_returned;
2750 *(bcc_ptr + 1) = 0;
2751 *(bcc_ptr + 2) = 0;
2752 bcc_ptr += 2; /* null terminate network opsys string */
2753 *(bcc_ptr + 1) = 0;
2754 *(bcc_ptr + 2) = 0;
2755 bcc_ptr += 2; /* null domain */
2756 } else { /* ASCII */
2757 strcpy(bcc_ptr, "Linux version ");
2758 bcc_ptr += strlen("Linux version ");
2759 strcpy(bcc_ptr, utsname()->release);
2760 bcc_ptr += strlen(utsname()->release) + 1;
2761 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2762 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2763 bcc_ptr++; /* empty domain field */
2764 *bcc_ptr = 0;
2766 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2767 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2768 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2769 smb_buffer->smb_buf_length += count;
2770 pSMB->req.ByteCount = cpu_to_le16(count);
2772 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2773 &bytes_returned, CIFS_LONG_OP);
2775 if (smb_buffer_response->Status.CifsError ==
2776 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2777 rc = 0;
2779 if (rc) {
2780 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2781 } else if ((smb_buffer_response->WordCount == 3)
2782 || (smb_buffer_response->WordCount == 4)) {
2783 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2784 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2786 if (action & GUEST_LOGIN)
2787 cFYI(1, (" Guest login"));
2788 /* Do we want to set anything in SesInfo struct when guest login? */
2790 bcc_ptr = pByteArea(smb_buffer_response);
2791 /* response can have either 3 or 4 word count - Samba sends 3 */
2793 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2794 if (SecurityBlob2->MessageType != NtLmChallenge) {
2795 cFYI(1,
2796 ("Unexpected NTLMSSP message type received %d",
2797 SecurityBlob2->MessageType));
2798 } else if (ses) {
2799 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2800 cFYI(1, ("UID = %d", ses->Suid));
2801 if ((pSMBr->resp.hdr.WordCount == 3)
2802 || ((pSMBr->resp.hdr.WordCount == 4)
2803 && (blob_len <
2804 pSMBr->resp.ByteCount))) {
2806 if (pSMBr->resp.hdr.WordCount == 4) {
2807 bcc_ptr += blob_len;
2808 cFYI(1, ("Security Blob Length %d",
2809 blob_len));
2812 cFYI(1, ("NTLMSSP Challenge rcvd"));
2814 memcpy(ses->server->cryptKey,
2815 SecurityBlob2->Challenge,
2816 CIFS_CRYPTO_KEY_SIZE);
2817 if (SecurityBlob2->NegotiateFlags &
2818 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2819 *pNTLMv2_flag = true;
2821 if ((SecurityBlob2->NegotiateFlags &
2822 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2823 || (sign_CIFS_PDUs > 1))
2824 ses->server->secMode |=
2825 SECMODE_SIGN_REQUIRED;
2826 if ((SecurityBlob2->NegotiateFlags &
2827 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2828 ses->server->secMode |=
2829 SECMODE_SIGN_ENABLED;
2831 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2832 if ((long) (bcc_ptr) % 2) {
2833 remaining_words =
2834 (BCC(smb_buffer_response)
2835 - 1) / 2;
2836 /* Must word align unicode strings */
2837 bcc_ptr++;
2838 } else {
2839 remaining_words =
2841 (smb_buffer_response) / 2;
2843 len =
2844 UniStrnlen((wchar_t *) bcc_ptr,
2845 remaining_words - 1);
2846 /* We look for obvious messed up bcc or strings in response so we do not go off
2847 the end since (at least) WIN2K and Windows XP have a major bug in not null
2848 terminating last Unicode string in response */
2849 if (ses->serverOS)
2850 kfree(ses->serverOS);
2851 ses->serverOS =
2852 kzalloc(2 * (len + 1), GFP_KERNEL);
2853 cifs_strfromUCS_le(ses->serverOS,
2854 (__le16 *)
2855 bcc_ptr, len,
2856 nls_codepage);
2857 bcc_ptr += 2 * (len + 1);
2858 remaining_words -= len + 1;
2859 ses->serverOS[2 * len] = 0;
2860 ses->serverOS[1 + (2 * len)] = 0;
2861 if (remaining_words > 0) {
2862 len = UniStrnlen((wchar_t *)
2863 bcc_ptr,
2864 remaining_words
2865 - 1);
2866 kfree(ses->serverNOS);
2867 ses->serverNOS =
2868 kzalloc(2 * (len + 1),
2869 GFP_KERNEL);
2870 cifs_strfromUCS_le(ses->
2871 serverNOS,
2872 (__le16 *)
2873 bcc_ptr,
2874 len,
2875 nls_codepage);
2876 bcc_ptr += 2 * (len + 1);
2877 ses->serverNOS[2 * len] = 0;
2878 ses->serverNOS[1 +
2879 (2 * len)] = 0;
2880 remaining_words -= len + 1;
2881 if (remaining_words > 0) {
2882 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2883 /* last string not always null terminated
2884 (for e.g. for Windows XP & 2000) */
2885 kfree(ses->serverDomain);
2886 ses->serverDomain =
2887 kzalloc(2 *
2888 (len +
2890 GFP_KERNEL);
2891 cifs_strfromUCS_le
2892 (ses->serverDomain,
2893 (__le16 *)bcc_ptr,
2894 len, nls_codepage);
2895 bcc_ptr +=
2896 2 * (len + 1);
2897 ses->serverDomain[2*len]
2898 = 0;
2899 ses->serverDomain
2900 [1 + (2 * len)]
2901 = 0;
2902 } /* else no more room so create dummy domain string */
2903 else {
2904 kfree(ses->serverDomain);
2905 ses->serverDomain =
2906 kzalloc(2,
2907 GFP_KERNEL);
2909 } else { /* no room so create dummy domain and NOS string */
2910 kfree(ses->serverDomain);
2911 ses->serverDomain =
2912 kzalloc(2, GFP_KERNEL);
2913 kfree(ses->serverNOS);
2914 ses->serverNOS =
2915 kzalloc(2, GFP_KERNEL);
2917 } else { /* ASCII */
2918 len = strnlen(bcc_ptr, 1024);
2919 if (((long) bcc_ptr + len) - (long)
2920 pByteArea(smb_buffer_response)
2921 <= BCC(smb_buffer_response)) {
2922 if (ses->serverOS)
2923 kfree(ses->serverOS);
2924 ses->serverOS =
2925 kzalloc(len + 1,
2926 GFP_KERNEL);
2927 strncpy(ses->serverOS,
2928 bcc_ptr, len);
2930 bcc_ptr += len;
2931 bcc_ptr[0] = 0; /* null terminate string */
2932 bcc_ptr++;
2934 len = strnlen(bcc_ptr, 1024);
2935 kfree(ses->serverNOS);
2936 ses->serverNOS =
2937 kzalloc(len + 1,
2938 GFP_KERNEL);
2939 strncpy(ses->serverNOS, bcc_ptr, len);
2940 bcc_ptr += len;
2941 bcc_ptr[0] = 0;
2942 bcc_ptr++;
2944 len = strnlen(bcc_ptr, 1024);
2945 kfree(ses->serverDomain);
2946 ses->serverDomain =
2947 kzalloc(len + 1,
2948 GFP_KERNEL);
2949 strncpy(ses->serverDomain,
2950 bcc_ptr, len);
2951 bcc_ptr += len;
2952 bcc_ptr[0] = 0;
2953 bcc_ptr++;
2954 } else
2955 cFYI(1,
2956 ("field of length %d "
2957 "extends beyond end of smb",
2958 len));
2960 } else {
2961 cERROR(1, ("Security Blob Length extends beyond"
2962 " end of SMB"));
2964 } else {
2965 cERROR(1, ("No session structure passed in."));
2967 } else {
2968 cERROR(1,
2969 (" Invalid Word count %d:",
2970 smb_buffer_response->WordCount));
2971 rc = -EIO;
2974 cifs_buf_release(smb_buffer);
2976 return rc;
2978 static int
2979 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2980 char *ntlm_session_key, bool ntlmv2_flag,
2981 const struct nls_table *nls_codepage)
2983 struct smb_hdr *smb_buffer;
2984 struct smb_hdr *smb_buffer_response;
2985 SESSION_SETUP_ANDX *pSMB;
2986 SESSION_SETUP_ANDX *pSMBr;
2987 char *bcc_ptr;
2988 char *user;
2989 char *domain;
2990 int rc = 0;
2991 int remaining_words = 0;
2992 int bytes_returned = 0;
2993 int len;
2994 int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
2995 PAUTHENTICATE_MESSAGE SecurityBlob;
2996 __u32 negotiate_flags, capabilities;
2997 __u16 count;
2999 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
3000 if (ses == NULL)
3001 return -EINVAL;
3002 user = ses->userName;
3003 domain = ses->domainName;
3004 smb_buffer = cifs_buf_get();
3005 if (smb_buffer == NULL) {
3006 return -ENOMEM;
3008 smb_buffer_response = smb_buffer;
3009 pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
3010 pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
3012 /* send SMBsessionSetup here */
3013 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
3014 NULL /* no tCon exists yet */ , 12 /* wct */ );
3016 smb_buffer->Mid = GetNextMid(ses->server);
3017 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
3018 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
3019 pSMB->req.AndXCommand = 0xFF;
3020 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
3021 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
3023 pSMB->req.hdr.Uid = ses->Suid;
3025 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3026 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3028 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
3029 CAP_EXTENDED_SECURITY;
3030 if (ses->capabilities & CAP_UNICODE) {
3031 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3032 capabilities |= CAP_UNICODE;
3034 if (ses->capabilities & CAP_STATUS32) {
3035 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3036 capabilities |= CAP_STATUS32;
3038 if (ses->capabilities & CAP_DFS) {
3039 smb_buffer->Flags2 |= SMBFLG2_DFS;
3040 capabilities |= CAP_DFS;
3042 pSMB->req.Capabilities = cpu_to_le32(capabilities);
3044 bcc_ptr = (char *)&pSMB->req.SecurityBlob;
3045 SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
3046 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
3047 SecurityBlob->MessageType = NtLmAuthenticate;
3048 bcc_ptr += SecurityBlobLength;
3049 negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
3050 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
3051 0x80000000 | NTLMSSP_NEGOTIATE_128;
3052 if (sign_CIFS_PDUs)
3053 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
3054 if (ntlmv2_flag)
3055 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
3057 /* setup pointers to domain name and workstation name */
3059 SecurityBlob->WorkstationName.Buffer = 0;
3060 SecurityBlob->WorkstationName.Length = 0;
3061 SecurityBlob->WorkstationName.MaximumLength = 0;
3062 SecurityBlob->SessionKey.Length = 0;
3063 SecurityBlob->SessionKey.MaximumLength = 0;
3064 SecurityBlob->SessionKey.Buffer = 0;
3066 SecurityBlob->LmChallengeResponse.Length = 0;
3067 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
3068 SecurityBlob->LmChallengeResponse.Buffer = 0;
3070 SecurityBlob->NtChallengeResponse.Length =
3071 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3072 SecurityBlob->NtChallengeResponse.MaximumLength =
3073 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3074 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
3075 SecurityBlob->NtChallengeResponse.Buffer =
3076 cpu_to_le32(SecurityBlobLength);
3077 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
3078 bcc_ptr += CIFS_SESS_KEY_SIZE;
3080 if (ses->capabilities & CAP_UNICODE) {
3081 if (domain == NULL) {
3082 SecurityBlob->DomainName.Buffer = 0;
3083 SecurityBlob->DomainName.Length = 0;
3084 SecurityBlob->DomainName.MaximumLength = 0;
3085 } else {
3086 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
3087 nls_codepage);
3088 ln *= 2;
3089 SecurityBlob->DomainName.MaximumLength =
3090 cpu_to_le16(ln);
3091 SecurityBlob->DomainName.Buffer =
3092 cpu_to_le32(SecurityBlobLength);
3093 bcc_ptr += ln;
3094 SecurityBlobLength += ln;
3095 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3097 if (user == NULL) {
3098 SecurityBlob->UserName.Buffer = 0;
3099 SecurityBlob->UserName.Length = 0;
3100 SecurityBlob->UserName.MaximumLength = 0;
3101 } else {
3102 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
3103 nls_codepage);
3104 ln *= 2;
3105 SecurityBlob->UserName.MaximumLength =
3106 cpu_to_le16(ln);
3107 SecurityBlob->UserName.Buffer =
3108 cpu_to_le32(SecurityBlobLength);
3109 bcc_ptr += ln;
3110 SecurityBlobLength += ln;
3111 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3114 /* SecurityBlob->WorkstationName.Length =
3115 cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
3116 SecurityBlob->WorkstationName.Length *= 2;
3117 SecurityBlob->WorkstationName.MaximumLength =
3118 cpu_to_le16(SecurityBlob->WorkstationName.Length);
3119 SecurityBlob->WorkstationName.Buffer =
3120 cpu_to_le32(SecurityBlobLength);
3121 bcc_ptr += SecurityBlob->WorkstationName.Length;
3122 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
3123 SecurityBlob->WorkstationName.Length =
3124 cpu_to_le16(SecurityBlob->WorkstationName.Length); */
3126 if ((long) bcc_ptr % 2) {
3127 *bcc_ptr = 0;
3128 bcc_ptr++;
3130 bytes_returned =
3131 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
3132 32, nls_codepage);
3133 bcc_ptr += 2 * bytes_returned;
3134 bytes_returned =
3135 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
3136 nls_codepage);
3137 bcc_ptr += 2 * bytes_returned;
3138 bcc_ptr += 2; /* null term version string */
3139 bytes_returned =
3140 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
3141 64, nls_codepage);
3142 bcc_ptr += 2 * bytes_returned;
3143 *(bcc_ptr + 1) = 0;
3144 *(bcc_ptr + 2) = 0;
3145 bcc_ptr += 2; /* null terminate network opsys string */
3146 *(bcc_ptr + 1) = 0;
3147 *(bcc_ptr + 2) = 0;
3148 bcc_ptr += 2; /* null domain */
3149 } else { /* ASCII */
3150 if (domain == NULL) {
3151 SecurityBlob->DomainName.Buffer = 0;
3152 SecurityBlob->DomainName.Length = 0;
3153 SecurityBlob->DomainName.MaximumLength = 0;
3154 } else {
3155 __u16 ln;
3156 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3157 strncpy(bcc_ptr, domain, 63);
3158 ln = strnlen(domain, 64);
3159 SecurityBlob->DomainName.MaximumLength =
3160 cpu_to_le16(ln);
3161 SecurityBlob->DomainName.Buffer =
3162 cpu_to_le32(SecurityBlobLength);
3163 bcc_ptr += ln;
3164 SecurityBlobLength += ln;
3165 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3167 if (user == NULL) {
3168 SecurityBlob->UserName.Buffer = 0;
3169 SecurityBlob->UserName.Length = 0;
3170 SecurityBlob->UserName.MaximumLength = 0;
3171 } else {
3172 __u16 ln;
3173 strncpy(bcc_ptr, user, 63);
3174 ln = strnlen(user, 64);
3175 SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
3176 SecurityBlob->UserName.Buffer =
3177 cpu_to_le32(SecurityBlobLength);
3178 bcc_ptr += ln;
3179 SecurityBlobLength += ln;
3180 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3182 /* BB fill in our workstation name if known BB */
3184 strcpy(bcc_ptr, "Linux version ");
3185 bcc_ptr += strlen("Linux version ");
3186 strcpy(bcc_ptr, utsname()->release);
3187 bcc_ptr += strlen(utsname()->release) + 1;
3188 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3189 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3190 bcc_ptr++; /* null domain */
3191 *bcc_ptr = 0;
3193 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3194 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3195 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3196 smb_buffer->smb_buf_length += count;
3197 pSMB->req.ByteCount = cpu_to_le16(count);
3199 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3200 &bytes_returned, CIFS_LONG_OP);
3201 if (rc) {
3202 /* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
3203 } else if ((smb_buffer_response->WordCount == 3) ||
3204 (smb_buffer_response->WordCount == 4)) {
3205 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3206 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3207 if (action & GUEST_LOGIN)
3208 cFYI(1, (" Guest login")); /* BB Should we set anything
3209 in SesInfo struct ? */
3210 /* if (SecurityBlob2->MessageType != NtLm??) {
3211 cFYI("Unexpected message type on auth response is %d"));
3212 } */
3214 if (ses) {
3215 cFYI(1,
3216 ("Check challenge UID %d vs auth response UID %d",
3217 ses->Suid, smb_buffer_response->Uid));
3218 /* UID left in wire format */
3219 ses->Suid = smb_buffer_response->Uid;
3220 bcc_ptr = pByteArea(smb_buffer_response);
3221 /* response can have either 3 or 4 word count - Samba sends 3 */
3222 if ((pSMBr->resp.hdr.WordCount == 3)
3223 || ((pSMBr->resp.hdr.WordCount == 4)
3224 && (blob_len <
3225 pSMBr->resp.ByteCount))) {
3226 if (pSMBr->resp.hdr.WordCount == 4) {
3227 bcc_ptr +=
3228 blob_len;
3229 cFYI(1,
3230 ("Security Blob Length %d ",
3231 blob_len));
3234 cFYI(1,
3235 ("NTLMSSP response to Authenticate "));
3237 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3238 if ((long) (bcc_ptr) % 2) {
3239 remaining_words =
3240 (BCC(smb_buffer_response)
3241 - 1) / 2;
3242 bcc_ptr++; /* Unicode strings must be word aligned */
3243 } else {
3244 remaining_words = BCC(smb_buffer_response) / 2;
3246 len = UniStrnlen((wchar_t *) bcc_ptr,
3247 remaining_words - 1);
3248 /* We look for obvious messed up bcc or strings in response so we do not go off
3249 the end since (at least) WIN2K and Windows XP have a major bug in not null
3250 terminating last Unicode string in response */
3251 if (ses->serverOS)
3252 kfree(ses->serverOS);
3253 ses->serverOS =
3254 kzalloc(2 * (len + 1), GFP_KERNEL);
3255 cifs_strfromUCS_le(ses->serverOS,
3256 (__le16 *)
3257 bcc_ptr, len,
3258 nls_codepage);
3259 bcc_ptr += 2 * (len + 1);
3260 remaining_words -= len + 1;
3261 ses->serverOS[2 * len] = 0;
3262 ses->serverOS[1 + (2 * len)] = 0;
3263 if (remaining_words > 0) {
3264 len = UniStrnlen((wchar_t *)
3265 bcc_ptr,
3266 remaining_words
3267 - 1);
3268 kfree(ses->serverNOS);
3269 ses->serverNOS =
3270 kzalloc(2 * (len + 1),
3271 GFP_KERNEL);
3272 cifs_strfromUCS_le(ses->
3273 serverNOS,
3274 (__le16 *)
3275 bcc_ptr,
3276 len,
3277 nls_codepage);
3278 bcc_ptr += 2 * (len + 1);
3279 ses->serverNOS[2 * len] = 0;
3280 ses->serverNOS[1+(2*len)] = 0;
3281 remaining_words -= len + 1;
3282 if (remaining_words > 0) {
3283 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3284 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3285 if (ses->serverDomain)
3286 kfree(ses->serverDomain);
3287 ses->serverDomain =
3288 kzalloc(2 *
3289 (len +
3291 GFP_KERNEL);
3292 cifs_strfromUCS_le
3293 (ses->
3294 serverDomain,
3295 (__le16 *)
3296 bcc_ptr, len,
3297 nls_codepage);
3298 bcc_ptr +=
3299 2 * (len + 1);
3300 ses->
3301 serverDomain[2
3302 * len]
3303 = 0;
3304 ses->
3305 serverDomain[1
3309 len)]
3310 = 0;
3311 } /* else no more room so create dummy domain string */
3312 else {
3313 if (ses->serverDomain)
3314 kfree(ses->serverDomain);
3315 ses->serverDomain = kzalloc(2,GFP_KERNEL);
3317 } else { /* no room so create dummy domain and NOS string */
3318 if (ses->serverDomain)
3319 kfree(ses->serverDomain);
3320 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3321 kfree(ses->serverNOS);
3322 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3324 } else { /* ASCII */
3325 len = strnlen(bcc_ptr, 1024);
3326 if (((long) bcc_ptr + len) -
3327 (long) pByteArea(smb_buffer_response)
3328 <= BCC(smb_buffer_response)) {
3329 if (ses->serverOS)
3330 kfree(ses->serverOS);
3331 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
3332 strncpy(ses->serverOS,bcc_ptr, len);
3334 bcc_ptr += len;
3335 bcc_ptr[0] = 0; /* null terminate the string */
3336 bcc_ptr++;
3338 len = strnlen(bcc_ptr, 1024);
3339 kfree(ses->serverNOS);
3340 ses->serverNOS = kzalloc(len+1,
3341 GFP_KERNEL);
3342 strncpy(ses->serverNOS,
3343 bcc_ptr, len);
3344 bcc_ptr += len;
3345 bcc_ptr[0] = 0;
3346 bcc_ptr++;
3348 len = strnlen(bcc_ptr, 1024);
3349 if (ses->serverDomain)
3350 kfree(ses->serverDomain);
3351 ses->serverDomain =
3352 kzalloc(len+1,
3353 GFP_KERNEL);
3354 strncpy(ses->serverDomain,
3355 bcc_ptr, len);
3356 bcc_ptr += len;
3357 bcc_ptr[0] = 0;
3358 bcc_ptr++;
3359 } else
3360 cFYI(1, ("field of length %d "
3361 "extends beyond end of smb ",
3362 len));
3364 } else {
3365 cERROR(1, ("Security Blob extends beyond end "
3366 "of SMB"));
3368 } else {
3369 cERROR(1, ("No session structure passed in."));
3371 } else {
3372 cERROR(1, ("Invalid Word count %d: ",
3373 smb_buffer_response->WordCount));
3374 rc = -EIO;
3377 cifs_buf_release(smb_buffer);
3379 return rc;
3383 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3384 const char *tree, struct cifsTconInfo *tcon,
3385 const struct nls_table *nls_codepage)
3387 struct smb_hdr *smb_buffer;
3388 struct smb_hdr *smb_buffer_response;
3389 TCONX_REQ *pSMB;
3390 TCONX_RSP *pSMBr;
3391 unsigned char *bcc_ptr;
3392 int rc = 0;
3393 int length;
3394 __u16 count;
3396 if (ses == NULL)
3397 return -EIO;
3399 smb_buffer = cifs_buf_get();
3400 if (smb_buffer == NULL) {
3401 return -ENOMEM;
3403 smb_buffer_response = smb_buffer;
3405 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3406 NULL /*no tid */ , 4 /*wct */ );
3408 smb_buffer->Mid = GetNextMid(ses->server);
3409 smb_buffer->Uid = ses->Suid;
3410 pSMB = (TCONX_REQ *) smb_buffer;
3411 pSMBr = (TCONX_RSP *) smb_buffer_response;
3413 pSMB->AndXCommand = 0xFF;
3414 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3415 bcc_ptr = &pSMB->Password[0];
3416 if ((ses->server->secMode) & SECMODE_USER) {
3417 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3418 *bcc_ptr = 0; /* password is null byte */
3419 bcc_ptr++; /* skip password */
3420 /* already aligned so no need to do it below */
3421 } else {
3422 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
3423 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3424 specified as required (when that support is added to
3425 the vfs in the future) as only NTLM or the much
3426 weaker LANMAN (which we do not send by default) is accepted
3427 by Samba (not sure whether other servers allow
3428 NTLMv2 password here) */
3429 #ifdef CONFIG_CIFS_WEAK_PW_HASH
3430 if ((extended_security & CIFSSEC_MAY_LANMAN) &&
3431 (ses->server->secType == LANMAN))
3432 calc_lanman_hash(ses, bcc_ptr);
3433 else
3434 #endif /* CIFS_WEAK_PW_HASH */
3435 SMBNTencrypt(ses->password,
3436 ses->server->cryptKey,
3437 bcc_ptr);
3439 bcc_ptr += CIFS_SESS_KEY_SIZE;
3440 if (ses->capabilities & CAP_UNICODE) {
3441 /* must align unicode strings */
3442 *bcc_ptr = 0; /* null byte password */
3443 bcc_ptr++;
3447 if (ses->server->secMode &
3448 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3449 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3451 if (ses->capabilities & CAP_STATUS32) {
3452 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3454 if (ses->capabilities & CAP_DFS) {
3455 smb_buffer->Flags2 |= SMBFLG2_DFS;
3457 if (ses->capabilities & CAP_UNICODE) {
3458 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3459 length =
3460 cifs_strtoUCS((__le16 *) bcc_ptr, tree,
3461 6 /* max utf8 char length in bytes */ *
3462 (/* server len*/ + 256 /* share len */), nls_codepage);
3463 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
3464 bcc_ptr += 2; /* skip trailing null */
3465 } else { /* ASCII */
3466 strcpy(bcc_ptr, tree);
3467 bcc_ptr += strlen(tree) + 1;
3469 strcpy(bcc_ptr, "?????");
3470 bcc_ptr += strlen("?????");
3471 bcc_ptr += 1;
3472 count = bcc_ptr - &pSMB->Password[0];
3473 pSMB->hdr.smb_buf_length += count;
3474 pSMB->ByteCount = cpu_to_le16(count);
3476 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
3477 CIFS_STD_OP);
3479 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3480 /* above now done in SendReceive */
3481 if ((rc == 0) && (tcon != NULL)) {
3482 tcon->tidStatus = CifsGood;
3483 tcon->tid = smb_buffer_response->Tid;
3484 bcc_ptr = pByteArea(smb_buffer_response);
3485 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3486 /* skip service field (NB: this field is always ASCII) */
3487 if (length == 3) {
3488 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3489 (bcc_ptr[2] == 'C')) {
3490 cFYI(1, ("IPC connection"));
3491 tcon->ipc = 1;
3493 } else if (length == 2) {
3494 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3495 /* the most common case */
3496 cFYI(1, ("disk share connection"));
3499 bcc_ptr += length + 1;
3500 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3501 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3502 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3503 if ((bcc_ptr + (2 * length)) -
3504 pByteArea(smb_buffer_response) <=
3505 BCC(smb_buffer_response)) {
3506 kfree(tcon->nativeFileSystem);
3507 tcon->nativeFileSystem =
3508 kzalloc(length + 2, GFP_KERNEL);
3509 if (tcon->nativeFileSystem)
3510 cifs_strfromUCS_le(
3511 tcon->nativeFileSystem,
3512 (__le16 *) bcc_ptr,
3513 length, nls_codepage);
3514 bcc_ptr += 2 * length;
3515 bcc_ptr[0] = 0; /* null terminate the string */
3516 bcc_ptr[1] = 0;
3517 bcc_ptr += 2;
3519 /* else do not bother copying these information fields*/
3520 } else {
3521 length = strnlen(bcc_ptr, 1024);
3522 if ((bcc_ptr + length) -
3523 pByteArea(smb_buffer_response) <=
3524 BCC(smb_buffer_response)) {
3525 kfree(tcon->nativeFileSystem);
3526 tcon->nativeFileSystem =
3527 kzalloc(length + 1, GFP_KERNEL);
3528 if (tcon->nativeFileSystem)
3529 strncpy(tcon->nativeFileSystem, bcc_ptr,
3530 length);
3532 /* else do not bother copying these information fields*/
3534 if ((smb_buffer_response->WordCount == 3) ||
3535 (smb_buffer_response->WordCount == 7))
3536 /* field is in same location */
3537 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3538 else
3539 tcon->Flags = 0;
3540 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3541 } else if ((rc == 0) && tcon == NULL) {
3542 /* all we need to save for IPC$ connection */
3543 ses->ipc_tid = smb_buffer_response->Tid;
3546 cifs_buf_release(smb_buffer);
3547 return rc;
3551 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3553 int rc = 0;
3554 int xid;
3555 struct cifsSesInfo *ses = NULL;
3556 struct task_struct *cifsd_task;
3557 char *tmp;
3559 xid = GetXid();
3561 if (cifs_sb->tcon) {
3562 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3563 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3564 if (rc == -EBUSY) {
3565 FreeXid(xid);
3566 return 0;
3568 DeleteTconOplockQEntries(cifs_sb->tcon);
3569 tconInfoFree(cifs_sb->tcon);
3570 if ((ses) && (ses->server)) {
3571 /* save off task so we do not refer to ses later */
3572 cifsd_task = ses->server->tsk;
3573 cFYI(1, ("About to do SMBLogoff "));
3574 rc = CIFSSMBLogoff(xid, ses);
3575 if (rc == -EBUSY) {
3576 FreeXid(xid);
3577 return 0;
3578 } else if (rc == -ESHUTDOWN) {
3579 cFYI(1, ("Waking up socket by sending signal"));
3580 if (cifsd_task) {
3581 force_sig(SIGKILL, cifsd_task);
3582 kthread_stop(cifsd_task);
3584 rc = 0;
3585 } /* else - we have an smb session
3586 left on this socket do not kill cifsd */
3587 } else
3588 cFYI(1, ("No session or bad tcon"));
3591 cifs_sb->tcon = NULL;
3592 tmp = cifs_sb->prepath;
3593 cifs_sb->prepathlen = 0;
3594 cifs_sb->prepath = NULL;
3595 kfree(tmp);
3596 if (ses)
3597 sesInfoFree(ses);
3599 FreeXid(xid);
3600 return rc;
3603 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3604 struct nls_table *nls_info)
3606 int rc = 0;
3607 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3608 bool ntlmv2_flag = false;
3609 int first_time = 0;
3610 struct TCP_Server_Info *server = pSesInfo->server;
3612 /* what if server changes its buffer size after dropping the session? */
3613 if (server->maxBuf == 0) /* no need to send on reconnect */ {
3614 rc = CIFSSMBNegotiate(xid, pSesInfo);
3615 if (rc == -EAGAIN) {
3616 /* retry only once on 1st time connection */
3617 rc = CIFSSMBNegotiate(xid, pSesInfo);
3618 if (rc == -EAGAIN)
3619 rc = -EHOSTDOWN;
3621 if (rc == 0) {
3622 spin_lock(&GlobalMid_Lock);
3623 if (server->tcpStatus != CifsExiting)
3624 server->tcpStatus = CifsGood;
3625 else
3626 rc = -EHOSTDOWN;
3627 spin_unlock(&GlobalMid_Lock);
3630 first_time = 1;
3633 if (rc)
3634 goto ss_err_exit;
3636 pSesInfo->flags = 0;
3637 pSesInfo->capabilities = server->capabilities;
3638 if (linuxExtEnabled == 0)
3639 pSesInfo->capabilities &= (~CAP_UNIX);
3640 /* pSesInfo->sequence_number = 0;*/
3641 cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
3642 server->secMode, server->capabilities, server->timeAdj));
3644 if (experimEnabled < 2)
3645 rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
3646 else if (extended_security
3647 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3648 && (server->secType == NTLMSSP)) {
3649 rc = -EOPNOTSUPP;
3650 } else if (extended_security
3651 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3652 && (server->secType == RawNTLMSSP)) {
3653 cFYI(1, ("NTLMSSP sesssetup"));
3654 rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag,
3655 nls_info);
3656 if (!rc) {
3657 if (ntlmv2_flag) {
3658 char *v2_response;
3659 cFYI(1, ("more secure NTLM ver2 hash"));
3660 if (CalcNTLMv2_partial_mac_key(pSesInfo,
3661 nls_info)) {
3662 rc = -ENOMEM;
3663 goto ss_err_exit;
3664 } else
3665 v2_response = kmalloc(16 + 64 /* blob*/,
3666 GFP_KERNEL);
3667 if (v2_response) {
3668 CalcNTLMv2_response(pSesInfo,
3669 v2_response);
3670 /* if (first_time)
3671 cifs_calculate_ntlmv2_mac_key */
3672 kfree(v2_response);
3673 /* BB Put dummy sig in SessSetup PDU? */
3674 } else {
3675 rc = -ENOMEM;
3676 goto ss_err_exit;
3679 } else {
3680 SMBNTencrypt(pSesInfo->password,
3681 server->cryptKey,
3682 ntlm_session_key);
3684 if (first_time)
3685 cifs_calculate_mac_key(
3686 &server->mac_signing_key,
3687 ntlm_session_key,
3688 pSesInfo->password);
3690 /* for better security the weaker lanman hash not sent
3691 in AuthSessSetup so we no longer calculate it */
3693 rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo,
3694 ntlm_session_key,
3695 ntlmv2_flag,
3696 nls_info);
3698 } else { /* old style NTLM 0.12 session setup */
3699 SMBNTencrypt(pSesInfo->password, server->cryptKey,
3700 ntlm_session_key);
3702 if (first_time)
3703 cifs_calculate_mac_key(&server->mac_signing_key,
3704 ntlm_session_key,
3705 pSesInfo->password);
3707 rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info);
3709 if (rc) {
3710 cERROR(1, ("Send error in SessSetup = %d", rc));
3711 } else {
3712 cFYI(1, ("CIFS Session Established successfully"));
3713 pSesInfo->status = CifsGood;
3716 ss_err_exit:
3717 return rc;