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