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