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