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