x86: fixup config space size of CPU functions for AMD family 11h
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / fs / cifs / connect.c
blobc7d341714586fdfc9086c381dc310fe81a371237
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; /* Do not request DFS, even if available */
94 bool local_lease:1; /* check leases only on local system, not remote */
95 bool noblocksnd:1;
96 bool noautotune:1;
97 unsigned int rsize;
98 unsigned int wsize;
99 unsigned int sockopt;
100 unsigned short int port;
101 char *prepath;
104 static int ipv4_connect(struct sockaddr_in *psin_server,
105 struct socket **csocket,
106 char *netb_name,
107 char *server_netb_name,
108 bool noblocksnd,
109 bool nosndbuf); /* ipv6 never set sndbuf size */
110 static int ipv6_connect(struct sockaddr_in6 *psin_server,
111 struct socket **csocket, bool noblocksnd);
115 * cifs tcp session reconnection
117 * mark tcp session as reconnecting so temporarily locked
118 * mark all smb sessions as reconnecting for tcp session
119 * reconnect tcp session
120 * wake up waiters on reconnection? - (not needed currently)
123 static int
124 cifs_reconnect(struct TCP_Server_Info *server)
126 int rc = 0;
127 struct list_head *tmp, *tmp2;
128 struct cifsSesInfo *ses;
129 struct cifsTconInfo *tcon;
130 struct mid_q_entry *mid_entry;
132 spin_lock(&GlobalMid_Lock);
133 if (server->tcpStatus == CifsExiting) {
134 /* the demux thread will exit normally
135 next time through the loop */
136 spin_unlock(&GlobalMid_Lock);
137 return rc;
138 } else
139 server->tcpStatus = CifsNeedReconnect;
140 spin_unlock(&GlobalMid_Lock);
141 server->maxBuf = 0;
143 cFYI(1, ("Reconnecting tcp session"));
145 /* before reconnecting the tcp session, mark the smb session (uid)
146 and the tid bad so they are not used until reconnected */
147 read_lock(&cifs_tcp_ses_lock);
148 list_for_each(tmp, &server->smb_ses_list) {
149 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
150 ses->need_reconnect = true;
151 ses->ipc_tid = 0;
152 list_for_each(tmp2, &ses->tcon_list) {
153 tcon = list_entry(tmp2, struct cifsTconInfo, tcon_list);
154 tcon->need_reconnect = true;
157 read_unlock(&cifs_tcp_ses_lock);
158 /* do not want to be sending data on a socket we are freeing */
159 down(&server->tcpSem);
160 if (server->ssocket) {
161 cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state,
162 server->ssocket->flags));
163 kernel_sock_shutdown(server->ssocket, SHUT_WR);
164 cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx",
165 server->ssocket->state,
166 server->ssocket->flags));
167 sock_release(server->ssocket);
168 server->ssocket = NULL;
171 spin_lock(&GlobalMid_Lock);
172 list_for_each(tmp, &server->pending_mid_q) {
173 mid_entry = list_entry(tmp, struct
174 mid_q_entry,
175 qhead);
176 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
177 /* Mark other intransit requests as needing
178 retry so we do not immediately mark the
179 session bad again (ie after we reconnect
180 below) as they timeout too */
181 mid_entry->midState = MID_RETRY_NEEDED;
184 spin_unlock(&GlobalMid_Lock);
185 up(&server->tcpSem);
187 while ((server->tcpStatus != CifsExiting) &&
188 (server->tcpStatus != CifsGood)) {
189 try_to_freeze();
190 if (server->addr.sockAddr6.sin6_family == AF_INET6) {
191 rc = ipv6_connect(&server->addr.sockAddr6,
192 &server->ssocket, server->noautotune);
193 } else {
194 rc = ipv4_connect(&server->addr.sockAddr,
195 &server->ssocket,
196 server->workstation_RFC1001_name,
197 server->server_RFC1001_name,
198 server->noblocksnd, server->noautotune);
200 if (rc) {
201 cFYI(1, ("reconnect error %d", rc));
202 msleep(3000);
203 } else {
204 atomic_inc(&tcpSesReconnectCount);
205 spin_lock(&GlobalMid_Lock);
206 if (server->tcpStatus != CifsExiting)
207 server->tcpStatus = CifsGood;
208 server->sequence_number = 0;
209 spin_unlock(&GlobalMid_Lock);
210 /* atomic_set(&server->inFlight,0);*/
211 wake_up(&server->response_q);
214 return rc;
218 return codes:
219 0 not a transact2, or all data present
220 >0 transact2 with that much data missing
221 -EINVAL = invalid transact2
224 static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize)
226 struct smb_t2_rsp *pSMBt;
227 int total_data_size;
228 int data_in_this_rsp;
229 int remaining;
231 if (pSMB->Command != SMB_COM_TRANSACTION2)
232 return 0;
234 /* check for plausible wct, bcc and t2 data and parm sizes */
235 /* check for parm and data offset going beyond end of smb */
236 if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
237 cFYI(1, ("invalid transact2 word count"));
238 return -EINVAL;
241 pSMBt = (struct smb_t2_rsp *)pSMB;
243 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
244 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
246 remaining = total_data_size - data_in_this_rsp;
248 if (remaining == 0)
249 return 0;
250 else if (remaining < 0) {
251 cFYI(1, ("total data %d smaller than data in frame %d",
252 total_data_size, data_in_this_rsp));
253 return -EINVAL;
254 } else {
255 cFYI(1, ("missing %d bytes from transact2, check next response",
256 remaining));
257 if (total_data_size > maxBufSize) {
258 cERROR(1, ("TotalDataSize %d is over maximum buffer %d",
259 total_data_size, maxBufSize));
260 return -EINVAL;
262 return remaining;
266 static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
268 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
269 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
270 int total_data_size;
271 int total_in_buf;
272 int remaining;
273 int total_in_buf2;
274 char *data_area_of_target;
275 char *data_area_of_buf2;
276 __u16 byte_count;
278 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
280 if (total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
281 cFYI(1, ("total data size of primary and secondary t2 differ"));
284 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
286 remaining = total_data_size - total_in_buf;
288 if (remaining < 0)
289 return -EINVAL;
291 if (remaining == 0) /* nothing to do, ignore */
292 return 0;
294 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
295 if (remaining < total_in_buf2) {
296 cFYI(1, ("transact2 2nd response contains too much data"));
299 /* find end of first SMB data area */
300 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
301 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
302 /* validate target area */
304 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
305 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
307 data_area_of_target += total_in_buf;
309 /* copy second buffer into end of first buffer */
310 memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
311 total_in_buf += total_in_buf2;
312 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
313 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
314 byte_count += total_in_buf2;
315 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
317 byte_count = pTargetSMB->smb_buf_length;
318 byte_count += total_in_buf2;
320 /* BB also add check that we are not beyond maximum buffer size */
322 pTargetSMB->smb_buf_length = byte_count;
324 if (remaining == total_in_buf2) {
325 cFYI(1, ("found the last secondary response"));
326 return 0; /* we are done */
327 } else /* more responses to go */
328 return 1;
332 static int
333 cifs_demultiplex_thread(struct TCP_Server_Info *server)
335 int length;
336 unsigned int pdu_length, total_read;
337 struct smb_hdr *smb_buffer = NULL;
338 struct smb_hdr *bigbuf = NULL;
339 struct smb_hdr *smallbuf = NULL;
340 struct msghdr smb_msg;
341 struct kvec iov;
342 struct socket *csocket = server->ssocket;
343 struct list_head *tmp;
344 struct cifsSesInfo *ses;
345 struct task_struct *task_to_wake = NULL;
346 struct mid_q_entry *mid_entry;
347 char temp;
348 bool isLargeBuf = false;
349 bool isMultiRsp;
350 int reconnect;
352 current->flags |= PF_MEMALLOC;
353 cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
355 length = atomic_inc_return(&tcpSesAllocCount);
356 if (length > 1)
357 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
358 GFP_KERNEL);
360 set_freezable();
361 while (server->tcpStatus != CifsExiting) {
362 if (try_to_freeze())
363 continue;
364 if (bigbuf == NULL) {
365 bigbuf = cifs_buf_get();
366 if (!bigbuf) {
367 cERROR(1, ("No memory for large SMB response"));
368 msleep(3000);
369 /* retry will check if exiting */
370 continue;
372 } else if (isLargeBuf) {
373 /* we are reusing a dirty large buf, clear its start */
374 memset(bigbuf, 0, sizeof(struct smb_hdr));
377 if (smallbuf == NULL) {
378 smallbuf = cifs_small_buf_get();
379 if (!smallbuf) {
380 cERROR(1, ("No memory for SMB response"));
381 msleep(1000);
382 /* retry will check if exiting */
383 continue;
385 /* beginning of smb buffer is cleared in our buf_get */
386 } else /* if existing small buf clear beginning */
387 memset(smallbuf, 0, sizeof(struct smb_hdr));
389 isLargeBuf = false;
390 isMultiRsp = false;
391 smb_buffer = smallbuf;
392 iov.iov_base = smb_buffer;
393 iov.iov_len = 4;
394 smb_msg.msg_control = NULL;
395 smb_msg.msg_controllen = 0;
396 pdu_length = 4; /* enough to get RFC1001 header */
397 incomplete_rcv:
398 length =
399 kernel_recvmsg(csocket, &smb_msg,
400 &iov, 1, pdu_length, 0 /* BB other flags? */);
402 if (server->tcpStatus == CifsExiting) {
403 break;
404 } else if (server->tcpStatus == CifsNeedReconnect) {
405 cFYI(1, ("Reconnect after server stopped responding"));
406 cifs_reconnect(server);
407 cFYI(1, ("call to reconnect done"));
408 csocket = server->ssocket;
409 continue;
410 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
411 msleep(1); /* minimum sleep to prevent looping
412 allowing socket to clear and app threads to set
413 tcpStatus CifsNeedReconnect if server hung */
414 if (pdu_length < 4) {
415 iov.iov_base = (4 - pdu_length) +
416 (char *)smb_buffer;
417 iov.iov_len = pdu_length;
418 smb_msg.msg_control = NULL;
419 smb_msg.msg_controllen = 0;
420 goto incomplete_rcv;
421 } else
422 continue;
423 } else if (length <= 0) {
424 if (server->tcpStatus == CifsNew) {
425 cFYI(1, ("tcp session abend after SMBnegprot"));
426 /* some servers kill the TCP session rather than
427 returning an SMB negprot error, in which
428 case reconnecting here is not going to help,
429 and so simply return error to mount */
430 break;
432 if (!try_to_freeze() && (length == -EINTR)) {
433 cFYI(1, ("cifsd thread killed"));
434 break;
436 cFYI(1, ("Reconnect after unexpected peek error %d",
437 length));
438 cifs_reconnect(server);
439 csocket = server->ssocket;
440 wake_up(&server->response_q);
441 continue;
442 } else if (length < pdu_length) {
443 cFYI(1, ("requested %d bytes but only got %d bytes",
444 pdu_length, length));
445 pdu_length -= length;
446 msleep(1);
447 goto incomplete_rcv;
450 /* The right amount was read from socket - 4 bytes */
451 /* so we can now interpret the length field */
453 /* the first byte big endian of the length field,
454 is actually not part of the length but the type
455 with the most common, zero, as regular data */
456 temp = *((char *) smb_buffer);
458 /* Note that FC 1001 length is big endian on the wire,
459 but we convert it here so it is always manipulated
460 as host byte order */
461 pdu_length = be32_to_cpu((__force __be32)smb_buffer->smb_buf_length);
462 smb_buffer->smb_buf_length = pdu_length;
464 cFYI(1, ("rfc1002 length 0x%x", pdu_length+4));
466 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
467 continue;
468 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
469 cFYI(1, ("Good RFC 1002 session rsp"));
470 continue;
471 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
472 /* we get this from Windows 98 instead of
473 an error on SMB negprot response */
474 cFYI(1, ("Negative RFC1002 Session Response Error 0x%x)",
475 pdu_length));
476 if (server->tcpStatus == CifsNew) {
477 /* if nack on negprot (rather than
478 ret of smb negprot error) reconnecting
479 not going to help, ret error to mount */
480 break;
481 } else {
482 /* give server a second to
483 clean up before reconnect attempt */
484 msleep(1000);
485 /* always try 445 first on reconnect
486 since we get NACK on some if we ever
487 connected to port 139 (the NACK is
488 since we do not begin with RFC1001
489 session initialize frame) */
490 server->addr.sockAddr.sin_port =
491 htons(CIFS_PORT);
492 cifs_reconnect(server);
493 csocket = server->ssocket;
494 wake_up(&server->response_q);
495 continue;
497 } else if (temp != (char) 0) {
498 cERROR(1, ("Unknown RFC 1002 frame"));
499 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
500 length);
501 cifs_reconnect(server);
502 csocket = server->ssocket;
503 continue;
506 /* else we have an SMB response */
507 if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
508 (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
509 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
510 length, pdu_length+4));
511 cifs_reconnect(server);
512 csocket = server->ssocket;
513 wake_up(&server->response_q);
514 continue;
517 /* else length ok */
518 reconnect = 0;
520 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
521 isLargeBuf = true;
522 memcpy(bigbuf, smallbuf, 4);
523 smb_buffer = bigbuf;
525 length = 0;
526 iov.iov_base = 4 + (char *)smb_buffer;
527 iov.iov_len = pdu_length;
528 for (total_read = 0; total_read < pdu_length;
529 total_read += length) {
530 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
531 pdu_length - total_read, 0);
532 if ((server->tcpStatus == CifsExiting) ||
533 (length == -EINTR)) {
534 /* then will exit */
535 reconnect = 2;
536 break;
537 } else if (server->tcpStatus == CifsNeedReconnect) {
538 cifs_reconnect(server);
539 csocket = server->ssocket;
540 /* Reconnect wakes up rspns q */
541 /* Now we will reread sock */
542 reconnect = 1;
543 break;
544 } else if ((length == -ERESTARTSYS) ||
545 (length == -EAGAIN)) {
546 msleep(1); /* minimum sleep to prevent looping,
547 allowing socket to clear and app
548 threads to set tcpStatus
549 CifsNeedReconnect if server hung*/
550 length = 0;
551 continue;
552 } else if (length <= 0) {
553 cERROR(1, ("Received no data, expecting %d",
554 pdu_length - total_read));
555 cifs_reconnect(server);
556 csocket = server->ssocket;
557 reconnect = 1;
558 break;
561 if (reconnect == 2)
562 break;
563 else if (reconnect == 1)
564 continue;
566 length += 4; /* account for rfc1002 hdr */
569 dump_smb(smb_buffer, length);
570 if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
571 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
572 continue;
576 task_to_wake = NULL;
577 spin_lock(&GlobalMid_Lock);
578 list_for_each(tmp, &server->pending_mid_q) {
579 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
581 if ((mid_entry->mid == smb_buffer->Mid) &&
582 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
583 (mid_entry->command == smb_buffer->Command)) {
584 if (check2ndT2(smb_buffer,server->maxBuf) > 0) {
585 /* We have a multipart transact2 resp */
586 isMultiRsp = true;
587 if (mid_entry->resp_buf) {
588 /* merge response - fix up 1st*/
589 if (coalesce_t2(smb_buffer,
590 mid_entry->resp_buf)) {
591 mid_entry->multiRsp =
592 true;
593 break;
594 } else {
595 /* all parts received */
596 mid_entry->multiEnd =
597 true;
598 goto multi_t2_fnd;
600 } else {
601 if (!isLargeBuf) {
602 cERROR(1,("1st trans2 resp needs bigbuf"));
603 /* BB maybe we can fix this up, switch
604 to already allocated large buffer? */
605 } else {
606 /* Have first buffer */
607 mid_entry->resp_buf =
608 smb_buffer;
609 mid_entry->largeBuf =
610 true;
611 bigbuf = NULL;
614 break;
616 mid_entry->resp_buf = smb_buffer;
617 mid_entry->largeBuf = isLargeBuf;
618 multi_t2_fnd:
619 task_to_wake = mid_entry->tsk;
620 mid_entry->midState = MID_RESPONSE_RECEIVED;
621 #ifdef CONFIG_CIFS_STATS2
622 mid_entry->when_received = jiffies;
623 #endif
624 /* so we do not time out requests to server
625 which is still responding (since server could
626 be busy but not dead) */
627 server->lstrp = jiffies;
628 break;
631 spin_unlock(&GlobalMid_Lock);
632 if (task_to_wake) {
633 /* Was previous buf put in mpx struct for multi-rsp? */
634 if (!isMultiRsp) {
635 /* smb buffer will be freed by user thread */
636 if (isLargeBuf)
637 bigbuf = NULL;
638 else
639 smallbuf = NULL;
641 wake_up_process(task_to_wake);
642 } else if (!is_valid_oplock_break(smb_buffer, server) &&
643 !isMultiRsp) {
644 cERROR(1, ("No task to wake, unknown frame received! "
645 "NumMids %d", midCount.counter));
646 cifs_dump_mem("Received Data is: ", (char *)smb_buffer,
647 sizeof(struct smb_hdr));
648 #ifdef CONFIG_CIFS_DEBUG2
649 cifs_dump_detail(smb_buffer);
650 cifs_dump_mids(server);
651 #endif /* CIFS_DEBUG2 */
654 } /* end while !EXITING */
656 /* take it off the list, if it's not already */
657 write_lock(&cifs_tcp_ses_lock);
658 list_del_init(&server->tcp_ses_list);
659 write_unlock(&cifs_tcp_ses_lock);
661 spin_lock(&GlobalMid_Lock);
662 server->tcpStatus = CifsExiting;
663 spin_unlock(&GlobalMid_Lock);
664 wake_up_all(&server->response_q);
666 /* check if we have blocked requests that need to free */
667 /* Note that cifs_max_pending is normally 50, but
668 can be set at module install time to as little as two */
669 spin_lock(&GlobalMid_Lock);
670 if (atomic_read(&server->inFlight) >= cifs_max_pending)
671 atomic_set(&server->inFlight, cifs_max_pending - 1);
672 /* We do not want to set the max_pending too low or we
673 could end up with the counter going negative */
674 spin_unlock(&GlobalMid_Lock);
675 /* Although there should not be any requests blocked on
676 this queue it can not hurt to be paranoid and try to wake up requests
677 that may haven been blocked when more than 50 at time were on the wire
678 to the same server - they now will see the session is in exit state
679 and get out of SendReceive. */
680 wake_up_all(&server->request_q);
681 /* give those requests time to exit */
682 msleep(125);
684 if (server->ssocket) {
685 sock_release(csocket);
686 server->ssocket = NULL;
688 /* buffer usuallly freed in free_mid - need to free it here on exit */
689 cifs_buf_release(bigbuf);
690 if (smallbuf) /* no sense logging a debug message if NULL */
691 cifs_small_buf_release(smallbuf);
694 * BB: we shouldn't have to do any of this. It shouldn't be
695 * possible to exit from the thread with active SMB sessions
697 read_lock(&cifs_tcp_ses_lock);
698 if (list_empty(&server->pending_mid_q)) {
699 /* loop through server session structures attached to this and
700 mark them dead */
701 list_for_each(tmp, &server->smb_ses_list) {
702 ses = list_entry(tmp, struct cifsSesInfo,
703 smb_ses_list);
704 ses->status = CifsExiting;
705 ses->server = NULL;
707 read_unlock(&cifs_tcp_ses_lock);
708 } else {
709 /* although we can not zero the server struct pointer yet,
710 since there are active requests which may depnd on them,
711 mark the corresponding SMB sessions as exiting too */
712 list_for_each(tmp, &server->smb_ses_list) {
713 ses = list_entry(tmp, struct cifsSesInfo,
714 smb_ses_list);
715 ses->status = CifsExiting;
718 spin_lock(&GlobalMid_Lock);
719 list_for_each(tmp, &server->pending_mid_q) {
720 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
721 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
722 cFYI(1, ("Clearing Mid 0x%x - waking up ",
723 mid_entry->mid));
724 task_to_wake = mid_entry->tsk;
725 if (task_to_wake)
726 wake_up_process(task_to_wake);
729 spin_unlock(&GlobalMid_Lock);
730 read_unlock(&cifs_tcp_ses_lock);
731 /* 1/8th of sec is more than enough time for them to exit */
732 msleep(125);
735 if (!list_empty(&server->pending_mid_q)) {
736 /* mpx threads have not exited yet give them
737 at least the smb send timeout time for long ops */
738 /* due to delays on oplock break requests, we need
739 to wait at least 45 seconds before giving up
740 on a request getting a response and going ahead
741 and killing cifsd */
742 cFYI(1, ("Wait for exit from demultiplex thread"));
743 msleep(46000);
744 /* if threads still have not exited they are probably never
745 coming home not much else we can do but free the memory */
748 /* last chance to mark ses pointers invalid
749 if there are any pointing to this (e.g
750 if a crazy root user tried to kill cifsd
751 kernel thread explicitly this might happen) */
752 /* BB: This shouldn't be necessary, see above */
753 read_lock(&cifs_tcp_ses_lock);
754 list_for_each(tmp, &server->smb_ses_list) {
755 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
756 ses->server = NULL;
758 read_unlock(&cifs_tcp_ses_lock);
760 kfree(server->hostname);
761 task_to_wake = xchg(&server->tsk, NULL);
762 kfree(server);
764 length = atomic_dec_return(&tcpSesAllocCount);
765 if (length > 0)
766 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
767 GFP_KERNEL);
769 /* if server->tsk was NULL then wait for a signal before exiting */
770 if (!task_to_wake) {
771 set_current_state(TASK_INTERRUPTIBLE);
772 while (!signal_pending(current)) {
773 schedule();
774 set_current_state(TASK_INTERRUPTIBLE);
776 set_current_state(TASK_RUNNING);
779 return 0;
782 /* extract the host portion of the UNC string */
783 static char *
784 extract_hostname(const char *unc)
786 const char *src;
787 char *dst, *delim;
788 unsigned int len;
790 /* skip double chars at beginning of string */
791 /* BB: check validity of these bytes? */
792 src = unc + 2;
794 /* delimiter between hostname and sharename is always '\\' now */
795 delim = strchr(src, '\\');
796 if (!delim)
797 return ERR_PTR(-EINVAL);
799 len = delim - src;
800 dst = kmalloc((len + 1), GFP_KERNEL);
801 if (dst == NULL)
802 return ERR_PTR(-ENOMEM);
804 memcpy(dst, src, len);
805 dst[len] = '\0';
807 return dst;
810 static int
811 cifs_parse_mount_options(char *options, const char *devname,
812 struct smb_vol *vol)
814 char *value;
815 char *data;
816 unsigned int temp_len, i, j;
817 char separator[2];
819 separator[0] = ',';
820 separator[1] = 0;
822 if (Local_System_Name[0] != 0)
823 memcpy(vol->source_rfc1001_name, Local_System_Name, 15);
824 else {
825 char *nodename = utsname()->nodename;
826 int n = strnlen(nodename, 15);
827 memset(vol->source_rfc1001_name, 0x20, 15);
828 for (i = 0; i < n; i++) {
829 /* does not have to be perfect mapping since field is
830 informational, only used for servers that do not support
831 port 445 and it can be overridden at mount time */
832 vol->source_rfc1001_name[i] = toupper(nodename[i]);
835 vol->source_rfc1001_name[15] = 0;
836 /* null target name indicates to use *SMBSERVR default called name
837 if we end up sending RFC1001 session initialize */
838 vol->target_rfc1001_name[0] = 0;
839 vol->linux_uid = current->uid; /* current->euid instead? */
840 vol->linux_gid = current->gid;
841 vol->dir_mode = S_IRWXUGO;
842 /* 2767 perms indicate mandatory locking support */
843 vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);
845 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
846 vol->rw = true;
847 /* default is always to request posix paths. */
848 vol->posix_paths = 1;
850 if (!options)
851 return 1;
853 if (strncmp(options, "sep=", 4) == 0) {
854 if (options[4] != 0) {
855 separator[0] = options[4];
856 options += 5;
857 } else {
858 cFYI(1, ("Null separator not allowed"));
862 while ((data = strsep(&options, separator)) != NULL) {
863 if (!*data)
864 continue;
865 if ((value = strchr(data, '=')) != NULL)
866 *value++ = '\0';
868 /* Have to parse this before we parse for "user" */
869 if (strnicmp(data, "user_xattr", 10) == 0) {
870 vol->no_xattr = 0;
871 } else if (strnicmp(data, "nouser_xattr", 12) == 0) {
872 vol->no_xattr = 1;
873 } else if (strnicmp(data, "user", 4) == 0) {
874 if (!value) {
875 printk(KERN_WARNING
876 "CIFS: invalid or missing username\n");
877 return 1; /* needs_arg; */
878 } else if (!*value) {
879 /* null user, ie anonymous, authentication */
880 vol->nullauth = 1;
882 if (strnlen(value, 200) < 200) {
883 vol->username = value;
884 } else {
885 printk(KERN_WARNING "CIFS: username too long\n");
886 return 1;
888 } else if (strnicmp(data, "pass", 4) == 0) {
889 if (!value) {
890 vol->password = NULL;
891 continue;
892 } else if (value[0] == 0) {
893 /* check if string begins with double comma
894 since that would mean the password really
895 does start with a comma, and would not
896 indicate an empty string */
897 if (value[1] != separator[0]) {
898 vol->password = NULL;
899 continue;
902 temp_len = strlen(value);
903 /* removed password length check, NTLM passwords
904 can be arbitrarily long */
906 /* if comma in password, the string will be
907 prematurely null terminated. Commas in password are
908 specified across the cifs mount interface by a double
909 comma ie ,, and a comma used as in other cases ie ','
910 as a parameter delimiter/separator is single and due
911 to the strsep above is temporarily zeroed. */
913 /* NB: password legally can have multiple commas and
914 the only illegal character in a password is null */
916 if ((value[temp_len] == 0) &&
917 (value[temp_len+1] == separator[0])) {
918 /* reinsert comma */
919 value[temp_len] = separator[0];
920 temp_len += 2; /* move after second comma */
921 while (value[temp_len] != 0) {
922 if (value[temp_len] == separator[0]) {
923 if (value[temp_len+1] ==
924 separator[0]) {
925 /* skip second comma */
926 temp_len++;
927 } else {
928 /* single comma indicating start
929 of next parm */
930 break;
933 temp_len++;
935 if (value[temp_len] == 0) {
936 options = NULL;
937 } else {
938 value[temp_len] = 0;
939 /* point option to start of next parm */
940 options = value + temp_len + 1;
942 /* go from value to value + temp_len condensing
943 double commas to singles. Note that this ends up
944 allocating a few bytes too many, which is ok */
945 vol->password = kzalloc(temp_len, GFP_KERNEL);
946 if (vol->password == NULL) {
947 printk(KERN_WARNING "CIFS: no memory "
948 "for password\n");
949 return 1;
951 for (i = 0, j = 0; i < temp_len; i++, j++) {
952 vol->password[j] = value[i];
953 if (value[i] == separator[0]
954 && value[i+1] == separator[0]) {
955 /* skip second comma */
956 i++;
959 vol->password[j] = 0;
960 } else {
961 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
962 if (vol->password == NULL) {
963 printk(KERN_WARNING "CIFS: no memory "
964 "for password\n");
965 return 1;
967 strcpy(vol->password, value);
969 } else if (strnicmp(data, "ip", 2) == 0) {
970 if (!value || !*value) {
971 vol->UNCip = NULL;
972 } else if (strnlen(value, 35) < 35) {
973 vol->UNCip = value;
974 } else {
975 printk(KERN_WARNING "CIFS: ip address "
976 "too long\n");
977 return 1;
979 } else if (strnicmp(data, "sec", 3) == 0) {
980 if (!value || !*value) {
981 cERROR(1, ("no security value specified"));
982 continue;
983 } else if (strnicmp(value, "krb5i", 5) == 0) {
984 vol->secFlg |= CIFSSEC_MAY_KRB5 |
985 CIFSSEC_MUST_SIGN;
986 } else if (strnicmp(value, "krb5p", 5) == 0) {
987 /* vol->secFlg |= CIFSSEC_MUST_SEAL |
988 CIFSSEC_MAY_KRB5; */
989 cERROR(1, ("Krb5 cifs privacy not supported"));
990 return 1;
991 } else if (strnicmp(value, "krb5", 4) == 0) {
992 vol->secFlg |= CIFSSEC_MAY_KRB5;
993 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
994 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
995 CIFSSEC_MUST_SIGN;
996 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
997 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
998 } else if (strnicmp(value, "ntlmi", 5) == 0) {
999 vol->secFlg |= CIFSSEC_MAY_NTLM |
1000 CIFSSEC_MUST_SIGN;
1001 } else if (strnicmp(value, "ntlm", 4) == 0) {
1002 /* ntlm is default so can be turned off too */
1003 vol->secFlg |= CIFSSEC_MAY_NTLM;
1004 } else if (strnicmp(value, "nontlm", 6) == 0) {
1005 /* BB is there a better way to do this? */
1006 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
1007 #ifdef CONFIG_CIFS_WEAK_PW_HASH
1008 } else if (strnicmp(value, "lanman", 6) == 0) {
1009 vol->secFlg |= CIFSSEC_MAY_LANMAN;
1010 #endif
1011 } else if (strnicmp(value, "none", 4) == 0) {
1012 vol->nullauth = 1;
1013 } else {
1014 cERROR(1, ("bad security option: %s", value));
1015 return 1;
1017 } else if ((strnicmp(data, "unc", 3) == 0)
1018 || (strnicmp(data, "target", 6) == 0)
1019 || (strnicmp(data, "path", 4) == 0)) {
1020 if (!value || !*value) {
1021 printk(KERN_WARNING "CIFS: invalid path to "
1022 "network resource\n");
1023 return 1; /* needs_arg; */
1025 if ((temp_len = strnlen(value, 300)) < 300) {
1026 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1027 if (vol->UNC == NULL)
1028 return 1;
1029 strcpy(vol->UNC, value);
1030 if (strncmp(vol->UNC, "//", 2) == 0) {
1031 vol->UNC[0] = '\\';
1032 vol->UNC[1] = '\\';
1033 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1034 printk(KERN_WARNING
1035 "CIFS: UNC Path does not begin "
1036 "with // or \\\\ \n");
1037 return 1;
1039 } else {
1040 printk(KERN_WARNING "CIFS: UNC name too long\n");
1041 return 1;
1043 } else if ((strnicmp(data, "domain", 3) == 0)
1044 || (strnicmp(data, "workgroup", 5) == 0)) {
1045 if (!value || !*value) {
1046 printk(KERN_WARNING "CIFS: invalid domain name\n");
1047 return 1; /* needs_arg; */
1049 /* BB are there cases in which a comma can be valid in
1050 a domain name and need special handling? */
1051 if (strnlen(value, 256) < 256) {
1052 vol->domainname = value;
1053 cFYI(1, ("Domain name set"));
1054 } else {
1055 printk(KERN_WARNING "CIFS: domain name too "
1056 "long\n");
1057 return 1;
1059 } else if (strnicmp(data, "prefixpath", 10) == 0) {
1060 if (!value || !*value) {
1061 printk(KERN_WARNING
1062 "CIFS: invalid path prefix\n");
1063 return 1; /* needs_argument */
1065 if ((temp_len = strnlen(value, 1024)) < 1024) {
1066 if (value[0] != '/')
1067 temp_len++; /* missing leading slash */
1068 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1069 if (vol->prepath == NULL)
1070 return 1;
1071 if (value[0] != '/') {
1072 vol->prepath[0] = '/';
1073 strcpy(vol->prepath+1, value);
1074 } else
1075 strcpy(vol->prepath, value);
1076 cFYI(1, ("prefix path %s", vol->prepath));
1077 } else {
1078 printk(KERN_WARNING "CIFS: prefix too long\n");
1079 return 1;
1081 } else if (strnicmp(data, "iocharset", 9) == 0) {
1082 if (!value || !*value) {
1083 printk(KERN_WARNING "CIFS: invalid iocharset "
1084 "specified\n");
1085 return 1; /* needs_arg; */
1087 if (strnlen(value, 65) < 65) {
1088 if (strnicmp(value, "default", 7))
1089 vol->iocharset = value;
1090 /* if iocharset not set then load_nls_default
1091 is used by caller */
1092 cFYI(1, ("iocharset set to %s", value));
1093 } else {
1094 printk(KERN_WARNING "CIFS: iocharset name "
1095 "too long.\n");
1096 return 1;
1098 } else if (strnicmp(data, "uid", 3) == 0) {
1099 if (value && *value) {
1100 vol->linux_uid =
1101 simple_strtoul(value, &value, 0);
1102 vol->override_uid = 1;
1104 } else if (strnicmp(data, "gid", 3) == 0) {
1105 if (value && *value) {
1106 vol->linux_gid =
1107 simple_strtoul(value, &value, 0);
1108 vol->override_gid = 1;
1110 } else if (strnicmp(data, "file_mode", 4) == 0) {
1111 if (value && *value) {
1112 vol->file_mode =
1113 simple_strtoul(value, &value, 0);
1115 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1116 if (value && *value) {
1117 vol->dir_mode =
1118 simple_strtoul(value, &value, 0);
1120 } else if (strnicmp(data, "dirmode", 4) == 0) {
1121 if (value && *value) {
1122 vol->dir_mode =
1123 simple_strtoul(value, &value, 0);
1125 } else if (strnicmp(data, "port", 4) == 0) {
1126 if (value && *value) {
1127 vol->port =
1128 simple_strtoul(value, &value, 0);
1130 } else if (strnicmp(data, "rsize", 5) == 0) {
1131 if (value && *value) {
1132 vol->rsize =
1133 simple_strtoul(value, &value, 0);
1135 } else if (strnicmp(data, "wsize", 5) == 0) {
1136 if (value && *value) {
1137 vol->wsize =
1138 simple_strtoul(value, &value, 0);
1140 } else if (strnicmp(data, "sockopt", 5) == 0) {
1141 if (value && *value) {
1142 vol->sockopt =
1143 simple_strtoul(value, &value, 0);
1145 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1146 if (!value || !*value || (*value == ' ')) {
1147 cFYI(1, ("invalid (empty) netbiosname"));
1148 } else {
1149 memset(vol->source_rfc1001_name, 0x20, 15);
1150 for (i = 0; i < 15; i++) {
1151 /* BB are there cases in which a comma can be
1152 valid in this workstation netbios name (and need
1153 special handling)? */
1155 /* We do not uppercase netbiosname for user */
1156 if (value[i] == 0)
1157 break;
1158 else
1159 vol->source_rfc1001_name[i] =
1160 value[i];
1162 /* The string has 16th byte zero still from
1163 set at top of the function */
1164 if ((i == 15) && (value[i] != 0))
1165 printk(KERN_WARNING "CIFS: netbiosname"
1166 " longer than 15 truncated.\n");
1168 } else if (strnicmp(data, "servern", 7) == 0) {
1169 /* servernetbiosname specified override *SMBSERVER */
1170 if (!value || !*value || (*value == ' ')) {
1171 cFYI(1, ("empty server netbiosname specified"));
1172 } else {
1173 /* last byte, type, is 0x20 for servr type */
1174 memset(vol->target_rfc1001_name, 0x20, 16);
1176 for (i = 0; i < 15; i++) {
1177 /* BB are there cases in which a comma can be
1178 valid in this workstation netbios name
1179 (and need special handling)? */
1181 /* user or mount helper must uppercase
1182 the netbiosname */
1183 if (value[i] == 0)
1184 break;
1185 else
1186 vol->target_rfc1001_name[i] =
1187 value[i];
1189 /* The string has 16th byte zero still from
1190 set at top of the function */
1191 if ((i == 15) && (value[i] != 0))
1192 printk(KERN_WARNING "CIFS: server net"
1193 "biosname longer than 15 truncated.\n");
1195 } else if (strnicmp(data, "credentials", 4) == 0) {
1196 /* ignore */
1197 } else if (strnicmp(data, "version", 3) == 0) {
1198 /* ignore */
1199 } else if (strnicmp(data, "guest", 5) == 0) {
1200 /* ignore */
1201 } else if (strnicmp(data, "rw", 2) == 0) {
1202 vol->rw = true;
1203 } else if (strnicmp(data, "noblocksend", 11) == 0) {
1204 vol->noblocksnd = 1;
1205 } else if (strnicmp(data, "noautotune", 10) == 0) {
1206 vol->noautotune = 1;
1207 } else if ((strnicmp(data, "suid", 4) == 0) ||
1208 (strnicmp(data, "nosuid", 6) == 0) ||
1209 (strnicmp(data, "exec", 4) == 0) ||
1210 (strnicmp(data, "noexec", 6) == 0) ||
1211 (strnicmp(data, "nodev", 5) == 0) ||
1212 (strnicmp(data, "noauto", 6) == 0) ||
1213 (strnicmp(data, "dev", 3) == 0)) {
1214 /* The mount tool or mount.cifs helper (if present)
1215 uses these opts to set flags, and the flags are read
1216 by the kernel vfs layer before we get here (ie
1217 before read super) so there is no point trying to
1218 parse these options again and set anything and it
1219 is ok to just ignore them */
1220 continue;
1221 } else if (strnicmp(data, "ro", 2) == 0) {
1222 vol->rw = false;
1223 } else if (strnicmp(data, "hard", 4) == 0) {
1224 vol->retry = 1;
1225 } else if (strnicmp(data, "soft", 4) == 0) {
1226 vol->retry = 0;
1227 } else if (strnicmp(data, "perm", 4) == 0) {
1228 vol->noperm = 0;
1229 } else if (strnicmp(data, "noperm", 6) == 0) {
1230 vol->noperm = 1;
1231 } else if (strnicmp(data, "mapchars", 8) == 0) {
1232 vol->remap = 1;
1233 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1234 vol->remap = 0;
1235 } else if (strnicmp(data, "sfu", 3) == 0) {
1236 vol->sfu_emul = 1;
1237 } else if (strnicmp(data, "nosfu", 5) == 0) {
1238 vol->sfu_emul = 0;
1239 } else if (strnicmp(data, "nodfs", 5) == 0) {
1240 vol->nodfs = 1;
1241 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1242 vol->posix_paths = 1;
1243 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1244 vol->posix_paths = 0;
1245 } else if (strnicmp(data, "nounix", 6) == 0) {
1246 vol->no_linux_ext = 1;
1247 } else if (strnicmp(data, "nolinux", 7) == 0) {
1248 vol->no_linux_ext = 1;
1249 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1250 (strnicmp(data, "ignorecase", 10) == 0)) {
1251 vol->nocase = 1;
1252 } else if (strnicmp(data, "brl", 3) == 0) {
1253 vol->nobrl = 0;
1254 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1255 (strnicmp(data, "nolock", 6) == 0)) {
1256 vol->nobrl = 1;
1257 /* turn off mandatory locking in mode
1258 if remote locking is turned off since the
1259 local vfs will do advisory */
1260 if (vol->file_mode ==
1261 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1262 vol->file_mode = S_IALLUGO;
1263 } else if (strnicmp(data, "setuids", 7) == 0) {
1264 vol->setuids = 1;
1265 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1266 vol->setuids = 0;
1267 } else if (strnicmp(data, "dynperm", 7) == 0) {
1268 vol->dynperm = true;
1269 } else if (strnicmp(data, "nodynperm", 9) == 0) {
1270 vol->dynperm = false;
1271 } else if (strnicmp(data, "nohard", 6) == 0) {
1272 vol->retry = 0;
1273 } else if (strnicmp(data, "nosoft", 6) == 0) {
1274 vol->retry = 1;
1275 } else if (strnicmp(data, "nointr", 6) == 0) {
1276 vol->intr = 0;
1277 } else if (strnicmp(data, "intr", 4) == 0) {
1278 vol->intr = 1;
1279 } else if (strnicmp(data, "serverino", 7) == 0) {
1280 vol->server_ino = 1;
1281 } else if (strnicmp(data, "noserverino", 9) == 0) {
1282 vol->server_ino = 0;
1283 } else if (strnicmp(data, "cifsacl", 7) == 0) {
1284 vol->cifs_acl = 1;
1285 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1286 vol->cifs_acl = 0;
1287 } else if (strnicmp(data, "acl", 3) == 0) {
1288 vol->no_psx_acl = 0;
1289 } else if (strnicmp(data, "noacl", 5) == 0) {
1290 vol->no_psx_acl = 1;
1291 #ifdef CONFIG_CIFS_EXPERIMENTAL
1292 } else if (strnicmp(data, "locallease", 6) == 0) {
1293 vol->local_lease = 1;
1294 #endif
1295 } else if (strnicmp(data, "sign", 4) == 0) {
1296 vol->secFlg |= CIFSSEC_MUST_SIGN;
1297 } else if (strnicmp(data, "seal", 4) == 0) {
1298 /* we do not do the following in secFlags because seal
1299 is a per tree connection (mount) not a per socket
1300 or per-smb connection option in the protocol */
1301 /* vol->secFlg |= CIFSSEC_MUST_SEAL; */
1302 vol->seal = 1;
1303 } else if (strnicmp(data, "direct", 6) == 0) {
1304 vol->direct_io = 1;
1305 } else if (strnicmp(data, "forcedirectio", 13) == 0) {
1306 vol->direct_io = 1;
1307 } else if (strnicmp(data, "in6_addr", 8) == 0) {
1308 if (!value || !*value) {
1309 vol->in6_addr = NULL;
1310 } else if (strnlen(value, 49) == 48) {
1311 vol->in6_addr = value;
1312 } else {
1313 printk(KERN_WARNING "CIFS: ip v6 address not "
1314 "48 characters long\n");
1315 return 1;
1317 } else if (strnicmp(data, "noac", 4) == 0) {
1318 printk(KERN_WARNING "CIFS: Mount option noac not "
1319 "supported. Instead set "
1320 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
1321 } else
1322 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
1323 data);
1325 if (vol->UNC == NULL) {
1326 if (devname == NULL) {
1327 printk(KERN_WARNING "CIFS: Missing UNC name for mount "
1328 "target\n");
1329 return 1;
1331 if ((temp_len = strnlen(devname, 300)) < 300) {
1332 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1333 if (vol->UNC == NULL)
1334 return 1;
1335 strcpy(vol->UNC, devname);
1336 if (strncmp(vol->UNC, "//", 2) == 0) {
1337 vol->UNC[0] = '\\';
1338 vol->UNC[1] = '\\';
1339 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1340 printk(KERN_WARNING "CIFS: UNC Path does not "
1341 "begin with // or \\\\ \n");
1342 return 1;
1344 value = strpbrk(vol->UNC+2, "/\\");
1345 if (value)
1346 *value = '\\';
1347 } else {
1348 printk(KERN_WARNING "CIFS: UNC name too long\n");
1349 return 1;
1352 if (vol->UNCip == NULL)
1353 vol->UNCip = &vol->UNC[2];
1355 return 0;
1358 static struct TCP_Server_Info *
1359 cifs_find_tcp_session(struct sockaddr *addr)
1361 struct list_head *tmp;
1362 struct TCP_Server_Info *server;
1363 struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
1364 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
1366 write_lock(&cifs_tcp_ses_lock);
1367 list_for_each(tmp, &cifs_tcp_ses_list) {
1368 server = list_entry(tmp, struct TCP_Server_Info,
1369 tcp_ses_list);
1371 * the demux thread can exit on its own while still in CifsNew
1372 * so don't accept any sockets in that state. Since the
1373 * tcpStatus never changes back to CifsNew it's safe to check
1374 * for this without a lock.
1376 if (server->tcpStatus == CifsNew)
1377 continue;
1379 if (addr->sa_family == AF_INET &&
1380 (addr4->sin_addr.s_addr !=
1381 server->addr.sockAddr.sin_addr.s_addr))
1382 continue;
1383 else if (addr->sa_family == AF_INET6 &&
1384 memcmp(&server->addr.sockAddr6.sin6_addr,
1385 &addr6->sin6_addr, sizeof(addr6->sin6_addr)))
1386 continue;
1388 ++server->srv_count;
1389 write_unlock(&cifs_tcp_ses_lock);
1390 cFYI(1, ("Existing tcp session with server found"));
1391 return server;
1393 write_unlock(&cifs_tcp_ses_lock);
1394 return NULL;
1397 static void
1398 cifs_put_tcp_session(struct TCP_Server_Info *server)
1400 struct task_struct *task;
1402 write_lock(&cifs_tcp_ses_lock);
1403 if (--server->srv_count > 0) {
1404 write_unlock(&cifs_tcp_ses_lock);
1405 return;
1408 list_del_init(&server->tcp_ses_list);
1409 write_unlock(&cifs_tcp_ses_lock);
1411 spin_lock(&GlobalMid_Lock);
1412 server->tcpStatus = CifsExiting;
1413 spin_unlock(&GlobalMid_Lock);
1415 task = xchg(&server->tsk, NULL);
1416 if (task)
1417 force_sig(SIGKILL, task);
1420 static struct cifsSesInfo *
1421 cifs_find_smb_ses(struct TCP_Server_Info *server, char *username)
1423 struct list_head *tmp;
1424 struct cifsSesInfo *ses;
1426 write_lock(&cifs_tcp_ses_lock);
1427 list_for_each(tmp, &server->smb_ses_list) {
1428 ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list);
1429 if (strncmp(ses->userName, username, MAX_USERNAME_SIZE))
1430 continue;
1432 ++ses->ses_count;
1433 write_unlock(&cifs_tcp_ses_lock);
1434 return ses;
1436 write_unlock(&cifs_tcp_ses_lock);
1437 return NULL;
1440 static void
1441 cifs_put_smb_ses(struct cifsSesInfo *ses)
1443 int xid;
1444 struct TCP_Server_Info *server = ses->server;
1446 write_lock(&cifs_tcp_ses_lock);
1447 if (--ses->ses_count > 0) {
1448 write_unlock(&cifs_tcp_ses_lock);
1449 return;
1452 list_del_init(&ses->smb_ses_list);
1453 write_unlock(&cifs_tcp_ses_lock);
1455 if (ses->status == CifsGood) {
1456 xid = GetXid();
1457 CIFSSMBLogoff(xid, ses);
1458 _FreeXid(xid);
1460 sesInfoFree(ses);
1461 cifs_put_tcp_session(server);
1464 static struct cifsTconInfo *
1465 cifs_find_tcon(struct cifsSesInfo *ses, const char *unc)
1467 struct list_head *tmp;
1468 struct cifsTconInfo *tcon;
1470 write_lock(&cifs_tcp_ses_lock);
1471 list_for_each(tmp, &ses->tcon_list) {
1472 tcon = list_entry(tmp, struct cifsTconInfo, tcon_list);
1473 if (tcon->tidStatus == CifsExiting)
1474 continue;
1475 if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE))
1476 continue;
1478 ++tcon->tc_count;
1479 write_unlock(&cifs_tcp_ses_lock);
1480 return tcon;
1482 write_unlock(&cifs_tcp_ses_lock);
1483 return NULL;
1486 static void
1487 cifs_put_tcon(struct cifsTconInfo *tcon)
1489 int xid;
1490 struct cifsSesInfo *ses = tcon->ses;
1492 write_lock(&cifs_tcp_ses_lock);
1493 if (--tcon->tc_count > 0) {
1494 write_unlock(&cifs_tcp_ses_lock);
1495 return;
1498 list_del_init(&tcon->tcon_list);
1499 write_unlock(&cifs_tcp_ses_lock);
1501 xid = GetXid();
1502 CIFSSMBTDis(xid, tcon);
1503 _FreeXid(xid);
1505 DeleteTconOplockQEntries(tcon);
1506 tconInfoFree(tcon);
1507 cifs_put_smb_ses(ses);
1511 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
1512 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
1513 struct dfs_info3_param **preferrals, int remap)
1515 char *temp_unc;
1516 int rc = 0;
1518 *pnum_referrals = 0;
1519 *preferrals = NULL;
1521 if (pSesInfo->ipc_tid == 0) {
1522 temp_unc = kmalloc(2 /* for slashes */ +
1523 strnlen(pSesInfo->serverName,
1524 SERVER_NAME_LEN_WITH_NULL * 2)
1525 + 1 + 4 /* slash IPC$ */ + 2,
1526 GFP_KERNEL);
1527 if (temp_unc == NULL)
1528 return -ENOMEM;
1529 temp_unc[0] = '\\';
1530 temp_unc[1] = '\\';
1531 strcpy(temp_unc + 2, pSesInfo->serverName);
1532 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1533 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1534 cFYI(1,
1535 ("CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid));
1536 kfree(temp_unc);
1538 if (rc == 0)
1539 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1540 pnum_referrals, nls_codepage, remap);
1541 /* BB map targetUNCs to dfs_info3 structures, here or
1542 in CIFSGetDFSRefer BB */
1544 return rc;
1547 #ifdef CONFIG_DEBUG_LOCK_ALLOC
1548 static struct lock_class_key cifs_key[2];
1549 static struct lock_class_key cifs_slock_key[2];
1551 static inline void
1552 cifs_reclassify_socket4(struct socket *sock)
1554 struct sock *sk = sock->sk;
1555 BUG_ON(sock_owned_by_user(sk));
1556 sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
1557 &cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
1560 static inline void
1561 cifs_reclassify_socket6(struct socket *sock)
1563 struct sock *sk = sock->sk;
1564 BUG_ON(sock_owned_by_user(sk));
1565 sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
1566 &cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
1568 #else
1569 static inline void
1570 cifs_reclassify_socket4(struct socket *sock)
1574 static inline void
1575 cifs_reclassify_socket6(struct socket *sock)
1578 #endif
1580 /* See RFC1001 section 14 on representation of Netbios names */
1581 static void rfc1002mangle(char *target, char *source, unsigned int length)
1583 unsigned int i, j;
1585 for (i = 0, j = 0; i < (length); i++) {
1586 /* mask a nibble at a time and encode */
1587 target[j] = 'A' + (0x0F & (source[i] >> 4));
1588 target[j+1] = 'A' + (0x0F & source[i]);
1589 j += 2;
1595 static int
1596 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1597 char *netbios_name, char *target_name,
1598 bool noblocksnd, bool noautotune)
1600 int rc = 0;
1601 int connected = 0;
1602 __be16 orig_port = 0;
1604 if (*csocket == NULL) {
1605 rc = sock_create_kern(PF_INET, SOCK_STREAM,
1606 IPPROTO_TCP, csocket);
1607 if (rc < 0) {
1608 cERROR(1, ("Error %d creating socket", rc));
1609 *csocket = NULL;
1610 return rc;
1611 } else {
1612 /* BB other socket options to set KEEPALIVE, NODELAY? */
1613 cFYI(1, ("Socket created"));
1614 (*csocket)->sk->sk_allocation = GFP_NOFS;
1615 cifs_reclassify_socket4(*csocket);
1619 psin_server->sin_family = AF_INET;
1620 if (psin_server->sin_port) { /* user overrode default port */
1621 rc = (*csocket)->ops->connect(*csocket,
1622 (struct sockaddr *) psin_server,
1623 sizeof(struct sockaddr_in), 0);
1624 if (rc >= 0)
1625 connected = 1;
1628 if (!connected) {
1629 /* save original port so we can retry user specified port
1630 later if fall back ports fail this time */
1631 orig_port = psin_server->sin_port;
1633 /* do not retry on the same port we just failed on */
1634 if (psin_server->sin_port != htons(CIFS_PORT)) {
1635 psin_server->sin_port = htons(CIFS_PORT);
1637 rc = (*csocket)->ops->connect(*csocket,
1638 (struct sockaddr *) psin_server,
1639 sizeof(struct sockaddr_in), 0);
1640 if (rc >= 0)
1641 connected = 1;
1644 if (!connected) {
1645 psin_server->sin_port = htons(RFC1001_PORT);
1646 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1647 psin_server,
1648 sizeof(struct sockaddr_in), 0);
1649 if (rc >= 0)
1650 connected = 1;
1653 /* give up here - unless we want to retry on different
1654 protocol families some day */
1655 if (!connected) {
1656 if (orig_port)
1657 psin_server->sin_port = orig_port;
1658 cFYI(1, ("Error %d connecting to server via ipv4", rc));
1659 sock_release(*csocket);
1660 *csocket = NULL;
1661 return rc;
1663 /* Eventually check for other socket options to change from
1664 the default. sock_setsockopt not used because it expects
1665 user space buffer */
1666 cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
1667 (*csocket)->sk->sk_sndbuf,
1668 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1669 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1670 if (!noblocksnd)
1671 (*csocket)->sk->sk_sndtimeo = 3 * HZ;
1673 /* make the bufsizes depend on wsize/rsize and max requests */
1674 if (noautotune) {
1675 if ((*csocket)->sk->sk_sndbuf < (200 * 1024))
1676 (*csocket)->sk->sk_sndbuf = 200 * 1024;
1677 if ((*csocket)->sk->sk_rcvbuf < (140 * 1024))
1678 (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1681 /* send RFC1001 sessinit */
1682 if (psin_server->sin_port == htons(RFC1001_PORT)) {
1683 /* some servers require RFC1001 sessinit before sending
1684 negprot - BB check reconnection in case where second
1685 sessinit is sent but no second negprot */
1686 struct rfc1002_session_packet *ses_init_buf;
1687 struct smb_hdr *smb_buf;
1688 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
1689 GFP_KERNEL);
1690 if (ses_init_buf) {
1691 ses_init_buf->trailer.session_req.called_len = 32;
1692 if (target_name && (target_name[0] != 0)) {
1693 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1694 target_name, 16);
1695 } else {
1696 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1697 DEFAULT_CIFS_CALLED_NAME, 16);
1700 ses_init_buf->trailer.session_req.calling_len = 32;
1701 /* calling name ends in null (byte 16) from old smb
1702 convention. */
1703 if (netbios_name && (netbios_name[0] != 0)) {
1704 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1705 netbios_name, 16);
1706 } else {
1707 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1708 "LINUX_CIFS_CLNT", 16);
1710 ses_init_buf->trailer.session_req.scope1 = 0;
1711 ses_init_buf->trailer.session_req.scope2 = 0;
1712 smb_buf = (struct smb_hdr *)ses_init_buf;
1713 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1714 smb_buf->smb_buf_length = 0x81000044;
1715 rc = smb_send(*csocket, smb_buf, 0x44,
1716 (struct sockaddr *)psin_server, noblocksnd);
1717 kfree(ses_init_buf);
1718 msleep(1); /* RFC1001 layer in at least one server
1719 requires very short break before negprot
1720 presumably because not expecting negprot
1721 to follow so fast. This is a simple
1722 solution that works without
1723 complicating the code and causes no
1724 significant slowing down on mount
1725 for everyone else */
1727 /* else the negprot may still work without this
1728 even though malloc failed */
1732 return rc;
1735 static int
1736 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket,
1737 bool noblocksnd)
1739 int rc = 0;
1740 int connected = 0;
1741 __be16 orig_port = 0;
1743 if (*csocket == NULL) {
1744 rc = sock_create_kern(PF_INET6, SOCK_STREAM,
1745 IPPROTO_TCP, csocket);
1746 if (rc < 0) {
1747 cERROR(1, ("Error %d creating ipv6 socket", rc));
1748 *csocket = NULL;
1749 return rc;
1750 } else {
1751 /* BB other socket options to set KEEPALIVE, NODELAY? */
1752 cFYI(1, ("ipv6 Socket created"));
1753 (*csocket)->sk->sk_allocation = GFP_NOFS;
1754 cifs_reclassify_socket6(*csocket);
1758 psin_server->sin6_family = AF_INET6;
1760 if (psin_server->sin6_port) { /* user overrode default port */
1761 rc = (*csocket)->ops->connect(*csocket,
1762 (struct sockaddr *) psin_server,
1763 sizeof(struct sockaddr_in6), 0);
1764 if (rc >= 0)
1765 connected = 1;
1768 if (!connected) {
1769 /* save original port so we can retry user specified port
1770 later if fall back ports fail this time */
1772 orig_port = psin_server->sin6_port;
1773 /* do not retry on the same port we just failed on */
1774 if (psin_server->sin6_port != htons(CIFS_PORT)) {
1775 psin_server->sin6_port = htons(CIFS_PORT);
1777 rc = (*csocket)->ops->connect(*csocket,
1778 (struct sockaddr *) psin_server,
1779 sizeof(struct sockaddr_in6), 0);
1780 if (rc >= 0)
1781 connected = 1;
1784 if (!connected) {
1785 psin_server->sin6_port = htons(RFC1001_PORT);
1786 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1787 psin_server, sizeof(struct sockaddr_in6), 0);
1788 if (rc >= 0)
1789 connected = 1;
1792 /* give up here - unless we want to retry on different
1793 protocol families some day */
1794 if (!connected) {
1795 if (orig_port)
1796 psin_server->sin6_port = orig_port;
1797 cFYI(1, ("Error %d connecting to server via ipv6", rc));
1798 sock_release(*csocket);
1799 *csocket = NULL;
1800 return rc;
1802 /* Eventually check for other socket options to change from
1803 the default. sock_setsockopt not used because it expects
1804 user space buffer */
1805 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1806 if (!noblocksnd)
1807 (*csocket)->sk->sk_sndtimeo = 3 * HZ;
1810 return rc;
1813 void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
1814 struct super_block *sb, struct smb_vol *vol_info)
1816 /* if we are reconnecting then should we check to see if
1817 * any requested capabilities changed locally e.g. via
1818 * remount but we can not do much about it here
1819 * if they have (even if we could detect it by the following)
1820 * Perhaps we could add a backpointer to array of sb from tcon
1821 * or if we change to make all sb to same share the same
1822 * sb as NFS - then we only have one backpointer to sb.
1823 * What if we wanted to mount the server share twice once with
1824 * and once without posixacls or posix paths? */
1825 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1827 if (vol_info && vol_info->no_linux_ext) {
1828 tcon->fsUnixInfo.Capability = 0;
1829 tcon->unix_ext = 0; /* Unix Extensions disabled */
1830 cFYI(1, ("Linux protocol extensions disabled"));
1831 return;
1832 } else if (vol_info)
1833 tcon->unix_ext = 1; /* Unix Extensions supported */
1835 if (tcon->unix_ext == 0) {
1836 cFYI(1, ("Unix extensions disabled so not set on reconnect"));
1837 return;
1840 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
1841 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1843 /* check for reconnect case in which we do not
1844 want to change the mount behavior if we can avoid it */
1845 if (vol_info == NULL) {
1846 /* turn off POSIX ACL and PATHNAMES if not set
1847 originally at mount time */
1848 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
1849 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1850 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
1851 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
1852 cERROR(1, ("POSIXPATH support change"));
1853 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1854 } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) {
1855 cERROR(1, ("possible reconnect error"));
1856 cERROR(1,
1857 ("server disabled POSIX path support"));
1861 cap &= CIFS_UNIX_CAP_MASK;
1862 if (vol_info && vol_info->no_psx_acl)
1863 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1864 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
1865 cFYI(1, ("negotiated posix acl support"));
1866 if (sb)
1867 sb->s_flags |= MS_POSIXACL;
1870 if (vol_info && vol_info->posix_paths == 0)
1871 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1872 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
1873 cFYI(1, ("negotiate posix pathnames"));
1874 if (sb)
1875 CIFS_SB(sb)->mnt_cifs_flags |=
1876 CIFS_MOUNT_POSIX_PATHS;
1879 /* We might be setting the path sep back to a different
1880 form if we are reconnecting and the server switched its
1881 posix path capability for this share */
1882 if (sb && (CIFS_SB(sb)->prepathlen > 0))
1883 CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
1885 if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {
1886 if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
1887 CIFS_SB(sb)->rsize = 127 * 1024;
1888 cFYI(DBG2,
1889 ("larger reads not supported by srv"));
1894 cFYI(1, ("Negotiate caps 0x%x", (int)cap));
1895 #ifdef CONFIG_CIFS_DEBUG2
1896 if (cap & CIFS_UNIX_FCNTL_CAP)
1897 cFYI(1, ("FCNTL cap"));
1898 if (cap & CIFS_UNIX_EXTATTR_CAP)
1899 cFYI(1, ("EXTATTR cap"));
1900 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
1901 cFYI(1, ("POSIX path cap"));
1902 if (cap & CIFS_UNIX_XATTR_CAP)
1903 cFYI(1, ("XATTR cap"));
1904 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
1905 cFYI(1, ("POSIX ACL cap"));
1906 if (cap & CIFS_UNIX_LARGE_READ_CAP)
1907 cFYI(1, ("very large read cap"));
1908 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
1909 cFYI(1, ("very large write cap"));
1910 #endif /* CIFS_DEBUG2 */
1911 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1912 if (vol_info == NULL) {
1913 cFYI(1, ("resetting capabilities failed"));
1914 } else
1915 cERROR(1, ("Negotiating Unix capabilities "
1916 "with the server failed. Consider "
1917 "mounting with the Unix Extensions\n"
1918 "disabled, if problems are found, "
1919 "by specifying the nounix mount "
1920 "option."));
1926 static void
1927 convert_delimiter(char *path, char delim)
1929 int i;
1930 char old_delim;
1932 if (path == NULL)
1933 return;
1935 if (delim == '/')
1936 old_delim = '\\';
1937 else
1938 old_delim = '/';
1940 for (i = 0; path[i] != '\0'; i++) {
1941 if (path[i] == old_delim)
1942 path[i] = delim;
1946 static void setup_cifs_sb(struct smb_vol *pvolume_info,
1947 struct cifs_sb_info *cifs_sb)
1949 if (pvolume_info->rsize > CIFSMaxBufSize) {
1950 cERROR(1, ("rsize %d too large, using MaxBufSize",
1951 pvolume_info->rsize));
1952 cifs_sb->rsize = CIFSMaxBufSize;
1953 } else if ((pvolume_info->rsize) &&
1954 (pvolume_info->rsize <= CIFSMaxBufSize))
1955 cifs_sb->rsize = pvolume_info->rsize;
1956 else /* default */
1957 cifs_sb->rsize = CIFSMaxBufSize;
1959 if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
1960 cERROR(1, ("wsize %d too large, using 4096 instead",
1961 pvolume_info->wsize));
1962 cifs_sb->wsize = 4096;
1963 } else if (pvolume_info->wsize)
1964 cifs_sb->wsize = pvolume_info->wsize;
1965 else
1966 cifs_sb->wsize = min_t(const int,
1967 PAGEVEC_SIZE * PAGE_CACHE_SIZE,
1968 127*1024);
1969 /* old default of CIFSMaxBufSize was too small now
1970 that SMB Write2 can send multiple pages in kvec.
1971 RFC1001 does not describe what happens when frame
1972 bigger than 128K is sent so use that as max in
1973 conjunction with 52K kvec constraint on arch with 4K
1974 page size */
1976 if (cifs_sb->rsize < 2048) {
1977 cifs_sb->rsize = 2048;
1978 /* Windows ME may prefer this */
1979 cFYI(1, ("readsize set to minimum: 2048"));
1981 /* calculate prepath */
1982 cifs_sb->prepath = pvolume_info->prepath;
1983 if (cifs_sb->prepath) {
1984 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
1985 /* we can not convert the / to \ in the path
1986 separators in the prefixpath yet because we do not
1987 know (until reset_cifs_unix_caps is called later)
1988 whether POSIX PATH CAP is available. We normalize
1989 the / to \ after reset_cifs_unix_caps is called */
1990 pvolume_info->prepath = NULL;
1991 } else
1992 cifs_sb->prepathlen = 0;
1993 cifs_sb->mnt_uid = pvolume_info->linux_uid;
1994 cifs_sb->mnt_gid = pvolume_info->linux_gid;
1995 cifs_sb->mnt_file_mode = pvolume_info->file_mode;
1996 cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
1997 cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
1998 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
2000 if (pvolume_info->noperm)
2001 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
2002 if (pvolume_info->setuids)
2003 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
2004 if (pvolume_info->server_ino)
2005 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
2006 if (pvolume_info->remap)
2007 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
2008 if (pvolume_info->no_xattr)
2009 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
2010 if (pvolume_info->sfu_emul)
2011 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
2012 if (pvolume_info->nobrl)
2013 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
2014 if (pvolume_info->cifs_acl)
2015 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
2016 if (pvolume_info->override_uid)
2017 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
2018 if (pvolume_info->override_gid)
2019 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2020 if (pvolume_info->dynperm)
2021 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
2022 if (pvolume_info->direct_io) {
2023 cFYI(1, ("mounting share using direct i/o"));
2024 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
2027 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
2028 cERROR(1, ("mount option dynperm ignored if cifsacl "
2029 "mount option supported"));
2033 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2034 char *mount_data, const char *devname)
2036 int rc = 0;
2037 int xid;
2038 struct socket *csocket = NULL;
2039 struct sockaddr addr;
2040 struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
2041 struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
2042 struct smb_vol volume_info;
2043 struct cifsSesInfo *pSesInfo = NULL;
2044 struct cifsTconInfo *tcon = NULL;
2045 struct TCP_Server_Info *srvTcp = NULL;
2047 xid = GetXid();
2049 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
2051 memset(&addr, 0, sizeof(struct sockaddr));
2052 memset(&volume_info, 0, sizeof(struct smb_vol));
2053 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
2054 rc = -EINVAL;
2055 goto out;
2058 if (volume_info.nullauth) {
2059 cFYI(1, ("null user"));
2060 volume_info.username = "";
2061 } else if (volume_info.username) {
2062 /* BB fixme parse for domain name here */
2063 cFYI(1, ("Username: %s", volume_info.username));
2064 } else {
2065 cifserror("No username specified");
2066 /* In userspace mount helper we can get user name from alternate
2067 locations such as env variables and files on disk */
2068 rc = -EINVAL;
2069 goto out;
2072 if (volume_info.UNCip && volume_info.UNC) {
2073 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,
2074 &sin_server->sin_addr.s_addr);
2076 if (rc <= 0) {
2077 /* not ipv4 address, try ipv6 */
2078 rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,
2079 &sin_server6->sin6_addr.in6_u);
2080 if (rc > 0)
2081 addr.sa_family = AF_INET6;
2082 } else {
2083 addr.sa_family = AF_INET;
2086 if (rc <= 0) {
2087 /* we failed translating address */
2088 rc = -EINVAL;
2089 goto out;
2092 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
2093 /* success */
2094 rc = 0;
2095 } else if (volume_info.UNCip) {
2096 /* BB using ip addr as server name to connect to the
2097 DFS root below */
2098 cERROR(1, ("Connecting to DFS root not implemented yet"));
2099 rc = -EINVAL;
2100 goto out;
2101 } else /* which servers DFS root would we conect to */ {
2102 cERROR(1,
2103 ("CIFS mount error: No UNC path (e.g. -o "
2104 "unc=//192.168.1.100/public) specified"));
2105 rc = -EINVAL;
2106 goto out;
2109 /* this is needed for ASCII cp to Unicode converts */
2110 if (volume_info.iocharset == NULL) {
2111 cifs_sb->local_nls = load_nls_default();
2112 /* load_nls_default can not return null */
2113 } else {
2114 cifs_sb->local_nls = load_nls(volume_info.iocharset);
2115 if (cifs_sb->local_nls == NULL) {
2116 cERROR(1, ("CIFS mount error: iocharset %s not found",
2117 volume_info.iocharset));
2118 rc = -ELIBACC;
2119 goto out;
2123 srvTcp = cifs_find_tcp_session(&addr);
2124 if (!srvTcp) { /* create socket */
2125 if (addr.sa_family == AF_INET6) {
2126 cFYI(1, ("attempting ipv6 connect"));
2127 /* BB should we allow ipv6 on port 139? */
2128 /* other OS never observed in Wild doing 139 with v6 */
2129 sin_server6->sin6_port = htons(volume_info.port);
2130 rc = ipv6_connect(sin_server6, &csocket,
2131 volume_info.noblocksnd);
2132 } else {
2133 sin_server->sin_port = htons(volume_info.port);
2134 rc = ipv4_connect(sin_server, &csocket,
2135 volume_info.source_rfc1001_name,
2136 volume_info.target_rfc1001_name,
2137 volume_info.noblocksnd,
2138 volume_info.noautotune);
2140 if (rc < 0) {
2141 cERROR(1, ("Error connecting to socket. "
2142 "Aborting operation"));
2143 if (csocket != NULL)
2144 sock_release(csocket);
2145 goto out;
2148 srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
2149 if (!srvTcp) {
2150 rc = -ENOMEM;
2151 sock_release(csocket);
2152 goto out;
2153 } else {
2154 srvTcp->noblocksnd = volume_info.noblocksnd;
2155 srvTcp->noautotune = volume_info.noautotune;
2156 if (addr.sa_family == AF_INET6)
2157 memcpy(&srvTcp->addr.sockAddr6, sin_server6,
2158 sizeof(struct sockaddr_in6));
2159 else
2160 memcpy(&srvTcp->addr.sockAddr, sin_server,
2161 sizeof(struct sockaddr_in));
2162 atomic_set(&srvTcp->inFlight, 0);
2163 /* BB Add code for ipv6 case too */
2164 srvTcp->ssocket = csocket;
2165 srvTcp->hostname = extract_hostname(volume_info.UNC);
2166 if (IS_ERR(srvTcp->hostname)) {
2167 rc = PTR_ERR(srvTcp->hostname);
2168 sock_release(csocket);
2169 goto out;
2171 init_waitqueue_head(&srvTcp->response_q);
2172 init_waitqueue_head(&srvTcp->request_q);
2173 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
2174 /* at this point we are the only ones with the pointer
2175 to the struct since the kernel thread not created yet
2176 so no need to spinlock this init of tcpStatus */
2177 srvTcp->tcpStatus = CifsNew;
2178 init_MUTEX(&srvTcp->tcpSem);
2179 srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd");
2180 if (IS_ERR(srvTcp->tsk)) {
2181 rc = PTR_ERR(srvTcp->tsk);
2182 cERROR(1, ("error %d create cifsd thread", rc));
2183 srvTcp->tsk = NULL;
2184 sock_release(csocket);
2185 kfree(srvTcp->hostname);
2186 goto out;
2188 rc = 0;
2189 memcpy(srvTcp->workstation_RFC1001_name,
2190 volume_info.source_rfc1001_name, 16);
2191 memcpy(srvTcp->server_RFC1001_name,
2192 volume_info.target_rfc1001_name, 16);
2193 srvTcp->sequence_number = 0;
2194 INIT_LIST_HEAD(&srvTcp->tcp_ses_list);
2195 INIT_LIST_HEAD(&srvTcp->smb_ses_list);
2196 ++srvTcp->srv_count;
2197 write_lock(&cifs_tcp_ses_lock);
2198 list_add(&srvTcp->tcp_ses_list,
2199 &cifs_tcp_ses_list);
2200 write_unlock(&cifs_tcp_ses_lock);
2204 pSesInfo = cifs_find_smb_ses(srvTcp, volume_info.username);
2205 if (pSesInfo) {
2206 cFYI(1, ("Existing smb sess found (status=%d)",
2207 pSesInfo->status));
2209 * The existing SMB session already has a reference to srvTcp,
2210 * so we can put back the extra one we got before
2212 cifs_put_tcp_session(srvTcp);
2214 down(&pSesInfo->sesSem);
2215 if (pSesInfo->need_reconnect) {
2216 cFYI(1, ("Session needs reconnect"));
2217 rc = cifs_setup_session(xid, pSesInfo,
2218 cifs_sb->local_nls);
2220 up(&pSesInfo->sesSem);
2221 } else if (!rc) {
2222 cFYI(1, ("Existing smb sess not found"));
2223 pSesInfo = sesInfoAlloc();
2224 if (pSesInfo == NULL) {
2225 rc = -ENOMEM;
2226 goto mount_fail_check;
2229 /* new SMB session uses our srvTcp ref */
2230 pSesInfo->server = srvTcp;
2231 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
2232 NIPQUAD(sin_server->sin_addr.s_addr));
2234 write_lock(&cifs_tcp_ses_lock);
2235 list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list);
2236 write_unlock(&cifs_tcp_ses_lock);
2238 /* volume_info.password freed at unmount */
2239 if (volume_info.password) {
2240 pSesInfo->password = volume_info.password;
2241 /* set to NULL to prevent freeing on exit */
2242 volume_info.password = NULL;
2244 if (volume_info.username)
2245 strncpy(pSesInfo->userName, volume_info.username,
2246 MAX_USERNAME_SIZE);
2247 if (volume_info.domainname) {
2248 int len = strlen(volume_info.domainname);
2249 pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL);
2250 if (pSesInfo->domainName)
2251 strcpy(pSesInfo->domainName,
2252 volume_info.domainname);
2254 pSesInfo->linux_uid = volume_info.linux_uid;
2255 pSesInfo->overrideSecFlg = volume_info.secFlg;
2256 down(&pSesInfo->sesSem);
2258 /* BB FIXME need to pass vol->secFlgs BB */
2259 rc = cifs_setup_session(xid, pSesInfo,
2260 cifs_sb->local_nls);
2261 up(&pSesInfo->sesSem);
2264 /* search for existing tcon to this server share */
2265 if (!rc) {
2266 setup_cifs_sb(&volume_info, cifs_sb);
2268 tcon = cifs_find_tcon(pSesInfo, volume_info.UNC);
2269 if (tcon) {
2270 cFYI(1, ("Found match on UNC path"));
2271 /* existing tcon already has a reference */
2272 cifs_put_smb_ses(pSesInfo);
2273 if (tcon->seal != volume_info.seal)
2274 cERROR(1, ("transport encryption setting "
2275 "conflicts with existing tid"));
2276 } else {
2277 tcon = tconInfoAlloc();
2278 if (tcon == NULL) {
2279 rc = -ENOMEM;
2280 goto mount_fail_check;
2282 tcon->ses = pSesInfo;
2284 /* check for null share name ie connect to dfs root */
2285 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
2286 && (strchr(volume_info.UNC + 3, '/') == NULL)) {
2287 /* rc = connect_to_dfs_path(...) */
2288 cFYI(1, ("DFS root not supported"));
2289 rc = -ENODEV;
2290 goto mount_fail_check;
2291 } else {
2292 /* BB Do we need to wrap sesSem around
2293 * this TCon call and Unix SetFS as
2294 * we do on SessSetup and reconnect? */
2295 rc = CIFSTCon(xid, pSesInfo, volume_info.UNC,
2296 tcon, cifs_sb->local_nls);
2297 cFYI(1, ("CIFS Tcon rc = %d", rc));
2298 if (volume_info.nodfs) {
2299 tcon->Flags &= ~SMB_SHARE_IS_IN_DFS;
2300 cFYI(1, ("DFS disabled (%d)",
2301 tcon->Flags));
2304 if (rc)
2305 goto mount_fail_check;
2306 tcon->seal = volume_info.seal;
2307 write_lock(&cifs_tcp_ses_lock);
2308 list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
2309 write_unlock(&cifs_tcp_ses_lock);
2312 /* we can have only one retry value for a connection
2313 to a share so for resources mounted more than once
2314 to the same server share the last value passed in
2315 for the retry flag is used */
2316 tcon->retry = volume_info.retry;
2317 tcon->nocase = volume_info.nocase;
2318 tcon->local_lease = volume_info.local_lease;
2320 if (pSesInfo) {
2321 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
2322 sb->s_maxbytes = (u64) 1 << 63;
2323 } else
2324 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
2327 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
2328 sb->s_time_gran = 100;
2330 mount_fail_check:
2331 /* on error free sesinfo and tcon struct if needed */
2332 if (rc) {
2333 /* If find_unc succeeded then rc == 0 so we can not end */
2334 /* up accidently freeing someone elses tcon struct */
2335 if (tcon)
2336 cifs_put_tcon(tcon);
2337 else if (pSesInfo)
2338 cifs_put_smb_ses(pSesInfo);
2339 else
2340 cifs_put_tcp_session(srvTcp);
2341 goto out;
2343 cifs_sb->tcon = tcon;
2345 /* do not care if following two calls succeed - informational */
2346 if (!tcon->ipc) {
2347 CIFSSMBQFSDeviceInfo(xid, tcon);
2348 CIFSSMBQFSAttributeInfo(xid, tcon);
2351 /* tell server which Unix caps we support */
2352 if (tcon->ses->capabilities & CAP_UNIX)
2353 /* reset of caps checks mount to see if unix extensions
2354 disabled for just this mount */
2355 reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
2356 else
2357 tcon->unix_ext = 0; /* server does not support them */
2359 /* convert forward to back slashes in prepath here if needed */
2360 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
2361 convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
2363 if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
2364 cifs_sb->rsize = 1024 * 127;
2365 cFYI(DBG2, ("no very large read support, rsize now 127K"));
2367 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
2368 cifs_sb->wsize = min(cifs_sb->wsize,
2369 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
2370 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
2371 cifs_sb->rsize = min(cifs_sb->rsize,
2372 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
2374 /* volume_info.password is freed above when existing session found
2375 (in which case it is not needed anymore) but when new sesion is created
2376 the password ptr is put in the new session structure (in which case the
2377 password will be freed at unmount time) */
2378 out:
2379 /* zero out password before freeing */
2380 if (volume_info.password != NULL) {
2381 memset(volume_info.password, 0, strlen(volume_info.password));
2382 kfree(volume_info.password);
2384 kfree(volume_info.UNC);
2385 kfree(volume_info.prepath);
2386 FreeXid(xid);
2387 return rc;
2390 static int
2391 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2392 char session_key[CIFS_SESS_KEY_SIZE],
2393 const struct nls_table *nls_codepage)
2395 struct smb_hdr *smb_buffer;
2396 struct smb_hdr *smb_buffer_response;
2397 SESSION_SETUP_ANDX *pSMB;
2398 SESSION_SETUP_ANDX *pSMBr;
2399 char *bcc_ptr;
2400 char *user;
2401 char *domain;
2402 int rc = 0;
2403 int remaining_words = 0;
2404 int bytes_returned = 0;
2405 int len;
2406 __u32 capabilities;
2407 __u16 count;
2409 cFYI(1, ("In sesssetup"));
2410 if (ses == NULL)
2411 return -EINVAL;
2412 user = ses->userName;
2413 domain = ses->domainName;
2414 smb_buffer = cifs_buf_get();
2416 if (smb_buffer == NULL)
2417 return -ENOMEM;
2419 smb_buffer_response = smb_buffer;
2420 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2422 /* send SMBsessionSetup here */
2423 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2424 NULL /* no tCon exists yet */ , 13 /* wct */ );
2426 smb_buffer->Mid = GetNextMid(ses->server);
2427 pSMB->req_no_secext.AndXCommand = 0xFF;
2428 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2429 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2431 if (ses->server->secMode &
2432 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2433 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2435 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2436 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
2437 if (ses->capabilities & CAP_UNICODE) {
2438 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2439 capabilities |= CAP_UNICODE;
2441 if (ses->capabilities & CAP_STATUS32) {
2442 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2443 capabilities |= CAP_STATUS32;
2445 if (ses->capabilities & CAP_DFS) {
2446 smb_buffer->Flags2 |= SMBFLG2_DFS;
2447 capabilities |= CAP_DFS;
2449 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2451 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2452 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2454 pSMB->req_no_secext.CaseSensitivePasswordLength =
2455 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2456 bcc_ptr = pByteArea(smb_buffer);
2457 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2458 bcc_ptr += CIFS_SESS_KEY_SIZE;
2459 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2460 bcc_ptr += CIFS_SESS_KEY_SIZE;
2462 if (ses->capabilities & CAP_UNICODE) {
2463 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
2464 *bcc_ptr = 0;
2465 bcc_ptr++;
2467 if (user == NULL)
2468 bytes_returned = 0; /* skip null user */
2469 else
2470 bytes_returned =
2471 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
2472 nls_codepage);
2473 /* convert number of 16 bit words to bytes */
2474 bcc_ptr += 2 * bytes_returned;
2475 bcc_ptr += 2; /* trailing null */
2476 if (domain == NULL)
2477 bytes_returned =
2478 cifs_strtoUCS((__le16 *) bcc_ptr,
2479 "CIFS_LINUX_DOM", 32, nls_codepage);
2480 else
2481 bytes_returned =
2482 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2483 nls_codepage);
2484 bcc_ptr += 2 * bytes_returned;
2485 bcc_ptr += 2;
2486 bytes_returned =
2487 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2488 32, nls_codepage);
2489 bcc_ptr += 2 * bytes_returned;
2490 bytes_returned =
2491 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release,
2492 32, nls_codepage);
2493 bcc_ptr += 2 * bytes_returned;
2494 bcc_ptr += 2;
2495 bytes_returned =
2496 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2497 64, nls_codepage);
2498 bcc_ptr += 2 * bytes_returned;
2499 bcc_ptr += 2;
2500 } else {
2501 if (user != NULL) {
2502 strncpy(bcc_ptr, user, 200);
2503 bcc_ptr += strnlen(user, 200);
2505 *bcc_ptr = 0;
2506 bcc_ptr++;
2507 if (domain == NULL) {
2508 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2509 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2510 } else {
2511 strncpy(bcc_ptr, domain, 64);
2512 bcc_ptr += strnlen(domain, 64);
2513 *bcc_ptr = 0;
2514 bcc_ptr++;
2516 strcpy(bcc_ptr, "Linux version ");
2517 bcc_ptr += strlen("Linux version ");
2518 strcpy(bcc_ptr, utsname()->release);
2519 bcc_ptr += strlen(utsname()->release) + 1;
2520 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2521 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2523 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2524 smb_buffer->smb_buf_length += count;
2525 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2527 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2528 &bytes_returned, CIFS_LONG_OP);
2529 if (rc) {
2530 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2531 } else if ((smb_buffer_response->WordCount == 3)
2532 || (smb_buffer_response->WordCount == 4)) {
2533 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2534 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2535 if (action & GUEST_LOGIN)
2536 cFYI(1, (" Guest login")); /* BB mark SesInfo struct? */
2537 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format
2538 (little endian) */
2539 cFYI(1, ("UID = %d ", ses->Suid));
2540 /* response can have either 3 or 4 word count - Samba sends 3 */
2541 bcc_ptr = pByteArea(smb_buffer_response);
2542 if ((pSMBr->resp.hdr.WordCount == 3)
2543 || ((pSMBr->resp.hdr.WordCount == 4)
2544 && (blob_len < pSMBr->resp.ByteCount))) {
2545 if (pSMBr->resp.hdr.WordCount == 4)
2546 bcc_ptr += blob_len;
2548 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2549 if ((long) (bcc_ptr) % 2) {
2550 remaining_words =
2551 (BCC(smb_buffer_response) - 1) / 2;
2552 /* Unicode strings must be word
2553 aligned */
2554 bcc_ptr++;
2555 } else {
2556 remaining_words =
2557 BCC(smb_buffer_response) / 2;
2559 len =
2560 UniStrnlen((wchar_t *) bcc_ptr,
2561 remaining_words - 1);
2562 /* We look for obvious messed up bcc or strings in response so we do not go off
2563 the end since (at least) WIN2K and Windows XP have a major bug in not null
2564 terminating last Unicode string in response */
2565 if (ses->serverOS)
2566 kfree(ses->serverOS);
2567 ses->serverOS = kzalloc(2 * (len + 1),
2568 GFP_KERNEL);
2569 if (ses->serverOS == NULL)
2570 goto sesssetup_nomem;
2571 cifs_strfromUCS_le(ses->serverOS,
2572 (__le16 *)bcc_ptr,
2573 len, nls_codepage);
2574 bcc_ptr += 2 * (len + 1);
2575 remaining_words -= len + 1;
2576 ses->serverOS[2 * len] = 0;
2577 ses->serverOS[1 + (2 * len)] = 0;
2578 if (remaining_words > 0) {
2579 len = UniStrnlen((wchar_t *)bcc_ptr,
2580 remaining_words-1);
2581 kfree(ses->serverNOS);
2582 ses->serverNOS = kzalloc(2 * (len + 1),
2583 GFP_KERNEL);
2584 if (ses->serverNOS == NULL)
2585 goto sesssetup_nomem;
2586 cifs_strfromUCS_le(ses->serverNOS,
2587 (__le16 *)bcc_ptr,
2588 len, nls_codepage);
2589 bcc_ptr += 2 * (len + 1);
2590 ses->serverNOS[2 * len] = 0;
2591 ses->serverNOS[1 + (2 * len)] = 0;
2592 if (strncmp(ses->serverNOS,
2593 "NT LAN Manager 4", 16) == 0) {
2594 cFYI(1, ("NT4 server"));
2595 ses->flags |= CIFS_SES_NT4;
2597 remaining_words -= len + 1;
2598 if (remaining_words > 0) {
2599 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2600 /* last string is not always null terminated
2601 (for e.g. for Windows XP & 2000) */
2602 if (ses->serverDomain)
2603 kfree(ses->serverDomain);
2604 ses->serverDomain =
2605 kzalloc(2*(len+1),
2606 GFP_KERNEL);
2607 if (ses->serverDomain == NULL)
2608 goto sesssetup_nomem;
2609 cifs_strfromUCS_le(ses->serverDomain,
2610 (__le16 *)bcc_ptr,
2611 len, nls_codepage);
2612 bcc_ptr += 2 * (len + 1);
2613 ses->serverDomain[2*len] = 0;
2614 ses->serverDomain[1+(2*len)] = 0;
2615 } else { /* else no more room so create
2616 dummy domain string */
2617 if (ses->serverDomain)
2618 kfree(ses->serverDomain);
2619 ses->serverDomain =
2620 kzalloc(2, GFP_KERNEL);
2622 } else { /* no room so create dummy domain
2623 and NOS string */
2625 /* if these kcallocs fail not much we
2626 can do, but better to not fail the
2627 sesssetup itself */
2628 kfree(ses->serverDomain);
2629 ses->serverDomain =
2630 kzalloc(2, GFP_KERNEL);
2631 kfree(ses->serverNOS);
2632 ses->serverNOS =
2633 kzalloc(2, GFP_KERNEL);
2635 } else { /* ASCII */
2636 len = strnlen(bcc_ptr, 1024);
2637 if (((long) bcc_ptr + len) - (long)
2638 pByteArea(smb_buffer_response)
2639 <= BCC(smb_buffer_response)) {
2640 kfree(ses->serverOS);
2641 ses->serverOS = kzalloc(len + 1,
2642 GFP_KERNEL);
2643 if (ses->serverOS == NULL)
2644 goto sesssetup_nomem;
2645 strncpy(ses->serverOS, bcc_ptr, len);
2647 bcc_ptr += len;
2648 /* null terminate the string */
2649 bcc_ptr[0] = 0;
2650 bcc_ptr++;
2652 len = strnlen(bcc_ptr, 1024);
2653 kfree(ses->serverNOS);
2654 ses->serverNOS = kzalloc(len + 1,
2655 GFP_KERNEL);
2656 if (ses->serverNOS == NULL)
2657 goto sesssetup_nomem;
2658 strncpy(ses->serverNOS, bcc_ptr, len);
2659 bcc_ptr += len;
2660 bcc_ptr[0] = 0;
2661 bcc_ptr++;
2663 len = strnlen(bcc_ptr, 1024);
2664 if (ses->serverDomain)
2665 kfree(ses->serverDomain);
2666 ses->serverDomain = kzalloc(len + 1,
2667 GFP_KERNEL);
2668 if (ses->serverDomain == NULL)
2669 goto sesssetup_nomem;
2670 strncpy(ses->serverDomain, bcc_ptr,
2671 len);
2672 bcc_ptr += len;
2673 bcc_ptr[0] = 0;
2674 bcc_ptr++;
2675 } else
2676 cFYI(1,
2677 ("Variable field of length %d "
2678 "extends beyond end of smb ",
2679 len));
2681 } else {
2682 cERROR(1,
2683 (" Security Blob Length extends beyond "
2684 "end of SMB"));
2686 } else {
2687 cERROR(1,
2688 (" Invalid Word count %d: ",
2689 smb_buffer_response->WordCount));
2690 rc = -EIO;
2692 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2693 since that could make reconnection harder, and
2694 reconnection might be needed to free memory */
2695 cifs_buf_release(smb_buffer);
2697 return rc;
2700 static int
2701 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2702 struct cifsSesInfo *ses, bool *pNTLMv2_flag,
2703 const struct nls_table *nls_codepage)
2705 struct smb_hdr *smb_buffer;
2706 struct smb_hdr *smb_buffer_response;
2707 SESSION_SETUP_ANDX *pSMB;
2708 SESSION_SETUP_ANDX *pSMBr;
2709 char *bcc_ptr;
2710 char *domain;
2711 int rc = 0;
2712 int remaining_words = 0;
2713 int bytes_returned = 0;
2714 int len;
2715 int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
2716 PNEGOTIATE_MESSAGE SecurityBlob;
2717 PCHALLENGE_MESSAGE SecurityBlob2;
2718 __u32 negotiate_flags, capabilities;
2719 __u16 count;
2721 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
2722 if (ses == NULL)
2723 return -EINVAL;
2724 domain = ses->domainName;
2725 *pNTLMv2_flag = false;
2726 smb_buffer = cifs_buf_get();
2727 if (smb_buffer == NULL) {
2728 return -ENOMEM;
2730 smb_buffer_response = smb_buffer;
2731 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2732 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2734 /* send SMBsessionSetup here */
2735 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2736 NULL /* no tCon exists yet */ , 12 /* wct */ );
2738 smb_buffer->Mid = GetNextMid(ses->server);
2739 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2740 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2742 pSMB->req.AndXCommand = 0xFF;
2743 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2744 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2746 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2747 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2749 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2750 CAP_EXTENDED_SECURITY;
2751 if (ses->capabilities & CAP_UNICODE) {
2752 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2753 capabilities |= CAP_UNICODE;
2755 if (ses->capabilities & CAP_STATUS32) {
2756 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2757 capabilities |= CAP_STATUS32;
2759 if (ses->capabilities & CAP_DFS) {
2760 smb_buffer->Flags2 |= SMBFLG2_DFS;
2761 capabilities |= CAP_DFS;
2763 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2765 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2766 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2767 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2768 SecurityBlob->MessageType = NtLmNegotiate;
2769 negotiate_flags =
2770 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2771 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2772 NTLMSSP_NEGOTIATE_56 |
2773 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2774 if (sign_CIFS_PDUs)
2775 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2776 /* if (ntlmv2_support)
2777 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2778 /* setup pointers to domain name and workstation name */
2779 bcc_ptr += SecurityBlobLength;
2781 SecurityBlob->WorkstationName.Buffer = 0;
2782 SecurityBlob->WorkstationName.Length = 0;
2783 SecurityBlob->WorkstationName.MaximumLength = 0;
2785 /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2786 along with username on auth request (ie the response to challenge) */
2787 SecurityBlob->DomainName.Buffer = 0;
2788 SecurityBlob->DomainName.Length = 0;
2789 SecurityBlob->DomainName.MaximumLength = 0;
2790 if (ses->capabilities & CAP_UNICODE) {
2791 if ((long) bcc_ptr % 2) {
2792 *bcc_ptr = 0;
2793 bcc_ptr++;
2796 bytes_returned =
2797 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2798 32, nls_codepage);
2799 bcc_ptr += 2 * bytes_returned;
2800 bytes_returned =
2801 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
2802 nls_codepage);
2803 bcc_ptr += 2 * bytes_returned;
2804 bcc_ptr += 2; /* null terminate Linux version */
2805 bytes_returned =
2806 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2807 64, nls_codepage);
2808 bcc_ptr += 2 * bytes_returned;
2809 *(bcc_ptr + 1) = 0;
2810 *(bcc_ptr + 2) = 0;
2811 bcc_ptr += 2; /* null terminate network opsys string */
2812 *(bcc_ptr + 1) = 0;
2813 *(bcc_ptr + 2) = 0;
2814 bcc_ptr += 2; /* null domain */
2815 } else { /* ASCII */
2816 strcpy(bcc_ptr, "Linux version ");
2817 bcc_ptr += strlen("Linux version ");
2818 strcpy(bcc_ptr, utsname()->release);
2819 bcc_ptr += strlen(utsname()->release) + 1;
2820 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2821 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2822 bcc_ptr++; /* empty domain field */
2823 *bcc_ptr = 0;
2825 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2826 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2827 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2828 smb_buffer->smb_buf_length += count;
2829 pSMB->req.ByteCount = cpu_to_le16(count);
2831 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2832 &bytes_returned, CIFS_LONG_OP);
2834 if (smb_buffer_response->Status.CifsError ==
2835 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2836 rc = 0;
2838 if (rc) {
2839 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2840 } else if ((smb_buffer_response->WordCount == 3)
2841 || (smb_buffer_response->WordCount == 4)) {
2842 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2843 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2845 if (action & GUEST_LOGIN)
2846 cFYI(1, (" Guest login"));
2847 /* Do we want to set anything in SesInfo struct when guest login? */
2849 bcc_ptr = pByteArea(smb_buffer_response);
2850 /* response can have either 3 or 4 word count - Samba sends 3 */
2852 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2853 if (SecurityBlob2->MessageType != NtLmChallenge) {
2854 cFYI(1,
2855 ("Unexpected NTLMSSP message type received %d",
2856 SecurityBlob2->MessageType));
2857 } else if (ses) {
2858 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2859 cFYI(1, ("UID = %d", ses->Suid));
2860 if ((pSMBr->resp.hdr.WordCount == 3)
2861 || ((pSMBr->resp.hdr.WordCount == 4)
2862 && (blob_len <
2863 pSMBr->resp.ByteCount))) {
2865 if (pSMBr->resp.hdr.WordCount == 4) {
2866 bcc_ptr += blob_len;
2867 cFYI(1, ("Security Blob Length %d",
2868 blob_len));
2871 cFYI(1, ("NTLMSSP Challenge rcvd"));
2873 memcpy(ses->server->cryptKey,
2874 SecurityBlob2->Challenge,
2875 CIFS_CRYPTO_KEY_SIZE);
2876 if (SecurityBlob2->NegotiateFlags &
2877 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2878 *pNTLMv2_flag = true;
2880 if ((SecurityBlob2->NegotiateFlags &
2881 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2882 || (sign_CIFS_PDUs > 1))
2883 ses->server->secMode |=
2884 SECMODE_SIGN_REQUIRED;
2885 if ((SecurityBlob2->NegotiateFlags &
2886 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2887 ses->server->secMode |=
2888 SECMODE_SIGN_ENABLED;
2890 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2891 if ((long) (bcc_ptr) % 2) {
2892 remaining_words =
2893 (BCC(smb_buffer_response)
2894 - 1) / 2;
2895 /* Must word align unicode strings */
2896 bcc_ptr++;
2897 } else {
2898 remaining_words =
2900 (smb_buffer_response) / 2;
2902 len =
2903 UniStrnlen((wchar_t *) bcc_ptr,
2904 remaining_words - 1);
2905 /* We look for obvious messed up bcc or strings in response so we do not go off
2906 the end since (at least) WIN2K and Windows XP have a major bug in not null
2907 terminating last Unicode string in response */
2908 if (ses->serverOS)
2909 kfree(ses->serverOS);
2910 ses->serverOS =
2911 kzalloc(2 * (len + 1), GFP_KERNEL);
2912 cifs_strfromUCS_le(ses->serverOS,
2913 (__le16 *)
2914 bcc_ptr, len,
2915 nls_codepage);
2916 bcc_ptr += 2 * (len + 1);
2917 remaining_words -= len + 1;
2918 ses->serverOS[2 * len] = 0;
2919 ses->serverOS[1 + (2 * len)] = 0;
2920 if (remaining_words > 0) {
2921 len = UniStrnlen((wchar_t *)
2922 bcc_ptr,
2923 remaining_words
2924 - 1);
2925 kfree(ses->serverNOS);
2926 ses->serverNOS =
2927 kzalloc(2 * (len + 1),
2928 GFP_KERNEL);
2929 cifs_strfromUCS_le(ses->
2930 serverNOS,
2931 (__le16 *)
2932 bcc_ptr,
2933 len,
2934 nls_codepage);
2935 bcc_ptr += 2 * (len + 1);
2936 ses->serverNOS[2 * len] = 0;
2937 ses->serverNOS[1 +
2938 (2 * len)] = 0;
2939 remaining_words -= len + 1;
2940 if (remaining_words > 0) {
2941 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2942 /* last string not always null terminated
2943 (for e.g. for Windows XP & 2000) */
2944 kfree(ses->serverDomain);
2945 ses->serverDomain =
2946 kzalloc(2 *
2947 (len +
2949 GFP_KERNEL);
2950 cifs_strfromUCS_le
2951 (ses->serverDomain,
2952 (__le16 *)bcc_ptr,
2953 len, nls_codepage);
2954 bcc_ptr +=
2955 2 * (len + 1);
2956 ses->serverDomain[2*len]
2957 = 0;
2958 ses->serverDomain
2959 [1 + (2 * len)]
2960 = 0;
2961 } /* else no more room so create dummy domain string */
2962 else {
2963 kfree(ses->serverDomain);
2964 ses->serverDomain =
2965 kzalloc(2,
2966 GFP_KERNEL);
2968 } else { /* no room so create dummy domain and NOS string */
2969 kfree(ses->serverDomain);
2970 ses->serverDomain =
2971 kzalloc(2, GFP_KERNEL);
2972 kfree(ses->serverNOS);
2973 ses->serverNOS =
2974 kzalloc(2, GFP_KERNEL);
2976 } else { /* ASCII */
2977 len = strnlen(bcc_ptr, 1024);
2978 if (((long) bcc_ptr + len) - (long)
2979 pByteArea(smb_buffer_response)
2980 <= BCC(smb_buffer_response)) {
2981 if (ses->serverOS)
2982 kfree(ses->serverOS);
2983 ses->serverOS =
2984 kzalloc(len + 1,
2985 GFP_KERNEL);
2986 strncpy(ses->serverOS,
2987 bcc_ptr, len);
2989 bcc_ptr += len;
2990 bcc_ptr[0] = 0; /* null terminate string */
2991 bcc_ptr++;
2993 len = strnlen(bcc_ptr, 1024);
2994 kfree(ses->serverNOS);
2995 ses->serverNOS =
2996 kzalloc(len + 1,
2997 GFP_KERNEL);
2998 strncpy(ses->serverNOS, bcc_ptr, len);
2999 bcc_ptr += len;
3000 bcc_ptr[0] = 0;
3001 bcc_ptr++;
3003 len = strnlen(bcc_ptr, 1024);
3004 kfree(ses->serverDomain);
3005 ses->serverDomain =
3006 kzalloc(len + 1,
3007 GFP_KERNEL);
3008 strncpy(ses->serverDomain,
3009 bcc_ptr, len);
3010 bcc_ptr += len;
3011 bcc_ptr[0] = 0;
3012 bcc_ptr++;
3013 } else
3014 cFYI(1,
3015 ("field of length %d "
3016 "extends beyond end of smb",
3017 len));
3019 } else {
3020 cERROR(1, ("Security Blob Length extends beyond"
3021 " end of SMB"));
3023 } else {
3024 cERROR(1, ("No session structure passed in."));
3026 } else {
3027 cERROR(1,
3028 (" Invalid Word count %d:",
3029 smb_buffer_response->WordCount));
3030 rc = -EIO;
3033 cifs_buf_release(smb_buffer);
3035 return rc;
3037 static int
3038 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3039 char *ntlm_session_key, bool ntlmv2_flag,
3040 const struct nls_table *nls_codepage)
3042 struct smb_hdr *smb_buffer;
3043 struct smb_hdr *smb_buffer_response;
3044 SESSION_SETUP_ANDX *pSMB;
3045 SESSION_SETUP_ANDX *pSMBr;
3046 char *bcc_ptr;
3047 char *user;
3048 char *domain;
3049 int rc = 0;
3050 int remaining_words = 0;
3051 int bytes_returned = 0;
3052 int len;
3053 int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
3054 PAUTHENTICATE_MESSAGE SecurityBlob;
3055 __u32 negotiate_flags, capabilities;
3056 __u16 count;
3058 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
3059 if (ses == NULL)
3060 return -EINVAL;
3061 user = ses->userName;
3062 domain = ses->domainName;
3063 smb_buffer = cifs_buf_get();
3064 if (smb_buffer == NULL) {
3065 return -ENOMEM;
3067 smb_buffer_response = smb_buffer;
3068 pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
3069 pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
3071 /* send SMBsessionSetup here */
3072 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
3073 NULL /* no tCon exists yet */ , 12 /* wct */ );
3075 smb_buffer->Mid = GetNextMid(ses->server);
3076 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
3077 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
3078 pSMB->req.AndXCommand = 0xFF;
3079 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
3080 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
3082 pSMB->req.hdr.Uid = ses->Suid;
3084 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3085 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3087 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
3088 CAP_EXTENDED_SECURITY;
3089 if (ses->capabilities & CAP_UNICODE) {
3090 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3091 capabilities |= CAP_UNICODE;
3093 if (ses->capabilities & CAP_STATUS32) {
3094 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3095 capabilities |= CAP_STATUS32;
3097 if (ses->capabilities & CAP_DFS) {
3098 smb_buffer->Flags2 |= SMBFLG2_DFS;
3099 capabilities |= CAP_DFS;
3101 pSMB->req.Capabilities = cpu_to_le32(capabilities);
3103 bcc_ptr = (char *)&pSMB->req.SecurityBlob;
3104 SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
3105 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
3106 SecurityBlob->MessageType = NtLmAuthenticate;
3107 bcc_ptr += SecurityBlobLength;
3108 negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
3109 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
3110 0x80000000 | NTLMSSP_NEGOTIATE_128;
3111 if (sign_CIFS_PDUs)
3112 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
3113 if (ntlmv2_flag)
3114 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
3116 /* setup pointers to domain name and workstation name */
3118 SecurityBlob->WorkstationName.Buffer = 0;
3119 SecurityBlob->WorkstationName.Length = 0;
3120 SecurityBlob->WorkstationName.MaximumLength = 0;
3121 SecurityBlob->SessionKey.Length = 0;
3122 SecurityBlob->SessionKey.MaximumLength = 0;
3123 SecurityBlob->SessionKey.Buffer = 0;
3125 SecurityBlob->LmChallengeResponse.Length = 0;
3126 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
3127 SecurityBlob->LmChallengeResponse.Buffer = 0;
3129 SecurityBlob->NtChallengeResponse.Length =
3130 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3131 SecurityBlob->NtChallengeResponse.MaximumLength =
3132 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3133 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
3134 SecurityBlob->NtChallengeResponse.Buffer =
3135 cpu_to_le32(SecurityBlobLength);
3136 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
3137 bcc_ptr += CIFS_SESS_KEY_SIZE;
3139 if (ses->capabilities & CAP_UNICODE) {
3140 if (domain == NULL) {
3141 SecurityBlob->DomainName.Buffer = 0;
3142 SecurityBlob->DomainName.Length = 0;
3143 SecurityBlob->DomainName.MaximumLength = 0;
3144 } else {
3145 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
3146 nls_codepage);
3147 ln *= 2;
3148 SecurityBlob->DomainName.MaximumLength =
3149 cpu_to_le16(ln);
3150 SecurityBlob->DomainName.Buffer =
3151 cpu_to_le32(SecurityBlobLength);
3152 bcc_ptr += ln;
3153 SecurityBlobLength += ln;
3154 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3156 if (user == NULL) {
3157 SecurityBlob->UserName.Buffer = 0;
3158 SecurityBlob->UserName.Length = 0;
3159 SecurityBlob->UserName.MaximumLength = 0;
3160 } else {
3161 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
3162 nls_codepage);
3163 ln *= 2;
3164 SecurityBlob->UserName.MaximumLength =
3165 cpu_to_le16(ln);
3166 SecurityBlob->UserName.Buffer =
3167 cpu_to_le32(SecurityBlobLength);
3168 bcc_ptr += ln;
3169 SecurityBlobLength += ln;
3170 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3173 /* SecurityBlob->WorkstationName.Length =
3174 cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
3175 SecurityBlob->WorkstationName.Length *= 2;
3176 SecurityBlob->WorkstationName.MaximumLength =
3177 cpu_to_le16(SecurityBlob->WorkstationName.Length);
3178 SecurityBlob->WorkstationName.Buffer =
3179 cpu_to_le32(SecurityBlobLength);
3180 bcc_ptr += SecurityBlob->WorkstationName.Length;
3181 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
3182 SecurityBlob->WorkstationName.Length =
3183 cpu_to_le16(SecurityBlob->WorkstationName.Length); */
3185 if ((long) bcc_ptr % 2) {
3186 *bcc_ptr = 0;
3187 bcc_ptr++;
3189 bytes_returned =
3190 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
3191 32, nls_codepage);
3192 bcc_ptr += 2 * bytes_returned;
3193 bytes_returned =
3194 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
3195 nls_codepage);
3196 bcc_ptr += 2 * bytes_returned;
3197 bcc_ptr += 2; /* null term version string */
3198 bytes_returned =
3199 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
3200 64, nls_codepage);
3201 bcc_ptr += 2 * bytes_returned;
3202 *(bcc_ptr + 1) = 0;
3203 *(bcc_ptr + 2) = 0;
3204 bcc_ptr += 2; /* null terminate network opsys string */
3205 *(bcc_ptr + 1) = 0;
3206 *(bcc_ptr + 2) = 0;
3207 bcc_ptr += 2; /* null domain */
3208 } else { /* ASCII */
3209 if (domain == NULL) {
3210 SecurityBlob->DomainName.Buffer = 0;
3211 SecurityBlob->DomainName.Length = 0;
3212 SecurityBlob->DomainName.MaximumLength = 0;
3213 } else {
3214 __u16 ln;
3215 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3216 strncpy(bcc_ptr, domain, 63);
3217 ln = strnlen(domain, 64);
3218 SecurityBlob->DomainName.MaximumLength =
3219 cpu_to_le16(ln);
3220 SecurityBlob->DomainName.Buffer =
3221 cpu_to_le32(SecurityBlobLength);
3222 bcc_ptr += ln;
3223 SecurityBlobLength += ln;
3224 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3226 if (user == NULL) {
3227 SecurityBlob->UserName.Buffer = 0;
3228 SecurityBlob->UserName.Length = 0;
3229 SecurityBlob->UserName.MaximumLength = 0;
3230 } else {
3231 __u16 ln;
3232 strncpy(bcc_ptr, user, 63);
3233 ln = strnlen(user, 64);
3234 SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
3235 SecurityBlob->UserName.Buffer =
3236 cpu_to_le32(SecurityBlobLength);
3237 bcc_ptr += ln;
3238 SecurityBlobLength += ln;
3239 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3241 /* BB fill in our workstation name if known BB */
3243 strcpy(bcc_ptr, "Linux version ");
3244 bcc_ptr += strlen("Linux version ");
3245 strcpy(bcc_ptr, utsname()->release);
3246 bcc_ptr += strlen(utsname()->release) + 1;
3247 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3248 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3249 bcc_ptr++; /* null domain */
3250 *bcc_ptr = 0;
3252 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3253 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3254 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3255 smb_buffer->smb_buf_length += count;
3256 pSMB->req.ByteCount = cpu_to_le16(count);
3258 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3259 &bytes_returned, CIFS_LONG_OP);
3260 if (rc) {
3261 /* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
3262 } else if ((smb_buffer_response->WordCount == 3) ||
3263 (smb_buffer_response->WordCount == 4)) {
3264 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3265 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3266 if (action & GUEST_LOGIN)
3267 cFYI(1, (" Guest login")); /* BB Should we set anything
3268 in SesInfo struct ? */
3269 /* if (SecurityBlob2->MessageType != NtLm??) {
3270 cFYI("Unexpected message type on auth response is %d"));
3271 } */
3273 if (ses) {
3274 cFYI(1,
3275 ("Check challenge UID %d vs auth response UID %d",
3276 ses->Suid, smb_buffer_response->Uid));
3277 /* UID left in wire format */
3278 ses->Suid = smb_buffer_response->Uid;
3279 bcc_ptr = pByteArea(smb_buffer_response);
3280 /* response can have either 3 or 4 word count - Samba sends 3 */
3281 if ((pSMBr->resp.hdr.WordCount == 3)
3282 || ((pSMBr->resp.hdr.WordCount == 4)
3283 && (blob_len <
3284 pSMBr->resp.ByteCount))) {
3285 if (pSMBr->resp.hdr.WordCount == 4) {
3286 bcc_ptr +=
3287 blob_len;
3288 cFYI(1,
3289 ("Security Blob Length %d ",
3290 blob_len));
3293 cFYI(1,
3294 ("NTLMSSP response to Authenticate "));
3296 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3297 if ((long) (bcc_ptr) % 2) {
3298 remaining_words =
3299 (BCC(smb_buffer_response)
3300 - 1) / 2;
3301 bcc_ptr++; /* Unicode strings must be word aligned */
3302 } else {
3303 remaining_words = BCC(smb_buffer_response) / 2;
3305 len = UniStrnlen((wchar_t *) bcc_ptr,
3306 remaining_words - 1);
3307 /* We look for obvious messed up bcc or strings in response so we do not go off
3308 the end since (at least) WIN2K and Windows XP have a major bug in not null
3309 terminating last Unicode string in response */
3310 if (ses->serverOS)
3311 kfree(ses->serverOS);
3312 ses->serverOS =
3313 kzalloc(2 * (len + 1), GFP_KERNEL);
3314 cifs_strfromUCS_le(ses->serverOS,
3315 (__le16 *)
3316 bcc_ptr, len,
3317 nls_codepage);
3318 bcc_ptr += 2 * (len + 1);
3319 remaining_words -= len + 1;
3320 ses->serverOS[2 * len] = 0;
3321 ses->serverOS[1 + (2 * len)] = 0;
3322 if (remaining_words > 0) {
3323 len = UniStrnlen((wchar_t *)
3324 bcc_ptr,
3325 remaining_words
3326 - 1);
3327 kfree(ses->serverNOS);
3328 ses->serverNOS =
3329 kzalloc(2 * (len + 1),
3330 GFP_KERNEL);
3331 cifs_strfromUCS_le(ses->
3332 serverNOS,
3333 (__le16 *)
3334 bcc_ptr,
3335 len,
3336 nls_codepage);
3337 bcc_ptr += 2 * (len + 1);
3338 ses->serverNOS[2 * len] = 0;
3339 ses->serverNOS[1+(2*len)] = 0;
3340 remaining_words -= len + 1;
3341 if (remaining_words > 0) {
3342 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3343 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3344 if (ses->serverDomain)
3345 kfree(ses->serverDomain);
3346 ses->serverDomain =
3347 kzalloc(2 *
3348 (len +
3350 GFP_KERNEL);
3351 cifs_strfromUCS_le
3352 (ses->
3353 serverDomain,
3354 (__le16 *)
3355 bcc_ptr, len,
3356 nls_codepage);
3357 bcc_ptr +=
3358 2 * (len + 1);
3359 ses->
3360 serverDomain[2
3361 * len]
3362 = 0;
3363 ses->
3364 serverDomain[1
3368 len)]
3369 = 0;
3370 } /* else no more room so create dummy domain string */
3371 else {
3372 if (ses->serverDomain)
3373 kfree(ses->serverDomain);
3374 ses->serverDomain = kzalloc(2,GFP_KERNEL);
3376 } else { /* no room so create dummy domain and NOS string */
3377 if (ses->serverDomain)
3378 kfree(ses->serverDomain);
3379 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3380 kfree(ses->serverNOS);
3381 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3383 } else { /* ASCII */
3384 len = strnlen(bcc_ptr, 1024);
3385 if (((long) bcc_ptr + len) -
3386 (long) pByteArea(smb_buffer_response)
3387 <= BCC(smb_buffer_response)) {
3388 if (ses->serverOS)
3389 kfree(ses->serverOS);
3390 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
3391 strncpy(ses->serverOS,bcc_ptr, len);
3393 bcc_ptr += len;
3394 bcc_ptr[0] = 0; /* null terminate the string */
3395 bcc_ptr++;
3397 len = strnlen(bcc_ptr, 1024);
3398 kfree(ses->serverNOS);
3399 ses->serverNOS = kzalloc(len+1,
3400 GFP_KERNEL);
3401 strncpy(ses->serverNOS,
3402 bcc_ptr, len);
3403 bcc_ptr += len;
3404 bcc_ptr[0] = 0;
3405 bcc_ptr++;
3407 len = strnlen(bcc_ptr, 1024);
3408 if (ses->serverDomain)
3409 kfree(ses->serverDomain);
3410 ses->serverDomain =
3411 kzalloc(len+1,
3412 GFP_KERNEL);
3413 strncpy(ses->serverDomain,
3414 bcc_ptr, len);
3415 bcc_ptr += len;
3416 bcc_ptr[0] = 0;
3417 bcc_ptr++;
3418 } else
3419 cFYI(1, ("field of length %d "
3420 "extends beyond end of smb ",
3421 len));
3423 } else {
3424 cERROR(1, ("Security Blob extends beyond end "
3425 "of SMB"));
3427 } else {
3428 cERROR(1, ("No session structure passed in."));
3430 } else {
3431 cERROR(1, ("Invalid Word count %d: ",
3432 smb_buffer_response->WordCount));
3433 rc = -EIO;
3436 cifs_buf_release(smb_buffer);
3438 return rc;
3442 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3443 const char *tree, struct cifsTconInfo *tcon,
3444 const struct nls_table *nls_codepage)
3446 struct smb_hdr *smb_buffer;
3447 struct smb_hdr *smb_buffer_response;
3448 TCONX_REQ *pSMB;
3449 TCONX_RSP *pSMBr;
3450 unsigned char *bcc_ptr;
3451 int rc = 0;
3452 int length;
3453 __u16 count;
3455 if (ses == NULL)
3456 return -EIO;
3458 smb_buffer = cifs_buf_get();
3459 if (smb_buffer == NULL) {
3460 return -ENOMEM;
3462 smb_buffer_response = smb_buffer;
3464 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3465 NULL /*no tid */ , 4 /*wct */ );
3467 smb_buffer->Mid = GetNextMid(ses->server);
3468 smb_buffer->Uid = ses->Suid;
3469 pSMB = (TCONX_REQ *) smb_buffer;
3470 pSMBr = (TCONX_RSP *) smb_buffer_response;
3472 pSMB->AndXCommand = 0xFF;
3473 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3474 bcc_ptr = &pSMB->Password[0];
3475 if ((ses->server->secMode) & SECMODE_USER) {
3476 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3477 *bcc_ptr = 0; /* password is null byte */
3478 bcc_ptr++; /* skip password */
3479 /* already aligned so no need to do it below */
3480 } else {
3481 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
3482 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3483 specified as required (when that support is added to
3484 the vfs in the future) as only NTLM or the much
3485 weaker LANMAN (which we do not send by default) is accepted
3486 by Samba (not sure whether other servers allow
3487 NTLMv2 password here) */
3488 #ifdef CONFIG_CIFS_WEAK_PW_HASH
3489 if ((extended_security & CIFSSEC_MAY_LANMAN) &&
3490 (ses->server->secType == LANMAN))
3491 calc_lanman_hash(ses, bcc_ptr);
3492 else
3493 #endif /* CIFS_WEAK_PW_HASH */
3494 SMBNTencrypt(ses->password,
3495 ses->server->cryptKey,
3496 bcc_ptr);
3498 bcc_ptr += CIFS_SESS_KEY_SIZE;
3499 if (ses->capabilities & CAP_UNICODE) {
3500 /* must align unicode strings */
3501 *bcc_ptr = 0; /* null byte password */
3502 bcc_ptr++;
3506 if (ses->server->secMode &
3507 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3508 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3510 if (ses->capabilities & CAP_STATUS32) {
3511 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3513 if (ses->capabilities & CAP_DFS) {
3514 smb_buffer->Flags2 |= SMBFLG2_DFS;
3516 if (ses->capabilities & CAP_UNICODE) {
3517 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3518 length =
3519 cifs_strtoUCS((__le16 *) bcc_ptr, tree,
3520 6 /* max utf8 char length in bytes */ *
3521 (/* server len*/ + 256 /* share len */), nls_codepage);
3522 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
3523 bcc_ptr += 2; /* skip trailing null */
3524 } else { /* ASCII */
3525 strcpy(bcc_ptr, tree);
3526 bcc_ptr += strlen(tree) + 1;
3528 strcpy(bcc_ptr, "?????");
3529 bcc_ptr += strlen("?????");
3530 bcc_ptr += 1;
3531 count = bcc_ptr - &pSMB->Password[0];
3532 pSMB->hdr.smb_buf_length += count;
3533 pSMB->ByteCount = cpu_to_le16(count);
3535 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
3536 CIFS_STD_OP);
3538 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3539 /* above now done in SendReceive */
3540 if ((rc == 0) && (tcon != NULL)) {
3541 tcon->tidStatus = CifsGood;
3542 tcon->need_reconnect = false;
3543 tcon->tid = smb_buffer_response->Tid;
3544 bcc_ptr = pByteArea(smb_buffer_response);
3545 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3546 /* skip service field (NB: this field is always ASCII) */
3547 if (length == 3) {
3548 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3549 (bcc_ptr[2] == 'C')) {
3550 cFYI(1, ("IPC connection"));
3551 tcon->ipc = 1;
3553 } else if (length == 2) {
3554 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3555 /* the most common case */
3556 cFYI(1, ("disk share connection"));
3559 bcc_ptr += length + 1;
3560 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3561 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3562 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3563 if ((bcc_ptr + (2 * length)) -
3564 pByteArea(smb_buffer_response) <=
3565 BCC(smb_buffer_response)) {
3566 kfree(tcon->nativeFileSystem);
3567 tcon->nativeFileSystem =
3568 kzalloc(length + 2, GFP_KERNEL);
3569 if (tcon->nativeFileSystem)
3570 cifs_strfromUCS_le(
3571 tcon->nativeFileSystem,
3572 (__le16 *) bcc_ptr,
3573 length, nls_codepage);
3574 bcc_ptr += 2 * length;
3575 bcc_ptr[0] = 0; /* null terminate the string */
3576 bcc_ptr[1] = 0;
3577 bcc_ptr += 2;
3579 /* else do not bother copying these information fields*/
3580 } else {
3581 length = strnlen(bcc_ptr, 1024);
3582 if ((bcc_ptr + length) -
3583 pByteArea(smb_buffer_response) <=
3584 BCC(smb_buffer_response)) {
3585 kfree(tcon->nativeFileSystem);
3586 tcon->nativeFileSystem =
3587 kzalloc(length + 1, GFP_KERNEL);
3588 if (tcon->nativeFileSystem)
3589 strncpy(tcon->nativeFileSystem, bcc_ptr,
3590 length);
3592 /* else do not bother copying these information fields*/
3594 if ((smb_buffer_response->WordCount == 3) ||
3595 (smb_buffer_response->WordCount == 7))
3596 /* field is in same location */
3597 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3598 else
3599 tcon->Flags = 0;
3600 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3601 } else if ((rc == 0) && tcon == NULL) {
3602 /* all we need to save for IPC$ connection */
3603 ses->ipc_tid = smb_buffer_response->Tid;
3606 cifs_buf_release(smb_buffer);
3607 return rc;
3611 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3613 int rc = 0;
3614 char *tmp;
3616 if (cifs_sb->tcon)
3617 cifs_put_tcon(cifs_sb->tcon);
3619 cifs_sb->tcon = NULL;
3620 tmp = cifs_sb->prepath;
3621 cifs_sb->prepathlen = 0;
3622 cifs_sb->prepath = NULL;
3623 kfree(tmp);
3625 return rc;
3628 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3629 struct nls_table *nls_info)
3631 int rc = 0;
3632 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3633 bool ntlmv2_flag = false;
3634 int first_time = 0;
3635 struct TCP_Server_Info *server = pSesInfo->server;
3637 /* what if server changes its buffer size after dropping the session? */
3638 if (server->maxBuf == 0) /* no need to send on reconnect */ {
3639 rc = CIFSSMBNegotiate(xid, pSesInfo);
3640 if (rc == -EAGAIN) {
3641 /* retry only once on 1st time connection */
3642 rc = CIFSSMBNegotiate(xid, pSesInfo);
3643 if (rc == -EAGAIN)
3644 rc = -EHOSTDOWN;
3646 if (rc == 0) {
3647 spin_lock(&GlobalMid_Lock);
3648 if (server->tcpStatus != CifsExiting)
3649 server->tcpStatus = CifsGood;
3650 else
3651 rc = -EHOSTDOWN;
3652 spin_unlock(&GlobalMid_Lock);
3655 first_time = 1;
3658 if (rc)
3659 goto ss_err_exit;
3661 pSesInfo->flags = 0;
3662 pSesInfo->capabilities = server->capabilities;
3663 if (linuxExtEnabled == 0)
3664 pSesInfo->capabilities &= (~CAP_UNIX);
3665 /* pSesInfo->sequence_number = 0;*/
3666 cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
3667 server->secMode, server->capabilities, server->timeAdj));
3669 if (experimEnabled < 2)
3670 rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
3671 else if (extended_security
3672 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3673 && (server->secType == NTLMSSP)) {
3674 rc = -EOPNOTSUPP;
3675 } else if (extended_security
3676 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3677 && (server->secType == RawNTLMSSP)) {
3678 cFYI(1, ("NTLMSSP sesssetup"));
3679 rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag,
3680 nls_info);
3681 if (!rc) {
3682 if (ntlmv2_flag) {
3683 char *v2_response;
3684 cFYI(1, ("more secure NTLM ver2 hash"));
3685 if (CalcNTLMv2_partial_mac_key(pSesInfo,
3686 nls_info)) {
3687 rc = -ENOMEM;
3688 goto ss_err_exit;
3689 } else
3690 v2_response = kmalloc(16 + 64 /* blob*/,
3691 GFP_KERNEL);
3692 if (v2_response) {
3693 CalcNTLMv2_response(pSesInfo,
3694 v2_response);
3695 /* if (first_time)
3696 cifs_calculate_ntlmv2_mac_key */
3697 kfree(v2_response);
3698 /* BB Put dummy sig in SessSetup PDU? */
3699 } else {
3700 rc = -ENOMEM;
3701 goto ss_err_exit;
3704 } else {
3705 SMBNTencrypt(pSesInfo->password,
3706 server->cryptKey,
3707 ntlm_session_key);
3709 if (first_time)
3710 cifs_calculate_mac_key(
3711 &server->mac_signing_key,
3712 ntlm_session_key,
3713 pSesInfo->password);
3715 /* for better security the weaker lanman hash not sent
3716 in AuthSessSetup so we no longer calculate it */
3718 rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo,
3719 ntlm_session_key,
3720 ntlmv2_flag,
3721 nls_info);
3723 } else { /* old style NTLM 0.12 session setup */
3724 SMBNTencrypt(pSesInfo->password, server->cryptKey,
3725 ntlm_session_key);
3727 if (first_time)
3728 cifs_calculate_mac_key(&server->mac_signing_key,
3729 ntlm_session_key,
3730 pSesInfo->password);
3732 rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info);
3734 if (rc) {
3735 cERROR(1, ("Send error in SessSetup = %d", rc));
3736 } else {
3737 cFYI(1, ("CIFS Session Established successfully"));
3738 spin_lock(&GlobalMid_Lock);
3739 pSesInfo->status = CifsGood;
3740 pSesInfo->need_reconnect = false;
3741 spin_unlock(&GlobalMid_Lock);
3744 ss_err_exit:
3745 return rc;