[CIFS] Fix memory leak in statfs to very old servers
[linux-2.6-block.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
SF
675 /* buffer usuallly freed in free_mid - need to free it here on exit */
676 if (bigbuf != NULL)
677 cifs_buf_release(bigbuf);
678 if (smallbuf != NULL)
679 cifs_small_buf_release(smallbuf);
1da177e4
LT
680
681 read_lock(&GlobalSMBSeslock);
682 if (list_empty(&server->pending_mid_q)) {
09d1db5c
SF
683 /* loop through server session structures attached to this and
684 mark them dead */
1da177e4
LT
685 list_for_each(tmp, &GlobalSMBSessionList) {
686 ses =
687 list_entry(tmp, struct cifsSesInfo,
688 cifsSessionList);
689 if (ses->server == server) {
690 ses->status = CifsExiting;
691 ses->server = NULL;
692 }
693 }
694 read_unlock(&GlobalSMBSeslock);
695 } else {
31ca3bc3
SF
696 /* although we can not zero the server struct pointer yet,
697 since there are active requests which may depnd on them,
698 mark the corresponding SMB sessions as exiting too */
699 list_for_each(tmp, &GlobalSMBSessionList) {
700 ses = list_entry(tmp, struct cifsSesInfo,
701 cifsSessionList);
26f57364 702 if (ses->server == server)
31ca3bc3 703 ses->status = CifsExiting;
31ca3bc3
SF
704 }
705
1da177e4
LT
706 spin_lock(&GlobalMid_Lock);
707 list_for_each(tmp, &server->pending_mid_q) {
708 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
709 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
50c2f753
SF
710 cFYI(1, ("Clearing Mid 0x%x - waking up ",
711 mid_entry->mid));
1da177e4 712 task_to_wake = mid_entry->tsk;
26f57364 713 if (task_to_wake)
1da177e4 714 wake_up_process(task_to_wake);
1da177e4
LT
715 }
716 }
717 spin_unlock(&GlobalMid_Lock);
718 read_unlock(&GlobalSMBSeslock);
1da177e4 719 /* 1/8th of sec is more than enough time for them to exit */
b8643e1b 720 msleep(125);
1da177e4
LT
721 }
722
f191401f 723 if (!list_empty(&server->pending_mid_q)) {
50c2f753 724 /* mpx threads have not exited yet give them
1da177e4 725 at least the smb send timeout time for long ops */
31ca3bc3
SF
726 /* due to delays on oplock break requests, we need
727 to wait at least 45 seconds before giving up
728 on a request getting a response and going ahead
729 and killing cifsd */
1da177e4 730 cFYI(1, ("Wait for exit from demultiplex thread"));
31ca3bc3 731 msleep(46000);
1da177e4
LT
732 /* if threads still have not exited they are probably never
733 coming home not much else we can do but free the memory */
734 }
1da177e4
LT
735
736 write_lock(&GlobalSMBSeslock);
737 atomic_dec(&tcpSesAllocCount);
738 length = tcpSesAllocCount.counter;
31ca3bc3
SF
739
740 /* last chance to mark ses pointers invalid
741 if there are any pointing to this (e.g
50c2f753 742 if a crazy root user tried to kill cifsd
31ca3bc3
SF
743 kernel thread explicitly this might happen) */
744 list_for_each(tmp, &GlobalSMBSessionList) {
745 ses = list_entry(tmp, struct cifsSesInfo,
746 cifsSessionList);
26f57364 747 if (ses->server == server)
31ca3bc3 748 ses->server = NULL;
31ca3bc3 749 }
1da177e4 750 write_unlock(&GlobalSMBSeslock);
31ca3bc3
SF
751
752 kfree(server);
26f57364
SF
753 if (length > 0)
754 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
755 GFP_KERNEL);
50c2f753 756
1da177e4
LT
757 return 0;
758}
759
1da177e4 760static int
50c2f753
SF
761cifs_parse_mount_options(char *options, const char *devname,
762 struct smb_vol *vol)
1da177e4
LT
763{
764 char *value;
765 char *data;
766 unsigned int temp_len, i, j;
767 char separator[2];
768
769 separator[0] = ',';
50c2f753 770 separator[1] = 0;
1da177e4 771
12e36b2f 772 if (Local_System_Name[0] != 0)
50c2f753 773 memcpy(vol->source_rfc1001_name, Local_System_Name, 15);
2cd646a2 774 else {
12e36b2f 775 char *nodename = utsname()->nodename;
50c2f753
SF
776 int n = strnlen(nodename, 15);
777 memset(vol->source_rfc1001_name, 0x20, 15);
778 for (i = 0; i < n; i++) {
2cd646a2
SF
779 /* does not have to be perfect mapping since field is
780 informational, only used for servers that do not support
781 port 445 and it can be overridden at mount time */
12e36b2f 782 vol->source_rfc1001_name[i] = toupper(nodename[i]);
2cd646a2 783 }
1da177e4
LT
784 }
785 vol->source_rfc1001_name[15] = 0;
a10faeb2
SF
786 /* null target name indicates to use *SMBSERVR default called name
787 if we end up sending RFC1001 session initialize */
788 vol->target_rfc1001_name[0] = 0;
1da177e4
LT
789 vol->linux_uid = current->uid; /* current->euid instead? */
790 vol->linux_gid = current->gid;
791 vol->dir_mode = S_IRWXUGO;
792 /* 2767 perms indicate mandatory locking support */
793 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
794
795 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
796 vol->rw = TRUE;
ac67055e
JA
797 /* default is always to request posix paths. */
798 vol->posix_paths = 1;
799
1da177e4
LT
800 if (!options)
801 return 1;
802
50c2f753 803 if (strncmp(options, "sep=", 4) == 0) {
fb8c4b14 804 if (options[4] != 0) {
1da177e4
LT
805 separator[0] = options[4];
806 options += 5;
807 } else {
467a8f8d 808 cFYI(1, ("Null separator not allowed"));
1da177e4
LT
809 }
810 }
50c2f753 811
1da177e4
LT
812 while ((data = strsep(&options, separator)) != NULL) {
813 if (!*data)
814 continue;
815 if ((value = strchr(data, '=')) != NULL)
816 *value++ = '\0';
817
50c2f753
SF
818 /* Have to parse this before we parse for "user" */
819 if (strnicmp(data, "user_xattr", 10) == 0) {
1da177e4 820 vol->no_xattr = 0;
50c2f753 821 } else if (strnicmp(data, "nouser_xattr", 12) == 0) {
1da177e4
LT
822 vol->no_xattr = 1;
823 } else if (strnicmp(data, "user", 4) == 0) {
4b952a9b 824 if (!value) {
1da177e4
LT
825 printk(KERN_WARNING
826 "CIFS: invalid or missing username\n");
827 return 1; /* needs_arg; */
fb8c4b14 828 } else if (!*value) {
4b952a9b
SF
829 /* null user, ie anonymous, authentication */
830 vol->nullauth = 1;
1da177e4
LT
831 }
832 if (strnlen(value, 200) < 200) {
833 vol->username = value;
834 } else {
835 printk(KERN_WARNING "CIFS: username too long\n");
836 return 1;
837 }
838 } else if (strnicmp(data, "pass", 4) == 0) {
839 if (!value) {
840 vol->password = NULL;
841 continue;
fb8c4b14 842 } else if (value[0] == 0) {
1da177e4
LT
843 /* check if string begins with double comma
844 since that would mean the password really
845 does start with a comma, and would not
846 indicate an empty string */
fb8c4b14 847 if (value[1] != separator[0]) {
1da177e4
LT
848 vol->password = NULL;
849 continue;
850 }
851 }
852 temp_len = strlen(value);
853 /* removed password length check, NTLM passwords
854 can be arbitrarily long */
855
50c2f753 856 /* if comma in password, the string will be
1da177e4
LT
857 prematurely null terminated. Commas in password are
858 specified across the cifs mount interface by a double
859 comma ie ,, and a comma used as in other cases ie ','
860 as a parameter delimiter/separator is single and due
861 to the strsep above is temporarily zeroed. */
862
863 /* NB: password legally can have multiple commas and
864 the only illegal character in a password is null */
865
50c2f753 866 if ((value[temp_len] == 0) &&
09d1db5c 867 (value[temp_len+1] == separator[0])) {
1da177e4
LT
868 /* reinsert comma */
869 value[temp_len] = separator[0];
50c2f753
SF
870 temp_len += 2; /* move after second comma */
871 while (value[temp_len] != 0) {
1da177e4 872 if (value[temp_len] == separator[0]) {
50c2f753 873 if (value[temp_len+1] ==
09d1db5c
SF
874 separator[0]) {
875 /* skip second comma */
876 temp_len++;
50c2f753 877 } else {
1da177e4
LT
878 /* single comma indicating start
879 of next parm */
880 break;
881 }
882 }
883 temp_len++;
884 }
fb8c4b14 885 if (value[temp_len] == 0) {
1da177e4
LT
886 options = NULL;
887 } else {
888 value[temp_len] = 0;
889 /* point option to start of next parm */
890 options = value + temp_len + 1;
891 }
50c2f753 892 /* go from value to value + temp_len condensing
1da177e4
LT
893 double commas to singles. Note that this ends up
894 allocating a few bytes too many, which is ok */
e915fc49 895 vol->password = kzalloc(temp_len, GFP_KERNEL);
fb8c4b14 896 if (vol->password == NULL) {
50c2f753
SF
897 printk(KERN_WARNING "CIFS: no memory "
898 "for password\n");
433dc24f
SF
899 return 1;
900 }
50c2f753 901 for (i = 0, j = 0; i < temp_len; i++, j++) {
1da177e4 902 vol->password[j] = value[i];
fb8c4b14 903 if (value[i] == separator[0]
09d1db5c 904 && value[i+1] == separator[0]) {
1da177e4
LT
905 /* skip second comma */
906 i++;
907 }
908 }
909 vol->password[j] = 0;
910 } else {
e915fc49 911 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
fb8c4b14 912 if (vol->password == NULL) {
50c2f753
SF
913 printk(KERN_WARNING "CIFS: no memory "
914 "for password\n");
433dc24f
SF
915 return 1;
916 }
1da177e4
LT
917 strcpy(vol->password, value);
918 }
919 } else if (strnicmp(data, "ip", 2) == 0) {
920 if (!value || !*value) {
921 vol->UNCip = NULL;
922 } else if (strnlen(value, 35) < 35) {
923 vol->UNCip = value;
924 } else {
50c2f753
SF
925 printk(KERN_WARNING "CIFS: ip address "
926 "too long\n");
1da177e4
LT
927 return 1;
928 }
50c2f753
SF
929 } else if (strnicmp(data, "sec", 3) == 0) {
930 if (!value || !*value) {
931 cERROR(1, ("no security value specified"));
932 continue;
933 } else if (strnicmp(value, "krb5i", 5) == 0) {
934 vol->secFlg |= CIFSSEC_MAY_KRB5 |
189acaae 935 CIFSSEC_MUST_SIGN;
bf820679 936 } else if (strnicmp(value, "krb5p", 5) == 0) {
50c2f753
SF
937 /* vol->secFlg |= CIFSSEC_MUST_SEAL |
938 CIFSSEC_MAY_KRB5; */
939 cERROR(1, ("Krb5 cifs privacy not supported"));
bf820679
SF
940 return 1;
941 } else if (strnicmp(value, "krb5", 4) == 0) {
750d1151 942 vol->secFlg |= CIFSSEC_MAY_KRB5;
bf820679 943 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
750d1151 944 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
189acaae 945 CIFSSEC_MUST_SIGN;
bf820679 946 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
750d1151 947 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
bf820679 948 } else if (strnicmp(value, "ntlmi", 5) == 0) {
750d1151 949 vol->secFlg |= CIFSSEC_MAY_NTLM |
189acaae 950 CIFSSEC_MUST_SIGN;
bf820679
SF
951 } else if (strnicmp(value, "ntlm", 4) == 0) {
952 /* ntlm is default so can be turned off too */
750d1151 953 vol->secFlg |= CIFSSEC_MAY_NTLM;
bf820679 954 } else if (strnicmp(value, "nontlm", 6) == 0) {
189acaae 955 /* BB is there a better way to do this? */
750d1151 956 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
189acaae
SF
957#ifdef CONFIG_CIFS_WEAK_PW_HASH
958 } else if (strnicmp(value, "lanman", 6) == 0) {
50c2f753 959 vol->secFlg |= CIFSSEC_MAY_LANMAN;
189acaae 960#endif
bf820679 961 } else if (strnicmp(value, "none", 4) == 0) {
189acaae 962 vol->nullauth = 1;
50c2f753
SF
963 } else {
964 cERROR(1, ("bad security option: %s", value));
965 return 1;
966 }
1da177e4
LT
967 } else if ((strnicmp(data, "unc", 3) == 0)
968 || (strnicmp(data, "target", 6) == 0)
969 || (strnicmp(data, "path", 4) == 0)) {
970 if (!value || !*value) {
50c2f753
SF
971 printk(KERN_WARNING "CIFS: invalid path to "
972 "network resource\n");
1da177e4
LT
973 return 1; /* needs_arg; */
974 }
975 if ((temp_len = strnlen(value, 300)) < 300) {
50c2f753 976 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
4523cc30 977 if (vol->UNC == NULL)
1da177e4 978 return 1;
50c2f753 979 strcpy(vol->UNC, value);
1da177e4
LT
980 if (strncmp(vol->UNC, "//", 2) == 0) {
981 vol->UNC[0] = '\\';
982 vol->UNC[1] = '\\';
50c2f753 983 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1da177e4 984 printk(KERN_WARNING
50c2f753
SF
985 "CIFS: UNC Path does not begin "
986 "with // or \\\\ \n");
1da177e4
LT
987 return 1;
988 }
989 } else {
990 printk(KERN_WARNING "CIFS: UNC name too long\n");
991 return 1;
992 }
993 } else if ((strnicmp(data, "domain", 3) == 0)
994 || (strnicmp(data, "workgroup", 5) == 0)) {
995 if (!value || !*value) {
996 printk(KERN_WARNING "CIFS: invalid domain name\n");
997 return 1; /* needs_arg; */
998 }
999 /* BB are there cases in which a comma can be valid in
1000 a domain name and need special handling? */
3979877e 1001 if (strnlen(value, 256) < 256) {
1da177e4
LT
1002 vol->domainname = value;
1003 cFYI(1, ("Domain name set"));
1004 } else {
50c2f753
SF
1005 printk(KERN_WARNING "CIFS: domain name too "
1006 "long\n");
1da177e4
LT
1007 return 1;
1008 }
50c2f753
SF
1009 } else if (strnicmp(data, "prefixpath", 10) == 0) {
1010 if (!value || !*value) {
1011 printk(KERN_WARNING
1012 "CIFS: invalid path prefix\n");
1013 return 1; /* needs_argument */
1014 }
1015 if ((temp_len = strnlen(value, 1024)) < 1024) {
4523cc30 1016 if (value[0] != '/')
2fe87f02 1017 temp_len++; /* missing leading slash */
50c2f753
SF
1018 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1019 if (vol->prepath == NULL)
1020 return 1;
4523cc30 1021 if (value[0] != '/') {
2fe87f02 1022 vol->prepath[0] = '/';
50c2f753 1023 strcpy(vol->prepath+1, value);
2fe87f02 1024 } else
50c2f753
SF
1025 strcpy(vol->prepath, value);
1026 cFYI(1, ("prefix path %s", vol->prepath));
1027 } else {
1028 printk(KERN_WARNING "CIFS: prefix too long\n");
1029 return 1;
1030 }
1da177e4
LT
1031 } else if (strnicmp(data, "iocharset", 9) == 0) {
1032 if (!value || !*value) {
63135e08
SF
1033 printk(KERN_WARNING "CIFS: invalid iocharset "
1034 "specified\n");
1da177e4
LT
1035 return 1; /* needs_arg; */
1036 }
1037 if (strnlen(value, 65) < 65) {
50c2f753 1038 if (strnicmp(value, "default", 7))
1da177e4 1039 vol->iocharset = value;
50c2f753
SF
1040 /* if iocharset not set then load_nls_default
1041 is used by caller */
1042 cFYI(1, ("iocharset set to %s", value));
1da177e4 1043 } else {
63135e08
SF
1044 printk(KERN_WARNING "CIFS: iocharset name "
1045 "too long.\n");
1da177e4
LT
1046 return 1;
1047 }
1048 } else if (strnicmp(data, "uid", 3) == 0) {
1049 if (value && *value) {
1050 vol->linux_uid =
1051 simple_strtoul(value, &value, 0);
4523cc30 1052 vol->override_uid = 1;
1da177e4
LT
1053 }
1054 } else if (strnicmp(data, "gid", 3) == 0) {
1055 if (value && *value) {
1056 vol->linux_gid =
1057 simple_strtoul(value, &value, 0);
4523cc30 1058 vol->override_gid = 1;
1da177e4
LT
1059 }
1060 } else if (strnicmp(data, "file_mode", 4) == 0) {
1061 if (value && *value) {
1062 vol->file_mode =
1063 simple_strtoul(value, &value, 0);
1064 }
1065 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1066 if (value && *value) {
1067 vol->dir_mode =
1068 simple_strtoul(value, &value, 0);
1069 }
1070 } else if (strnicmp(data, "dirmode", 4) == 0) {
1071 if (value && *value) {
1072 vol->dir_mode =
1073 simple_strtoul(value, &value, 0);
1074 }
1075 } else if (strnicmp(data, "port", 4) == 0) {
1076 if (value && *value) {
1077 vol->port =
1078 simple_strtoul(value, &value, 0);
1079 }
1080 } else if (strnicmp(data, "rsize", 5) == 0) {
1081 if (value && *value) {
1082 vol->rsize =
1083 simple_strtoul(value, &value, 0);
1084 }
1085 } else if (strnicmp(data, "wsize", 5) == 0) {
1086 if (value && *value) {
1087 vol->wsize =
1088 simple_strtoul(value, &value, 0);
1089 }
1090 } else if (strnicmp(data, "sockopt", 5) == 0) {
1091 if (value && *value) {
1092 vol->sockopt =
1093 simple_strtoul(value, &value, 0);
1094 }
1095 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1096 if (!value || !*value || (*value == ' ')) {
63135e08 1097 cFYI(1, ("invalid (empty) netbiosname"));
1da177e4 1098 } else {
50c2f753
SF
1099 memset(vol->source_rfc1001_name, 0x20, 15);
1100 for (i = 0; i < 15; i++) {
1101 /* BB are there cases in which a comma can be
1da177e4
LT
1102 valid in this workstation netbios name (and need
1103 special handling)? */
1104
1105 /* We do not uppercase netbiosname for user */
50c2f753 1106 if (value[i] == 0)
1da177e4 1107 break;
50c2f753
SF
1108 else
1109 vol->source_rfc1001_name[i] =
1110 value[i];
1da177e4
LT
1111 }
1112 /* The string has 16th byte zero still from
1113 set at top of the function */
50c2f753
SF
1114 if ((i == 15) && (value[i] != 0))
1115 printk(KERN_WARNING "CIFS: netbiosname"
1116 " longer than 15 truncated.\n");
a10faeb2
SF
1117 }
1118 } else if (strnicmp(data, "servern", 7) == 0) {
1119 /* servernetbiosname specified override *SMBSERVER */
1120 if (!value || !*value || (*value == ' ')) {
467a8f8d 1121 cFYI(1, ("empty server netbiosname specified"));
a10faeb2
SF
1122 } else {
1123 /* last byte, type, is 0x20 for servr type */
50c2f753 1124 memset(vol->target_rfc1001_name, 0x20, 16);
a10faeb2 1125
50c2f753 1126 for (i = 0; i < 15; i++) {
a10faeb2 1127 /* BB are there cases in which a comma can be
50c2f753
SF
1128 valid in this workstation netbios name
1129 (and need special handling)? */
a10faeb2 1130
50c2f753
SF
1131 /* user or mount helper must uppercase
1132 the netbiosname */
1133 if (value[i] == 0)
a10faeb2
SF
1134 break;
1135 else
50c2f753
SF
1136 vol->target_rfc1001_name[i] =
1137 value[i];
a10faeb2
SF
1138 }
1139 /* The string has 16th byte zero still from
1140 set at top of the function */
50c2f753
SF
1141 if ((i == 15) && (value[i] != 0))
1142 printk(KERN_WARNING "CIFS: server net"
1143 "biosname longer than 15 truncated.\n");
1da177e4
LT
1144 }
1145 } else if (strnicmp(data, "credentials", 4) == 0) {
1146 /* ignore */
1147 } else if (strnicmp(data, "version", 3) == 0) {
1148 /* ignore */
50c2f753 1149 } else if (strnicmp(data, "guest", 5) == 0) {
1da177e4
LT
1150 /* ignore */
1151 } else if (strnicmp(data, "rw", 2) == 0) {
1152 vol->rw = TRUE;
1153 } else if ((strnicmp(data, "suid", 4) == 0) ||
1154 (strnicmp(data, "nosuid", 6) == 0) ||
1155 (strnicmp(data, "exec", 4) == 0) ||
1156 (strnicmp(data, "noexec", 6) == 0) ||
1157 (strnicmp(data, "nodev", 5) == 0) ||
1158 (strnicmp(data, "noauto", 6) == 0) ||
1159 (strnicmp(data, "dev", 3) == 0)) {
1160 /* The mount tool or mount.cifs helper (if present)
50c2f753
SF
1161 uses these opts to set flags, and the flags are read
1162 by the kernel vfs layer before we get here (ie
1163 before read super) so there is no point trying to
1164 parse these options again and set anything and it
1165 is ok to just ignore them */
1da177e4
LT
1166 continue;
1167 } else if (strnicmp(data, "ro", 2) == 0) {
1168 vol->rw = FALSE;
1169 } else if (strnicmp(data, "hard", 4) == 0) {
1170 vol->retry = 1;
1171 } else if (strnicmp(data, "soft", 4) == 0) {
1172 vol->retry = 0;
1173 } else if (strnicmp(data, "perm", 4) == 0) {
1174 vol->noperm = 0;
1175 } else if (strnicmp(data, "noperm", 6) == 0) {
1176 vol->noperm = 1;
6a0b4824
SF
1177 } else if (strnicmp(data, "mapchars", 8) == 0) {
1178 vol->remap = 1;
1179 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1180 vol->remap = 0;
50c2f753
SF
1181 } else if (strnicmp(data, "sfu", 3) == 0) {
1182 vol->sfu_emul = 1;
1183 } else if (strnicmp(data, "nosfu", 5) == 0) {
1184 vol->sfu_emul = 0;
ac67055e
JA
1185 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1186 vol->posix_paths = 1;
1187 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1188 vol->posix_paths = 0;
c18c842b
SF
1189 } else if (strnicmp(data, "nounix", 6) == 0) {
1190 vol->no_linux_ext = 1;
1191 } else if (strnicmp(data, "nolinux", 7) == 0) {
1192 vol->no_linux_ext = 1;
50c2f753 1193 } else if ((strnicmp(data, "nocase", 6) == 0) ||
a10faeb2 1194 (strnicmp(data, "ignorecase", 10) == 0)) {
50c2f753 1195 vol->nocase = 1;
c46fa8ac
SF
1196 } else if (strnicmp(data, "brl", 3) == 0) {
1197 vol->nobrl = 0;
50c2f753 1198 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1c955187 1199 (strnicmp(data, "nolock", 6) == 0)) {
c46fa8ac 1200 vol->nobrl = 1;
d3485d37
SF
1201 /* turn off mandatory locking in mode
1202 if remote locking is turned off since the
1203 local vfs will do advisory */
50c2f753
SF
1204 if (vol->file_mode ==
1205 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
d3485d37 1206 vol->file_mode = S_IALLUGO;
1da177e4
LT
1207 } else if (strnicmp(data, "setuids", 7) == 0) {
1208 vol->setuids = 1;
1209 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1210 vol->setuids = 0;
1211 } else if (strnicmp(data, "nohard", 6) == 0) {
1212 vol->retry = 0;
1213 } else if (strnicmp(data, "nosoft", 6) == 0) {
1214 vol->retry = 1;
1215 } else if (strnicmp(data, "nointr", 6) == 0) {
1216 vol->intr = 0;
1217 } else if (strnicmp(data, "intr", 4) == 0) {
1218 vol->intr = 1;
50c2f753 1219 } else if (strnicmp(data, "serverino", 7) == 0) {
1da177e4 1220 vol->server_ino = 1;
50c2f753 1221 } else if (strnicmp(data, "noserverino", 9) == 0) {
1da177e4 1222 vol->server_ino = 0;
50c2f753 1223 } else if (strnicmp(data, "cifsacl", 7) == 0) {
0a4b92c0
SF
1224 vol->cifs_acl = 1;
1225 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1226 vol->cifs_acl = 0;
50c2f753 1227 } else if (strnicmp(data, "acl", 3) == 0) {
1da177e4 1228 vol->no_psx_acl = 0;
50c2f753 1229 } else if (strnicmp(data, "noacl", 5) == 0) {
1da177e4 1230 vol->no_psx_acl = 1;
50c2f753 1231 } else if (strnicmp(data, "sign", 4) == 0) {
750d1151
SF
1232 vol->secFlg |= CIFSSEC_MUST_SIGN;
1233/* } else if (strnicmp(data, "seal",4) == 0) {
1234 vol->secFlg |= CIFSSEC_MUST_SEAL; */
50c2f753 1235 } else if (strnicmp(data, "direct", 6) == 0) {
1da177e4 1236 vol->direct_io = 1;
50c2f753 1237 } else if (strnicmp(data, "forcedirectio", 13) == 0) {
1da177e4 1238 vol->direct_io = 1;
50c2f753 1239 } else if (strnicmp(data, "in6_addr", 8) == 0) {
1da177e4
LT
1240 if (!value || !*value) {
1241 vol->in6_addr = NULL;
1242 } else if (strnlen(value, 49) == 48) {
1243 vol->in6_addr = value;
1244 } else {
50c2f753
SF
1245 printk(KERN_WARNING "CIFS: ip v6 address not "
1246 "48 characters long\n");
1da177e4
LT
1247 return 1;
1248 }
1249 } else if (strnicmp(data, "noac", 4) == 0) {
50c2f753
SF
1250 printk(KERN_WARNING "CIFS: Mount option noac not "
1251 "supported. Instead set "
1252 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
1da177e4 1253 } else
50c2f753
SF
1254 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
1255 data);
1da177e4
LT
1256 }
1257 if (vol->UNC == NULL) {
4523cc30 1258 if (devname == NULL) {
50c2f753
SF
1259 printk(KERN_WARNING "CIFS: Missing UNC name for mount "
1260 "target\n");
1da177e4
LT
1261 return 1;
1262 }
1263 if ((temp_len = strnlen(devname, 300)) < 300) {
50c2f753 1264 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
4523cc30 1265 if (vol->UNC == NULL)
1da177e4 1266 return 1;
50c2f753 1267 strcpy(vol->UNC, devname);
1da177e4
LT
1268 if (strncmp(vol->UNC, "//", 2) == 0) {
1269 vol->UNC[0] = '\\';
1270 vol->UNC[1] = '\\';
1271 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
50c2f753
SF
1272 printk(KERN_WARNING "CIFS: UNC Path does not "
1273 "begin with // or \\\\ \n");
1da177e4
LT
1274 return 1;
1275 }
1276 } else {
1277 printk(KERN_WARNING "CIFS: UNC name too long\n");
1278 return 1;
1279 }
1280 }
fb8c4b14 1281 if (vol->UNCip == NULL)
1da177e4
LT
1282 vol->UNCip = &vol->UNC[2];
1283
1284 return 0;
1285}
1286
1287static struct cifsSesInfo *
50c2f753 1288cifs_find_tcp_session(struct in_addr *target_ip_addr,
1da177e4
LT
1289 struct in6_addr *target_ip6_addr,
1290 char *userName, struct TCP_Server_Info **psrvTcp)
1291{
1292 struct list_head *tmp;
1293 struct cifsSesInfo *ses;
1294 *psrvTcp = NULL;
1295 read_lock(&GlobalSMBSeslock);
1296
1297 list_for_each(tmp, &GlobalSMBSessionList) {
1298 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1299 if (ses->server) {
50c2f753 1300 if ((target_ip_addr &&
1da177e4
LT
1301 (ses->server->addr.sockAddr.sin_addr.s_addr
1302 == target_ip_addr->s_addr)) || (target_ip6_addr
1303 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
50c2f753
SF
1304 target_ip6_addr, sizeof(*target_ip6_addr)))) {
1305 /* BB lock server and tcp session and increment
1306 use count here?? */
1307
1308 /* found a match on the TCP session */
1309 *psrvTcp = ses->server;
1310
1da177e4
LT
1311 /* BB check if reconnection needed */
1312 if (strncmp
1313 (ses->userName, userName,
1314 MAX_USERNAME_SIZE) == 0){
1315 read_unlock(&GlobalSMBSeslock);
50c2f753
SF
1316 /* Found exact match on both TCP and
1317 SMB sessions */
1318 return ses;
1da177e4
LT
1319 }
1320 }
1321 }
1322 /* else tcp and smb sessions need reconnection */
1323 }
1324 read_unlock(&GlobalSMBSeslock);
1325 return NULL;
1326}
1327
1328static struct cifsTconInfo *
1329find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1330{
1331 struct list_head *tmp;
1332 struct cifsTconInfo *tcon;
1333
1334 read_lock(&GlobalSMBSeslock);
1335 list_for_each(tmp, &GlobalTreeConnectionList) {
e466e487 1336 cFYI(1, ("Next tcon"));
1da177e4
LT
1337 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1338 if (tcon->ses) {
1339 if (tcon->ses->server) {
1340 cFYI(1,
e466e487 1341 ("old ip addr: %x == new ip %x ?",
1da177e4
LT
1342 tcon->ses->server->addr.sockAddr.sin_addr.
1343 s_addr, new_target_ip_addr));
1344 if (tcon->ses->server->addr.sockAddr.sin_addr.
1345 s_addr == new_target_ip_addr) {
e466e487 1346 /* BB lock tcon, server and tcp session and increment use count here? */
1da177e4
LT
1347 /* found a match on the TCP session */
1348 /* BB check if reconnection needed */
50c2f753
SF
1349 cFYI(1,
1350 ("IP match, old UNC: %s new: %s",
1da177e4
LT
1351 tcon->treeName, uncName));
1352 if (strncmp
1353 (tcon->treeName, uncName,
1354 MAX_TREE_SIZE) == 0) {
1355 cFYI(1,
e466e487 1356 ("and old usr: %s new: %s",
1da177e4
LT
1357 tcon->treeName, uncName));
1358 if (strncmp
1359 (tcon->ses->userName,
1360 userName,
1361 MAX_USERNAME_SIZE) == 0) {
1362 read_unlock(&GlobalSMBSeslock);
e466e487
SF
1363 /* matched smb session
1364 (user name */
1365 return tcon;
1da177e4
LT
1366 }
1367 }
1368 }
1369 }
1370 }
1371 }
1372 read_unlock(&GlobalSMBSeslock);
1373 return NULL;
1374}
1375
1376int
1377connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
737b758c
SF
1378 const char *old_path, const struct nls_table *nls_codepage,
1379 int remap)
1da177e4
LT
1380{
1381 unsigned char *referrals = NULL;
1382 unsigned int num_referrals;
1383 int rc = 0;
1384
50c2f753 1385 rc = get_dfs_path(xid, pSesInfo, old_path, nls_codepage,
737b758c 1386 &num_referrals, &referrals, remap);
1da177e4
LT
1387
1388 /* BB Add in code to: if valid refrl, if not ip address contact
50c2f753 1389 the helper that resolves tcp names, mount to it, try to
1da177e4
LT
1390 tcon to it unmount it if fail */
1391
f99d49ad 1392 kfree(referrals);
1da177e4
LT
1393
1394 return rc;
1395}
1396
1397int
50c2f753
SF
1398get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
1399 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
1400 unsigned char **preferrals, int remap)
1da177e4
LT
1401{
1402 char *temp_unc;
1403 int rc = 0;
1404
1405 *pnum_referrals = 0;
1406
1407 if (pSesInfo->ipc_tid == 0) {
1408 temp_unc = kmalloc(2 /* for slashes */ +
50c2f753
SF
1409 strnlen(pSesInfo->serverName,
1410 SERVER_NAME_LEN_WITH_NULL * 2)
1da177e4
LT
1411 + 1 + 4 /* slash IPC$ */ + 2,
1412 GFP_KERNEL);
1413 if (temp_unc == NULL)
1414 return -ENOMEM;
1415 temp_unc[0] = '\\';
1416 temp_unc[1] = '\\';
1417 strcpy(temp_unc + 2, pSesInfo->serverName);
1418 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1419 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1420 cFYI(1,
50c2f753 1421 ("CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid));
1da177e4
LT
1422 kfree(temp_unc);
1423 }
1424 if (rc == 0)
1425 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
737b758c 1426 pnum_referrals, nls_codepage, remap);
1da177e4
LT
1427
1428 return rc;
1429}
1430
1431/* See RFC1001 section 14 on representation of Netbios names */
50c2f753 1432static void rfc1002mangle(char *target, char *source, unsigned int length)
1da177e4 1433{
50c2f753 1434 unsigned int i, j;
1da177e4 1435
50c2f753 1436 for (i = 0, j = 0; i < (length); i++) {
1da177e4
LT
1437 /* mask a nibble at a time and encode */
1438 target[j] = 'A' + (0x0F & (source[i] >> 4));
1439 target[j+1] = 'A' + (0x0F & source[i]);
50c2f753 1440 j += 2;
1da177e4
LT
1441 }
1442
1443}
1444
1445
1446static int
50c2f753
SF
1447ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1448 char *netbios_name, char *target_name)
1da177e4
LT
1449{
1450 int rc = 0;
1451 int connected = 0;
1452 __be16 orig_port = 0;
1453
fb8c4b14 1454 if (*csocket == NULL) {
50c2f753
SF
1455 rc = sock_create_kern(PF_INET, SOCK_STREAM,
1456 IPPROTO_TCP, csocket);
1da177e4 1457 if (rc < 0) {
50c2f753 1458 cERROR(1, ("Error %d creating socket", rc));
1da177e4
LT
1459 *csocket = NULL;
1460 return rc;
1461 } else {
1462 /* BB other socket options to set KEEPALIVE, NODELAY? */
467a8f8d 1463 cFYI(1, ("Socket created"));
50c2f753 1464 (*csocket)->sk->sk_allocation = GFP_NOFS;
1da177e4
LT
1465 }
1466 }
1467
1468 psin_server->sin_family = AF_INET;
fb8c4b14 1469 if (psin_server->sin_port) { /* user overrode default port */
1da177e4
LT
1470 rc = (*csocket)->ops->connect(*csocket,
1471 (struct sockaddr *) psin_server,
50c2f753 1472 sizeof (struct sockaddr_in), 0);
1da177e4
LT
1473 if (rc >= 0)
1474 connected = 1;
50c2f753 1475 }
1da177e4 1476
fb8c4b14 1477 if (!connected) {
50c2f753 1478 /* save original port so we can retry user specified port
1da177e4
LT
1479 later if fall back ports fail this time */
1480 orig_port = psin_server->sin_port;
1481
1482 /* do not retry on the same port we just failed on */
fb8c4b14 1483 if (psin_server->sin_port != htons(CIFS_PORT)) {
1da177e4
LT
1484 psin_server->sin_port = htons(CIFS_PORT);
1485
1486 rc = (*csocket)->ops->connect(*csocket,
1487 (struct sockaddr *) psin_server,
50c2f753 1488 sizeof (struct sockaddr_in), 0);
1da177e4
LT
1489 if (rc >= 0)
1490 connected = 1;
1491 }
1492 }
1493 if (!connected) {
1494 psin_server->sin_port = htons(RFC1001_PORT);
1495 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
50c2f753
SF
1496 psin_server,
1497 sizeof (struct sockaddr_in), 0);
1498 if (rc >= 0)
1da177e4
LT
1499 connected = 1;
1500 }
1501
1502 /* give up here - unless we want to retry on different
1503 protocol families some day */
1504 if (!connected) {
fb8c4b14 1505 if (orig_port)
1da177e4 1506 psin_server->sin_port = orig_port;
50c2f753 1507 cFYI(1, ("Error %d connecting to server via ipv4", rc));
1da177e4
LT
1508 sock_release(*csocket);
1509 *csocket = NULL;
1510 return rc;
1511 }
50c2f753
SF
1512 /* Eventually check for other socket options to change from
1513 the default. sock_setsockopt not used because it expects
1da177e4 1514 user space buffer */
50c2f753
SF
1515 cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
1516 (*csocket)->sk->sk_sndbuf,
b387eaeb 1517 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1da177e4 1518 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
b387eaeb 1519 /* make the bufsizes depend on wsize/rsize and max requests */
fb8c4b14 1520 if ((*csocket)->sk->sk_sndbuf < (200 * 1024))
b387eaeb 1521 (*csocket)->sk->sk_sndbuf = 200 * 1024;
fb8c4b14 1522 if ((*csocket)->sk->sk_rcvbuf < (140 * 1024))
b387eaeb 1523 (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1da177e4
LT
1524
1525 /* send RFC1001 sessinit */
fb8c4b14 1526 if (psin_server->sin_port == htons(RFC1001_PORT)) {
1da177e4 1527 /* some servers require RFC1001 sessinit before sending
50c2f753 1528 negprot - BB check reconnection in case where second
1da177e4 1529 sessinit is sent but no second negprot */
50c2f753
SF
1530 struct rfc1002_session_packet *ses_init_buf;
1531 struct smb_hdr *smb_buf;
1532 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
1533 GFP_KERNEL);
fb8c4b14 1534 if (ses_init_buf) {
1da177e4 1535 ses_init_buf->trailer.session_req.called_len = 32;
fb8c4b14 1536 if (target_name && (target_name[0] != 0)) {
a10faeb2
SF
1537 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1538 target_name, 16);
1539 } else {
1540 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
50c2f753 1541 DEFAULT_CIFS_CALLED_NAME, 16);
a10faeb2
SF
1542 }
1543
1da177e4
LT
1544 ses_init_buf->trailer.session_req.calling_len = 32;
1545 /* calling name ends in null (byte 16) from old smb
1546 convention. */
50c2f753 1547 if (netbios_name && (netbios_name[0] != 0)) {
1da177e4 1548 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
50c2f753 1549 netbios_name, 16);
1da177e4
LT
1550 } else {
1551 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
50c2f753 1552 "LINUX_CIFS_CLNT", 16);
1da177e4
LT
1553 }
1554 ses_init_buf->trailer.session_req.scope1 = 0;
1555 ses_init_buf->trailer.session_req.scope2 = 0;
1556 smb_buf = (struct smb_hdr *)ses_init_buf;
1557 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1558 smb_buf->smb_buf_length = 0x81000044;
1559 rc = smb_send(*csocket, smb_buf, 0x44,
1560 (struct sockaddr *)psin_server);
1561 kfree(ses_init_buf);
50c2f753 1562 msleep(1); /* RFC1001 layer in at least one server
083d3a2c
SF
1563 requires very short break before negprot
1564 presumably because not expecting negprot
1565 to follow so fast. This is a simple
50c2f753 1566 solution that works without
083d3a2c
SF
1567 complicating the code and causes no
1568 significant slowing down on mount
1569 for everyone else */
1da177e4 1570 }
50c2f753 1571 /* else the negprot may still work without this
1da177e4 1572 even though malloc failed */
50c2f753 1573
1da177e4 1574 }
50c2f753 1575
1da177e4
LT
1576 return rc;
1577}
1578
1579static int
1580ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1581{
1582 int rc = 0;
1583 int connected = 0;
1584 __be16 orig_port = 0;
1585
fb8c4b14 1586 if (*csocket == NULL) {
50c2f753
SF
1587 rc = sock_create_kern(PF_INET6, SOCK_STREAM,
1588 IPPROTO_TCP, csocket);
1da177e4 1589 if (rc < 0) {
50c2f753 1590 cERROR(1, ("Error %d creating ipv6 socket", rc));
1da177e4
LT
1591 *csocket = NULL;
1592 return rc;
1593 } else {
1594 /* BB other socket options to set KEEPALIVE, NODELAY? */
fb8c4b14 1595 cFYI(1, ("ipv6 Socket created"));
1da177e4
LT
1596 (*csocket)->sk->sk_allocation = GFP_NOFS;
1597 }
1598 }
1599
1600 psin_server->sin6_family = AF_INET6;
1601
fb8c4b14 1602 if (psin_server->sin6_port) { /* user overrode default port */
1da177e4
LT
1603 rc = (*csocket)->ops->connect(*csocket,
1604 (struct sockaddr *) psin_server,
50c2f753 1605 sizeof (struct sockaddr_in6), 0);
1da177e4
LT
1606 if (rc >= 0)
1607 connected = 1;
50c2f753 1608 }
1da177e4 1609
fb8c4b14 1610 if (!connected) {
50c2f753 1611 /* save original port so we can retry user specified port
1da177e4
LT
1612 later if fall back ports fail this time */
1613
1614 orig_port = psin_server->sin6_port;
1615 /* do not retry on the same port we just failed on */
fb8c4b14 1616 if (psin_server->sin6_port != htons(CIFS_PORT)) {
1da177e4
LT
1617 psin_server->sin6_port = htons(CIFS_PORT);
1618
1619 rc = (*csocket)->ops->connect(*csocket,
1620 (struct sockaddr *) psin_server,
50c2f753 1621 sizeof (struct sockaddr_in6), 0);
1da177e4
LT
1622 if (rc >= 0)
1623 connected = 1;
1624 }
1625 }
1626 if (!connected) {
1627 psin_server->sin6_port = htons(RFC1001_PORT);
1628 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
50c2f753
SF
1629 psin_server, sizeof (struct sockaddr_in6), 0);
1630 if (rc >= 0)
1da177e4
LT
1631 connected = 1;
1632 }
1633
1634 /* give up here - unless we want to retry on different
1635 protocol families some day */
1636 if (!connected) {
fb8c4b14 1637 if (orig_port)
1da177e4 1638 psin_server->sin6_port = orig_port;
50c2f753 1639 cFYI(1, ("Error %d connecting to server via ipv6", rc));
1da177e4
LT
1640 sock_release(*csocket);
1641 *csocket = NULL;
1642 return rc;
1643 }
50c2f753
SF
1644 /* Eventually check for other socket options to change from
1645 the default. sock_setsockopt not used because it expects
1da177e4
LT
1646 user space buffer */
1647 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
50c2f753 1648
1da177e4
LT
1649 return rc;
1650}
1651
50c2f753
SF
1652void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
1653 struct super_block *sb, struct smb_vol *vol_info)
8af18971
SF
1654{
1655 /* if we are reconnecting then should we check to see if
1656 * any requested capabilities changed locally e.g. via
1657 * remount but we can not do much about it here
1658 * if they have (even if we could detect it by the following)
1659 * Perhaps we could add a backpointer to array of sb from tcon
1660 * or if we change to make all sb to same share the same
1661 * sb as NFS - then we only have one backpointer to sb.
1662 * What if we wanted to mount the server share twice once with
1663 * and once without posixacls or posix paths? */
1664 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
50c2f753 1665
c18c842b
SF
1666 if (vol_info && vol_info->no_linux_ext) {
1667 tcon->fsUnixInfo.Capability = 0;
1668 tcon->unix_ext = 0; /* Unix Extensions disabled */
1669 cFYI(1, ("Linux protocol extensions disabled"));
1670 return;
1671 } else if (vol_info)
1672 tcon->unix_ext = 1; /* Unix Extensions supported */
1673
1674 if (tcon->unix_ext == 0) {
1675 cFYI(1, ("Unix extensions disabled so not set on reconnect"));
1676 return;
1677 }
50c2f753 1678
fb8c4b14 1679 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
8af18971 1680 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
50c2f753 1681
8af18971
SF
1682 /* check for reconnect case in which we do not
1683 want to change the mount behavior if we can avoid it */
fb8c4b14 1684 if (vol_info == NULL) {
50c2f753 1685 /* turn off POSIX ACL and PATHNAMES if not set
8af18971
SF
1686 originally at mount time */
1687 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
1688 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1689 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
1690 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
8af18971 1691 }
50c2f753 1692
8af18971 1693 cap &= CIFS_UNIX_CAP_MASK;
75865f8c 1694 if (vol_info && vol_info->no_psx_acl)
8af18971 1695 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
75865f8c 1696 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
fb8c4b14
SF
1697 cFYI(1, ("negotiated posix acl support"));
1698 if (sb)
8af18971
SF
1699 sb->s_flags |= MS_POSIXACL;
1700 }
1701
75865f8c 1702 if (vol_info && vol_info->posix_paths == 0)
8af18971 1703 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
75865f8c 1704 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
fb8c4b14 1705 cFYI(1, ("negotiate posix pathnames"));
75865f8c 1706 if (sb)
50c2f753 1707 CIFS_SB(sb)->mnt_cifs_flags |=
8af18971
SF
1708 CIFS_MOUNT_POSIX_PATHS;
1709 }
50c2f753 1710
984acfe1
SF
1711 /* We might be setting the path sep back to a different
1712 form if we are reconnecting and the server switched its
50c2f753 1713 posix path capability for this share */
75865f8c 1714 if (sb && (CIFS_SB(sb)->prepathlen > 0))
984acfe1 1715 CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
75865f8c
SF
1716
1717 if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {
1718 if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
1719 CIFS_SB(sb)->rsize = 127 * 1024;
1720#ifdef CONFIG_CIFS_DEBUG2
fb8c4b14 1721 cFYI(1, ("larger reads not supported by srv"));
75865f8c
SF
1722#endif
1723 }
1724 }
50c2f753
SF
1725
1726
1727 cFYI(1, ("Negotiate caps 0x%x", (int)cap));
8af18971 1728#ifdef CONFIG_CIFS_DEBUG2
75865f8c 1729 if (cap & CIFS_UNIX_FCNTL_CAP)
fb8c4b14 1730 cFYI(1, ("FCNTL cap"));
75865f8c 1731 if (cap & CIFS_UNIX_EXTATTR_CAP)
fb8c4b14 1732 cFYI(1, ("EXTATTR cap"));
75865f8c 1733 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
fb8c4b14 1734 cFYI(1, ("POSIX path cap"));
75865f8c 1735 if (cap & CIFS_UNIX_XATTR_CAP)
fb8c4b14 1736 cFYI(1, ("XATTR cap"));
75865f8c 1737 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
fb8c4b14 1738 cFYI(1, ("POSIX ACL cap"));
75865f8c 1739 if (cap & CIFS_UNIX_LARGE_READ_CAP)
fb8c4b14 1740 cFYI(1, ("very large read cap"));
75865f8c 1741 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
fb8c4b14 1742 cFYI(1, ("very large write cap"));
8af18971
SF
1743#endif /* CIFS_DEBUG2 */
1744 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
442aa310 1745 if (vol_info == NULL) {
5a44b319 1746 cFYI(1, ("resetting capabilities failed"));
442aa310 1747 } else
5a44b319
SF
1748 cERROR(1, ("Negotiating Unix capabilities "
1749 "with the server failed. Consider "
1750 "mounting with the Unix Extensions\n"
1751 "disabled, if problems are found, "
1752 "by specifying the nounix mount "
2224f4e5 1753 "option."));
5a44b319 1754
8af18971
SF
1755 }
1756 }
1757}
1758
1da177e4
LT
1759int
1760cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1761 char *mount_data, const char *devname)
1762{
1763 int rc = 0;
1764 int xid;
1765 int address_type = AF_INET;
1766 struct socket *csocket = NULL;
1767 struct sockaddr_in sin_server;
1768 struct sockaddr_in6 sin_server6;
1769 struct smb_vol volume_info;
1770 struct cifsSesInfo *pSesInfo = NULL;
1771 struct cifsSesInfo *existingCifsSes = NULL;
1772 struct cifsTconInfo *tcon = NULL;
1773 struct TCP_Server_Info *srvTcp = NULL;
1774
1775 xid = GetXid();
1776
1777/* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
50c2f753
SF
1778
1779 memset(&volume_info, 0, sizeof(struct smb_vol));
1da177e4 1780 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
f99d49ad
JJ
1781 kfree(volume_info.UNC);
1782 kfree(volume_info.password);
2fe87f02 1783 kfree(volume_info.prepath);
1da177e4
LT
1784 FreeXid(xid);
1785 return -EINVAL;
1786 }
1787
8426c39c 1788 if (volume_info.nullauth) {
fb8c4b14 1789 cFYI(1, ("null user"));
8426c39c
JL
1790 volume_info.username = NULL;
1791 } else if (volume_info.username) {
1da177e4 1792 /* BB fixme parse for domain name here */
467a8f8d 1793 cFYI(1, ("Username: %s", volume_info.username));
1da177e4 1794 } else {
bf820679 1795 cifserror("No username specified");
50c2f753
SF
1796 /* In userspace mount helper we can get user name from alternate
1797 locations such as env variables and files on disk */
f99d49ad
JJ
1798 kfree(volume_info.UNC);
1799 kfree(volume_info.password);
2fe87f02 1800 kfree(volume_info.prepath);
1da177e4
LT
1801 FreeXid(xid);
1802 return -EINVAL;
1803 }
1804
1805 if (volume_info.UNCip && volume_info.UNC) {
50c2f753
SF
1806 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,
1807 &sin_server.sin_addr.s_addr);
1da177e4 1808
fb8c4b14 1809 if (rc <= 0) {
1da177e4 1810 /* not ipv4 address, try ipv6 */
50c2f753
SF
1811 rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,
1812 &sin_server6.sin6_addr.in6_u);
fb8c4b14 1813 if (rc > 0)
1da177e4
LT
1814 address_type = AF_INET6;
1815 } else {
1816 address_type = AF_INET;
1817 }
50c2f753 1818
fb8c4b14 1819 if (rc <= 0) {
1da177e4 1820 /* we failed translating address */
f99d49ad
JJ
1821 kfree(volume_info.UNC);
1822 kfree(volume_info.password);
2fe87f02 1823 kfree(volume_info.prepath);
1da177e4
LT
1824 FreeXid(xid);
1825 return -EINVAL;
1826 }
1827
1828 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1829 /* success */
1830 rc = 0;
50c2f753
SF
1831 } else if (volume_info.UNCip) {
1832 /* BB using ip addr as server name to connect to the
1833 DFS root below */
1834 cERROR(1, ("Connecting to DFS root not implemented yet"));
f99d49ad
JJ
1835 kfree(volume_info.UNC);
1836 kfree(volume_info.password);
2fe87f02 1837 kfree(volume_info.prepath);
1da177e4
LT
1838 FreeXid(xid);
1839 return -EINVAL;
1840 } else /* which servers DFS root would we conect to */ {
1841 cERROR(1,
50c2f753
SF
1842 ("CIFS mount error: No UNC path (e.g. -o "
1843 "unc=//192.168.1.100/public) specified"));
f99d49ad
JJ
1844 kfree(volume_info.UNC);
1845 kfree(volume_info.password);
2fe87f02 1846 kfree(volume_info.prepath);
1da177e4
LT
1847 FreeXid(xid);
1848 return -EINVAL;
1849 }
1850
1851 /* this is needed for ASCII cp to Unicode converts */
fb8c4b14 1852 if (volume_info.iocharset == NULL) {
1da177e4
LT
1853 cifs_sb->local_nls = load_nls_default();
1854 /* load_nls_default can not return null */
1855 } else {
1856 cifs_sb->local_nls = load_nls(volume_info.iocharset);
fb8c4b14 1857 if (cifs_sb->local_nls == NULL) {
50c2f753
SF
1858 cERROR(1, ("CIFS mount error: iocharset %s not found",
1859 volume_info.iocharset));
f99d49ad
JJ
1860 kfree(volume_info.UNC);
1861 kfree(volume_info.password);
2fe87f02 1862 kfree(volume_info.prepath);
1da177e4
LT
1863 FreeXid(xid);
1864 return -ELIBACC;
1865 }
1866 }
1867
fb8c4b14 1868 if (address_type == AF_INET)
1da177e4
LT
1869 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1870 NULL /* no ipv6 addr */,
1871 volume_info.username, &srvTcp);
fb8c4b14
SF
1872 else if (address_type == AF_INET6) {
1873 cFYI(1, ("looking for ipv6 address"));
1da177e4
LT
1874 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1875 &sin_server6.sin6_addr,
1876 volume_info.username, &srvTcp);
5858ae44 1877 } else {
f99d49ad
JJ
1878 kfree(volume_info.UNC);
1879 kfree(volume_info.password);
2fe87f02 1880 kfree(volume_info.prepath);
1da177e4
LT
1881 FreeXid(xid);
1882 return -EINVAL;
1883 }
1884
1da177e4 1885 if (srvTcp) {
50c2f753 1886 cFYI(1, ("Existing tcp session with server found"));
1da177e4 1887 } else { /* create socket */
4523cc30 1888 if (volume_info.port)
1da177e4
LT
1889 sin_server.sin_port = htons(volume_info.port);
1890 else
1891 sin_server.sin_port = 0;
5858ae44 1892 if (address_type == AF_INET6) {
fb8c4b14 1893 cFYI(1, ("attempting ipv6 connect"));
5858ae44
SF
1894 /* BB should we allow ipv6 on port 139? */
1895 /* other OS never observed in Wild doing 139 with v6 */
50c2f753
SF
1896 rc = ipv6_connect(&sin_server6, &csocket);
1897 } else
1898 rc = ipv4_connect(&sin_server, &csocket,
a10faeb2
SF
1899 volume_info.source_rfc1001_name,
1900 volume_info.target_rfc1001_name);
1da177e4 1901 if (rc < 0) {
50c2f753
SF
1902 cERROR(1, ("Error connecting to IPv4 socket. "
1903 "Aborting operation"));
4523cc30 1904 if (csocket != NULL)
1da177e4 1905 sock_release(csocket);
f99d49ad
JJ
1906 kfree(volume_info.UNC);
1907 kfree(volume_info.password);
2fe87f02 1908 kfree(volume_info.prepath);
1da177e4
LT
1909 FreeXid(xid);
1910 return rc;
1911 }
1912
1913 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1914 if (srvTcp == NULL) {
1915 rc = -ENOMEM;
1916 sock_release(csocket);
f99d49ad
JJ
1917 kfree(volume_info.UNC);
1918 kfree(volume_info.password);
2fe87f02 1919 kfree(volume_info.prepath);
1da177e4
LT
1920 FreeXid(xid);
1921 return rc;
1922 } else {
1923 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
50c2f753
SF
1924 memcpy(&srvTcp->addr.sockAddr, &sin_server,
1925 sizeof (struct sockaddr_in));
1926 atomic_set(&srvTcp->inFlight, 0);
1da177e4
LT
1927 /* BB Add code for ipv6 case too */
1928 srvTcp->ssocket = csocket;
1929 srvTcp->protocolType = IPV4;
1930 init_waitqueue_head(&srvTcp->response_q);
1931 init_waitqueue_head(&srvTcp->request_q);
1932 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1933 /* at this point we are the only ones with the pointer
1934 to the struct since the kernel thread not created yet
1935 so no need to spinlock this init of tcpStatus */
1936 srvTcp->tcpStatus = CifsNew;
1937 init_MUTEX(&srvTcp->tcpSem);
aaf737ad 1938 srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd");
4523cc30 1939 if ( IS_ERR(srvTcp->tsk) ) {
aaf737ad 1940 rc = PTR_ERR(srvTcp->tsk);
50c2f753 1941 cERROR(1, ("error %d create cifsd thread", rc));
aaf737ad 1942 srvTcp->tsk = NULL;
1da177e4 1943 sock_release(csocket);
f99d49ad
JJ
1944 kfree(volume_info.UNC);
1945 kfree(volume_info.password);
2fe87f02 1946 kfree(volume_info.prepath);
1da177e4
LT
1947 FreeXid(xid);
1948 return rc;
f191401f
SF
1949 }
1950 wait_for_completion(&cifsd_complete);
1951 rc = 0;
50c2f753
SF
1952 memcpy(srvTcp->workstation_RFC1001_name,
1953 volume_info.source_rfc1001_name, 16);
1954 memcpy(srvTcp->server_RFC1001_name,
1955 volume_info.target_rfc1001_name, 16);
ad009ac9 1956 srvTcp->sequence_number = 0;
1da177e4
LT
1957 }
1958 }
1959
1960 if (existingCifsSes) {
1961 pSesInfo = existingCifsSes;
bf820679 1962 cFYI(1, ("Existing smb sess found"));
f99d49ad 1963 kfree(volume_info.password);
1da177e4
LT
1964 /* volume_info.UNC freed at end of function */
1965 } else if (!rc) {
bf820679 1966 cFYI(1, ("Existing smb sess not found"));
1da177e4
LT
1967 pSesInfo = sesInfoAlloc();
1968 if (pSesInfo == NULL)
1969 rc = -ENOMEM;
1970 else {
1971 pSesInfo->server = srvTcp;
1972 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1973 NIPQUAD(sin_server.sin_addr.s_addr));
1974 }
1975
50c2f753
SF
1976 if (!rc) {
1977 /* volume_info.password freed at unmount */
1da177e4
LT
1978 if (volume_info.password)
1979 pSesInfo->password = volume_info.password;
1980 if (volume_info.username)
1981 strncpy(pSesInfo->userName,
50c2f753
SF
1982 volume_info.username,
1983 MAX_USERNAME_SIZE);
3979877e
SF
1984 if (volume_info.domainname) {
1985 int len = strlen(volume_info.domainname);
50c2f753 1986 pSesInfo->domainName =
3979877e 1987 kmalloc(len + 1, GFP_KERNEL);
4523cc30 1988 if (pSesInfo->domainName)
3979877e
SF
1989 strcpy(pSesInfo->domainName,
1990 volume_info.domainname);
1991 }
1da177e4 1992 pSesInfo->linux_uid = volume_info.linux_uid;
750d1151 1993 pSesInfo->overrideSecFlg = volume_info.secFlg;
1da177e4 1994 down(&pSesInfo->sesSem);
189acaae 1995 /* BB FIXME need to pass vol->secFlgs BB */
50c2f753
SF
1996 rc = cifs_setup_session(xid, pSesInfo,
1997 cifs_sb->local_nls);
1da177e4 1998 up(&pSesInfo->sesSem);
4523cc30 1999 if (!rc)
1da177e4
LT
2000 atomic_inc(&srvTcp->socketUseCount);
2001 } else
f99d49ad 2002 kfree(volume_info.password);
1da177e4 2003 }
50c2f753 2004
1da177e4
LT
2005 /* search for existing tcon to this server share */
2006 if (!rc) {
4523cc30 2007 if (volume_info.rsize > CIFSMaxBufSize) {
50c2f753 2008 cERROR(1, ("rsize %d too large, using MaxBufSize",
0ae0efad
SF
2009 volume_info.rsize));
2010 cifs_sb->rsize = CIFSMaxBufSize;
75865f8c
SF
2011 } else if ((volume_info.rsize) &&
2012 (volume_info.rsize <= CIFSMaxBufSize))
1da177e4 2013 cifs_sb->rsize = volume_info.rsize;
0ae0efad
SF
2014 else /* default */
2015 cifs_sb->rsize = CIFSMaxBufSize;
2016
4523cc30 2017 if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
50c2f753 2018 cERROR(1, ("wsize %d too large, using 4096 instead",
0ae0efad
SF
2019 volume_info.wsize));
2020 cifs_sb->wsize = 4096;
4523cc30 2021 } else if (volume_info.wsize)
1da177e4
LT
2022 cifs_sb->wsize = volume_info.wsize;
2023 else
50c2f753 2024 cifs_sb->wsize =
1877c9ea
SF
2025 min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
2026 127*1024);
17cbbafe 2027 /* old default of CIFSMaxBufSize was too small now
50c2f753 2028 that SMB Write2 can send multiple pages in kvec.
17cbbafe
SF
2029 RFC1001 does not describe what happens when frame
2030 bigger than 128K is sent so use that as max in
2031 conjunction with 52K kvec constraint on arch with 4K
2032 page size */
2033
4523cc30 2034 if (cifs_sb->rsize < 2048) {
50c2f753 2035 cifs_sb->rsize = 2048;
6cec2aed 2036 /* Windows ME may prefer this */
467a8f8d 2037 cFYI(1, ("readsize set to minimum: 2048"));
1da177e4 2038 }
2fe87f02
SF
2039 /* calculate prepath */
2040 cifs_sb->prepath = volume_info.prepath;
4523cc30 2041 if (cifs_sb->prepath) {
2fe87f02
SF
2042 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
2043 cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb);
2044 volume_info.prepath = NULL;
50c2f753 2045 } else
2fe87f02 2046 cifs_sb->prepathlen = 0;
1da177e4
LT
2047 cifs_sb->mnt_uid = volume_info.linux_uid;
2048 cifs_sb->mnt_gid = volume_info.linux_gid;
2049 cifs_sb->mnt_file_mode = volume_info.file_mode;
2050 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
467a8f8d
SF
2051 cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
2052 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
1da177e4 2053
4523cc30 2054 if (volume_info.noperm)
1da177e4 2055 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
4523cc30 2056 if (volume_info.setuids)
1da177e4 2057 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
4523cc30 2058 if (volume_info.server_ino)
1da177e4 2059 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
4523cc30 2060 if (volume_info.remap)
6a0b4824 2061 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
4523cc30 2062 if (volume_info.no_xattr)
1da177e4 2063 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
4523cc30 2064 if (volume_info.sfu_emul)
d7245c2c 2065 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
4523cc30 2066 if (volume_info.nobrl)
c46fa8ac 2067 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
4523cc30 2068 if (volume_info.cifs_acl)
0a4b92c0 2069 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
4523cc30
SF
2070 if (volume_info.override_uid)
2071 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
2072 if (volume_info.override_gid)
2073 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2074 if (volume_info.direct_io) {
467a8f8d 2075 cFYI(1, ("mounting share using direct i/o"));
1da177e4
LT
2076 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
2077 }
2078
2079 tcon =
2080 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
2081 volume_info.username);
2082 if (tcon) {
bf820679 2083 cFYI(1, ("Found match on UNC path"));
1da177e4
LT
2084 /* we can have only one retry value for a connection
2085 to a share so for resources mounted more than once
50c2f753 2086 to the same server share the last value passed in
1da177e4
LT
2087 for the retry flag is used */
2088 tcon->retry = volume_info.retry;
d3485d37 2089 tcon->nocase = volume_info.nocase;
1da177e4
LT
2090 } else {
2091 tcon = tconInfoAlloc();
2092 if (tcon == NULL)
2093 rc = -ENOMEM;
2094 else {
50c2f753 2095 /* check for null share name ie connecting to
8af18971 2096 * dfs root */
1da177e4 2097
50c2f753 2098 /* BB check if this works for exactly length
8af18971 2099 * three strings */
1da177e4
LT
2100 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
2101 && (strchr(volume_info.UNC + 3, '/') ==
2102 NULL)) {
737b758c 2103 rc = connect_to_dfs_path(xid, pSesInfo,
8af18971 2104 "", cifs_sb->local_nls,
50c2f753 2105 cifs_sb->mnt_cifs_flags &
8af18971 2106 CIFS_MOUNT_MAP_SPECIAL_CHR);
f99d49ad 2107 kfree(volume_info.UNC);
1da177e4
LT
2108 FreeXid(xid);
2109 return -ENODEV;
2110 } else {
8af18971
SF
2111 /* BB Do we need to wrap sesSem around
2112 * this TCon call and Unix SetFS as
2113 * we do on SessSetup and reconnect? */
50c2f753 2114 rc = CIFSTCon(xid, pSesInfo,
1da177e4
LT
2115 volume_info.UNC,
2116 tcon, cifs_sb->local_nls);
2117 cFYI(1, ("CIFS Tcon rc = %d", rc));
2118 }
2119 if (!rc) {
2120 atomic_inc(&pSesInfo->inUse);
2121 tcon->retry = volume_info.retry;
d3485d37 2122 tcon->nocase = volume_info.nocase;
1da177e4
LT
2123 }
2124 }
2125 }
2126 }
4523cc30 2127 if (pSesInfo) {
1da177e4
LT
2128 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
2129 sb->s_maxbytes = (u64) 1 << 63;
2130 } else
2131 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
2132 }
2133
8af18971 2134 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
1da177e4
LT
2135 sb->s_time_gran = 100;
2136
2137/* on error free sesinfo and tcon struct if needed */
2138 if (rc) {
2139 /* if session setup failed, use count is zero but
2140 we still need to free cifsd thread */
4523cc30 2141 if (atomic_read(&srvTcp->socketUseCount) == 0) {
1da177e4
LT
2142 spin_lock(&GlobalMid_Lock);
2143 srvTcp->tcpStatus = CifsExiting;
2144 spin_unlock(&GlobalMid_Lock);
4523cc30 2145 if (srvTcp->tsk) {
28356a16
SF
2146 struct task_struct *tsk;
2147 /* If we could verify that kthread_stop would
2148 always wake up processes blocked in
2149 tcp in recv_mesg then we could remove the
2150 send_sig call */
50c2f753 2151 force_sig(SIGKILL, srvTcp->tsk);
28356a16 2152 tsk = srvTcp->tsk;
fb8c4b14 2153 if (tsk)
f7f7c31c 2154 kthread_stop(tsk);
f191401f 2155 }
1da177e4
LT
2156 }
2157 /* If find_unc succeeded then rc == 0 so we can not end */
2158 if (tcon) /* up accidently freeing someone elses tcon struct */
2159 tconInfoFree(tcon);
2160 if (existingCifsSes == NULL) {
2161 if (pSesInfo) {
50c2f753 2162 if ((pSesInfo->server) &&
1da177e4
LT
2163 (pSesInfo->status == CifsGood)) {
2164 int temp_rc;
2165 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
2166 /* if the socketUseCount is now zero */
4523cc30 2167 if ((temp_rc == -ESHUTDOWN) &&
50c2f753 2168 (pSesInfo->server) &&
5d9c7206 2169 (pSesInfo->server->tsk)) {
28356a16 2170 struct task_struct *tsk;
5d9c7206
J
2171 force_sig(SIGKILL,
2172 pSesInfo->server->tsk);
28356a16 2173 tsk = pSesInfo->server->tsk;
f7f7c31c 2174 if (tsk)
28356a16 2175 kthread_stop(tsk);
f191401f 2176 }
1da177e4
LT
2177 } else
2178 cFYI(1, ("No session or bad tcon"));
2179 sesInfoFree(pSesInfo);
2180 /* pSesInfo = NULL; */
2181 }
2182 }
2183 } else {
2184 atomic_inc(&tcon->useCount);
2185 cifs_sb->tcon = tcon;
2186 tcon->ses = pSesInfo;
2187
82940a46 2188 /* do not care if following two calls succeed - informational */
737b758c
SF
2189 CIFSSMBQFSDeviceInfo(xid, tcon);
2190 CIFSSMBQFSAttributeInfo(xid, tcon);
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 */
1da177e4
LT
2530 if (smb_buffer)
2531 cifs_buf_release(smb_buffer);
2532
2533 return rc;
2534}
2535
1da177e4
LT
2536static int
2537CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
50c2f753 2538 struct cifsSesInfo *ses, int *pNTLMv2_flag,
1da177e4
LT
2539 const struct nls_table *nls_codepage)
2540{
2541 struct smb_hdr *smb_buffer;
2542 struct smb_hdr *smb_buffer_response;
2543 SESSION_SETUP_ANDX *pSMB;
2544 SESSION_SETUP_ANDX *pSMBr;
2545 char *bcc_ptr;
2546 char *domain;
2547 int rc = 0;
2548 int remaining_words = 0;
2549 int bytes_returned = 0;
2550 int len;
2551 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2552 PNEGOTIATE_MESSAGE SecurityBlob;
2553 PCHALLENGE_MESSAGE SecurityBlob2;
2554 __u32 negotiate_flags, capabilities;
2555 __u16 count;
2556
12b3b8ff 2557 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
fb8c4b14 2558 if (ses == NULL)
1da177e4
LT
2559 return -EINVAL;
2560 domain = ses->domainName;
2561 *pNTLMv2_flag = FALSE;
2562 smb_buffer = cifs_buf_get();
2563 if (smb_buffer == NULL) {
2564 return -ENOMEM;
2565 }
2566 smb_buffer_response = smb_buffer;
2567 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2568 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2569
2570 /* send SMBsessionSetup here */
2571 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2572 NULL /* no tCon exists yet */ , 12 /* wct */ );
1982c344
SF
2573
2574 smb_buffer->Mid = GetNextMid(ses->server);
1da177e4
LT
2575 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2576 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2577
2578 pSMB->req.AndXCommand = 0xFF;
2579 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2580 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2581
fb8c4b14 2582 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1da177e4
LT
2583 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2584
2585 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2586 CAP_EXTENDED_SECURITY;
2587 if (ses->capabilities & CAP_UNICODE) {
2588 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2589 capabilities |= CAP_UNICODE;
2590 }
2591 if (ses->capabilities & CAP_STATUS32) {
2592 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2593 capabilities |= CAP_STATUS32;
2594 }
2595 if (ses->capabilities & CAP_DFS) {
2596 smb_buffer->Flags2 |= SMBFLG2_DFS;
2597 capabilities |= CAP_DFS;
2598 }
2599 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2600
2601 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2602 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2603 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2604 SecurityBlob->MessageType = NtLmNegotiate;
2605 negotiate_flags =
2606 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
12b3b8ff
SF
2607 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2608 NTLMSSP_NEGOTIATE_56 |
1da177e4 2609 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
fb8c4b14 2610 if (sign_CIFS_PDUs)
1da177e4 2611 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
fb8c4b14 2612/* if (ntlmv2_support)
3979877e 2613 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
1da177e4
LT
2614 /* setup pointers to domain name and workstation name */
2615 bcc_ptr += SecurityBlobLength;
2616
2617 SecurityBlob->WorkstationName.Buffer = 0;
2618 SecurityBlob->WorkstationName.Length = 0;
2619 SecurityBlob->WorkstationName.MaximumLength = 0;
2620
12b3b8ff
SF
2621 /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2622 along with username on auth request (ie the response to challenge) */
2623 SecurityBlob->DomainName.Buffer = 0;
2624 SecurityBlob->DomainName.Length = 0;
2625 SecurityBlob->DomainName.MaximumLength = 0;
1da177e4
LT
2626 if (ses->capabilities & CAP_UNICODE) {
2627 if ((long) bcc_ptr % 2) {
2628 *bcc_ptr = 0;
2629 bcc_ptr++;
2630 }
2631
2632 bytes_returned =
e89dc920 2633 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
1da177e4
LT
2634 32, nls_codepage);
2635 bcc_ptr += 2 * bytes_returned;
2636 bytes_returned =
e9ff3990 2637 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
1da177e4
LT
2638 nls_codepage);
2639 bcc_ptr += 2 * bytes_returned;
2640 bcc_ptr += 2; /* null terminate Linux version */
2641 bytes_returned =
e89dc920 2642 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
1da177e4
LT
2643 64, nls_codepage);
2644 bcc_ptr += 2 * bytes_returned;
2645 *(bcc_ptr + 1) = 0;
2646 *(bcc_ptr + 2) = 0;
2647 bcc_ptr += 2; /* null terminate network opsys string */
2648 *(bcc_ptr + 1) = 0;
2649 *(bcc_ptr + 2) = 0;
2650 bcc_ptr += 2; /* null domain */
2651 } else { /* ASCII */
2652 strcpy(bcc_ptr, "Linux version ");
2653 bcc_ptr += strlen("Linux version ");
e9ff3990
SH
2654 strcpy(bcc_ptr, utsname()->release);
2655 bcc_ptr += strlen(utsname()->release) + 1;
1da177e4
LT
2656 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2657 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2658 bcc_ptr++; /* empty domain field */
2659 *bcc_ptr = 0;
2660 }
2661 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2662 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2663 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2664 smb_buffer->smb_buf_length += count;
2665 pSMB->req.ByteCount = cpu_to_le16(count);
2666
2667 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2668 &bytes_returned, 1);
2669
2670 if (smb_buffer_response->Status.CifsError ==
2671 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2672 rc = 0;
2673
2674 if (rc) {
2675/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2676 } else if ((smb_buffer_response->WordCount == 3)
2677 || (smb_buffer_response->WordCount == 4)) {
2678 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2679 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2680
2681 if (action & GUEST_LOGIN)
50c2f753
SF
2682 cFYI(1, (" Guest login"));
2683 /* Do we want to set anything in SesInfo struct when guest login? */
1da177e4 2684
50c2f753
SF
2685 bcc_ptr = pByteArea(smb_buffer_response);
2686 /* response can have either 3 or 4 word count - Samba sends 3 */
1da177e4
LT
2687
2688 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2689 if (SecurityBlob2->MessageType != NtLmChallenge) {
2690 cFYI(1,
2691 ("Unexpected NTLMSSP message type received %d",
2692 SecurityBlob2->MessageType));
2693 } else if (ses) {
50c2f753 2694 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
12b3b8ff 2695 cFYI(1, ("UID = %d", ses->Suid));
1da177e4
LT
2696 if ((pSMBr->resp.hdr.WordCount == 3)
2697 || ((pSMBr->resp.hdr.WordCount == 4)
2698 && (blob_len <
2699 pSMBr->resp.ByteCount))) {
2700
2701 if (pSMBr->resp.hdr.WordCount == 4) {
2702 bcc_ptr += blob_len;
12b3b8ff 2703 cFYI(1, ("Security Blob Length %d",
1da177e4
LT
2704 blob_len));
2705 }
2706
12b3b8ff 2707 cFYI(1, ("NTLMSSP Challenge rcvd"));
1da177e4
LT
2708
2709 memcpy(ses->server->cryptKey,
2710 SecurityBlob2->Challenge,
2711 CIFS_CRYPTO_KEY_SIZE);
50c2f753 2712 if (SecurityBlob2->NegotiateFlags &
12b3b8ff 2713 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
1da177e4
LT
2714 *pNTLMv2_flag = TRUE;
2715
50c2f753
SF
2716 if ((SecurityBlob2->NegotiateFlags &
2717 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
1da177e4 2718 || (sign_CIFS_PDUs > 1))
50c2f753
SF
2719 ses->server->secMode |=
2720 SECMODE_SIGN_REQUIRED;
2721 if ((SecurityBlob2->NegotiateFlags &
1da177e4 2722 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
50c2f753 2723 ses->server->secMode |=
1da177e4
LT
2724 SECMODE_SIGN_ENABLED;
2725
2726 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2727 if ((long) (bcc_ptr) % 2) {
2728 remaining_words =
2729 (BCC(smb_buffer_response)
2730 - 1) / 2;
50c2f753
SF
2731 /* Must word align unicode strings */
2732 bcc_ptr++;
1da177e4
LT
2733 } else {
2734 remaining_words =
2735 BCC
2736 (smb_buffer_response) / 2;
2737 }
2738 len =
2739 UniStrnlen((wchar_t *) bcc_ptr,
2740 remaining_words - 1);
2741/* We look for obvious messed up bcc or strings in response so we do not go off
2742 the end since (at least) WIN2K and Windows XP have a major bug in not null
2743 terminating last Unicode string in response */
fb8c4b14 2744 if (ses->serverOS)
a424f8bf 2745 kfree(ses->serverOS);
1da177e4 2746 ses->serverOS =
e915fc49 2747 kzalloc(2 * (len + 1), GFP_KERNEL);
1da177e4 2748 cifs_strfromUCS_le(ses->serverOS,
e89dc920 2749 (__le16 *)
1da177e4
LT
2750 bcc_ptr, len,
2751 nls_codepage);
2752 bcc_ptr += 2 * (len + 1);
2753 remaining_words -= len + 1;
2754 ses->serverOS[2 * len] = 0;
2755 ses->serverOS[1 + (2 * len)] = 0;
2756 if (remaining_words > 0) {
2757 len = UniStrnlen((wchar_t *)
2758 bcc_ptr,
2759 remaining_words
2760 - 1);
cd49b492 2761 kfree(ses->serverNOS);
1da177e4 2762 ses->serverNOS =
e915fc49 2763 kzalloc(2 * (len + 1),
1da177e4
LT
2764 GFP_KERNEL);
2765 cifs_strfromUCS_le(ses->
2766 serverNOS,
e89dc920 2767 (__le16 *)
1da177e4
LT
2768 bcc_ptr,
2769 len,
2770 nls_codepage);
2771 bcc_ptr += 2 * (len + 1);
2772 ses->serverNOS[2 * len] = 0;
2773 ses->serverNOS[1 +
2774 (2 * len)] = 0;
2775 remaining_words -= len + 1;
2776 if (remaining_words > 0) {
50c2f753
SF
2777 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2778 /* last string not always null terminated
2779 (for e.g. for Windows XP & 2000) */
cd49b492 2780 kfree(ses->serverDomain);
1da177e4 2781 ses->serverDomain =
e915fc49 2782 kzalloc(2 *
1da177e4
LT
2783 (len +
2784 1),
2785 GFP_KERNEL);
2786 cifs_strfromUCS_le
e89dc920
SF
2787 (ses->serverDomain,
2788 (__le16 *)bcc_ptr,
2789 len, nls_codepage);
1da177e4
LT
2790 bcc_ptr +=
2791 2 * (len + 1);
e89dc920 2792 ses->serverDomain[2*len]
1da177e4 2793 = 0;
e89dc920
SF
2794 ses->serverDomain
2795 [1 + (2 * len)]
1da177e4
LT
2796 = 0;
2797 } /* else no more room so create dummy domain string */
a424f8bf 2798 else {
cd49b492 2799 kfree(ses->serverDomain);
1da177e4 2800 ses->serverDomain =
e915fc49 2801 kzalloc(2,
1da177e4 2802 GFP_KERNEL);
a424f8bf 2803 }
1da177e4 2804 } else { /* no room so create dummy domain and NOS string */
cd49b492 2805 kfree(ses->serverDomain);
1da177e4 2806 ses->serverDomain =
e915fc49 2807 kzalloc(2, GFP_KERNEL);
cd49b492 2808 kfree(ses->serverNOS);
1da177e4 2809 ses->serverNOS =
e915fc49 2810 kzalloc(2, GFP_KERNEL);
1da177e4
LT
2811 }
2812 } else { /* ASCII */
2813 len = strnlen(bcc_ptr, 1024);
2814 if (((long) bcc_ptr + len) - (long)
2815 pByteArea(smb_buffer_response)
2816 <= BCC(smb_buffer_response)) {
fb8c4b14 2817 if (ses->serverOS)
a424f8bf 2818 kfree(ses->serverOS);
1da177e4 2819 ses->serverOS =
e915fc49 2820 kzalloc(len + 1,
1da177e4
LT
2821 GFP_KERNEL);
2822 strncpy(ses->serverOS,
2823 bcc_ptr, len);
2824
2825 bcc_ptr += len;
2826 bcc_ptr[0] = 0; /* null terminate string */
2827 bcc_ptr++;
2828
2829 len = strnlen(bcc_ptr, 1024);
cd49b492 2830 kfree(ses->serverNOS);
1da177e4 2831 ses->serverNOS =
e915fc49 2832 kzalloc(len + 1,
1da177e4
LT
2833 GFP_KERNEL);
2834 strncpy(ses->serverNOS, bcc_ptr, len);
2835 bcc_ptr += len;
2836 bcc_ptr[0] = 0;
2837 bcc_ptr++;
2838
2839 len = strnlen(bcc_ptr, 1024);
cd49b492 2840 kfree(ses->serverDomain);
1da177e4 2841 ses->serverDomain =
e915fc49 2842 kzalloc(len + 1,
1da177e4 2843 GFP_KERNEL);
50c2f753
SF
2844 strncpy(ses->serverDomain,
2845 bcc_ptr, len);
1da177e4
LT
2846 bcc_ptr += len;
2847 bcc_ptr[0] = 0;
2848 bcc_ptr++;
2849 } else
2850 cFYI(1,
63135e08
SF
2851 ("field of length %d "
2852 "extends beyond end of smb",
1da177e4
LT
2853 len));
2854 }
2855 } else {
50c2f753
SF
2856 cERROR(1, ("Security Blob Length extends beyond"
2857 " end of SMB"));
1da177e4
LT
2858 }
2859 } else {
2860 cERROR(1, ("No session structure passed in."));
2861 }
2862 } else {
2863 cERROR(1,
5815449d 2864 (" Invalid Word count %d:",
1da177e4
LT
2865 smb_buffer_response->WordCount));
2866 rc = -EIO;
2867 }
2868
2869 if (smb_buffer)
2870 cifs_buf_release(smb_buffer);
2871
2872 return rc;
2873}
2874static int
2875CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2876 char *ntlm_session_key, int ntlmv2_flag,
2877 const struct nls_table *nls_codepage)
2878{
2879 struct smb_hdr *smb_buffer;
2880 struct smb_hdr *smb_buffer_response;
2881 SESSION_SETUP_ANDX *pSMB;
2882 SESSION_SETUP_ANDX *pSMBr;
2883 char *bcc_ptr;
2884 char *user;
2885 char *domain;
2886 int rc = 0;
2887 int remaining_words = 0;
2888 int bytes_returned = 0;
2889 int len;
2890 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2891 PAUTHENTICATE_MESSAGE SecurityBlob;
2892 __u32 negotiate_flags, capabilities;
2893 __u16 count;
2894
2895 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
fb8c4b14 2896 if (ses == NULL)
1da177e4
LT
2897 return -EINVAL;
2898 user = ses->userName;
2899 domain = ses->domainName;
2900 smb_buffer = cifs_buf_get();
2901 if (smb_buffer == NULL) {
2902 return -ENOMEM;
2903 }
2904 smb_buffer_response = smb_buffer;
2905 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2906 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2907
2908 /* send SMBsessionSetup here */
2909 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2910 NULL /* no tCon exists yet */ , 12 /* wct */ );
1982c344
SF
2911
2912 smb_buffer->Mid = GetNextMid(ses->server);
1da177e4
LT
2913 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2914 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2915 pSMB->req.AndXCommand = 0xFF;
2916 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2917 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2918
2919 pSMB->req.hdr.Uid = ses->Suid;
2920
fb8c4b14 2921 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1da177e4
LT
2922 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2923
2924 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2925 CAP_EXTENDED_SECURITY;
2926 if (ses->capabilities & CAP_UNICODE) {
2927 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2928 capabilities |= CAP_UNICODE;
2929 }
2930 if (ses->capabilities & CAP_STATUS32) {
2931 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2932 capabilities |= CAP_STATUS32;
2933 }
2934 if (ses->capabilities & CAP_DFS) {
2935 smb_buffer->Flags2 |= SMBFLG2_DFS;
2936 capabilities |= CAP_DFS;
2937 }
2938 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2939
2940 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2941 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2942 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2943 SecurityBlob->MessageType = NtLmAuthenticate;
2944 bcc_ptr += SecurityBlobLength;
50c2f753 2945 negotiate_flags =
1da177e4
LT
2946 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2947 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2948 0x80000000 | NTLMSSP_NEGOTIATE_128;
fb8c4b14 2949 if (sign_CIFS_PDUs)
1da177e4 2950 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
fb8c4b14 2951 if (ntlmv2_flag)
1da177e4
LT
2952 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2953
2954/* setup pointers to domain name and workstation name */
2955
2956 SecurityBlob->WorkstationName.Buffer = 0;
2957 SecurityBlob->WorkstationName.Length = 0;
2958 SecurityBlob->WorkstationName.MaximumLength = 0;
2959 SecurityBlob->SessionKey.Length = 0;
2960 SecurityBlob->SessionKey.MaximumLength = 0;
2961 SecurityBlob->SessionKey.Buffer = 0;
2962
2963 SecurityBlob->LmChallengeResponse.Length = 0;
2964 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2965 SecurityBlob->LmChallengeResponse.Buffer = 0;
2966
2967 SecurityBlob->NtChallengeResponse.Length =
7c7b25bc 2968 cpu_to_le16(CIFS_SESS_KEY_SIZE);
1da177e4 2969 SecurityBlob->NtChallengeResponse.MaximumLength =
7c7b25bc
SF
2970 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2971 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
1da177e4
LT
2972 SecurityBlob->NtChallengeResponse.Buffer =
2973 cpu_to_le32(SecurityBlobLength);
7c7b25bc
SF
2974 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
2975 bcc_ptr += CIFS_SESS_KEY_SIZE;
1da177e4
LT
2976
2977 if (ses->capabilities & CAP_UNICODE) {
2978 if (domain == NULL) {
2979 SecurityBlob->DomainName.Buffer = 0;
2980 SecurityBlob->DomainName.Length = 0;
2981 SecurityBlob->DomainName.MaximumLength = 0;
2982 } else {
77159b4d 2983 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
1da177e4 2984 nls_codepage);
77159b4d 2985 ln *= 2;
1da177e4 2986 SecurityBlob->DomainName.MaximumLength =
77159b4d 2987 cpu_to_le16(ln);
1da177e4
LT
2988 SecurityBlob->DomainName.Buffer =
2989 cpu_to_le32(SecurityBlobLength);
77159b4d
SF
2990 bcc_ptr += ln;
2991 SecurityBlobLength += ln;
2992 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
1da177e4
LT
2993 }
2994 if (user == NULL) {
2995 SecurityBlob->UserName.Buffer = 0;
2996 SecurityBlob->UserName.Length = 0;
2997 SecurityBlob->UserName.MaximumLength = 0;
2998 } else {
77159b4d 2999 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
1da177e4 3000 nls_codepage);
77159b4d 3001 ln *= 2;
1da177e4 3002 SecurityBlob->UserName.MaximumLength =
77159b4d 3003 cpu_to_le16(ln);
1da177e4
LT
3004 SecurityBlob->UserName.Buffer =
3005 cpu_to_le32(SecurityBlobLength);
77159b4d
SF
3006 bcc_ptr += ln;
3007 SecurityBlobLength += ln;
3008 SecurityBlob->UserName.Length = cpu_to_le16(ln);
1da177e4
LT
3009 }
3010
63135e08
SF
3011 /* SecurityBlob->WorkstationName.Length =
3012 cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
1da177e4 3013 SecurityBlob->WorkstationName.Length *= 2;
63135e08
SF
3014 SecurityBlob->WorkstationName.MaximumLength =
3015 cpu_to_le16(SecurityBlob->WorkstationName.Length);
3016 SecurityBlob->WorkstationName.Buffer =
3017 cpu_to_le32(SecurityBlobLength);
1da177e4
LT
3018 bcc_ptr += SecurityBlob->WorkstationName.Length;
3019 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
63135e08
SF
3020 SecurityBlob->WorkstationName.Length =
3021 cpu_to_le16(SecurityBlob->WorkstationName.Length); */
1da177e4
LT
3022
3023 if ((long) bcc_ptr % 2) {
3024 *bcc_ptr = 0;
3025 bcc_ptr++;
3026 }
3027 bytes_returned =
e89dc920 3028 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
1da177e4
LT
3029 32, nls_codepage);
3030 bcc_ptr += 2 * bytes_returned;
3031 bytes_returned =
e9ff3990 3032 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
1da177e4
LT
3033 nls_codepage);
3034 bcc_ptr += 2 * bytes_returned;
3035 bcc_ptr += 2; /* null term version string */
3036 bytes_returned =
e89dc920 3037 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
1da177e4
LT
3038 64, nls_codepage);
3039 bcc_ptr += 2 * bytes_returned;
3040 *(bcc_ptr + 1) = 0;
3041 *(bcc_ptr + 2) = 0;
3042 bcc_ptr += 2; /* null terminate network opsys string */
3043 *(bcc_ptr + 1) = 0;
3044 *(bcc_ptr + 2) = 0;
3045 bcc_ptr += 2; /* null domain */
3046 } else { /* ASCII */
3047 if (domain == NULL) {
3048 SecurityBlob->DomainName.Buffer = 0;
3049 SecurityBlob->DomainName.Length = 0;
3050 SecurityBlob->DomainName.MaximumLength = 0;
3051 } else {
77159b4d 3052 __u16 ln;
1da177e4
LT
3053 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3054 strncpy(bcc_ptr, domain, 63);
77159b4d 3055 ln = strnlen(domain, 64);
1da177e4 3056 SecurityBlob->DomainName.MaximumLength =
77159b4d 3057 cpu_to_le16(ln);
1da177e4
LT
3058 SecurityBlob->DomainName.Buffer =
3059 cpu_to_le32(SecurityBlobLength);
77159b4d
SF
3060 bcc_ptr += ln;
3061 SecurityBlobLength += ln;
3062 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
1da177e4
LT
3063 }
3064 if (user == NULL) {
3065 SecurityBlob->UserName.Buffer = 0;
3066 SecurityBlob->UserName.Length = 0;
3067 SecurityBlob->UserName.MaximumLength = 0;
3068 } else {
77159b4d 3069 __u16 ln;
1da177e4 3070 strncpy(bcc_ptr, user, 63);
77159b4d
SF
3071 ln = strnlen(user, 64);
3072 SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
1da177e4 3073 SecurityBlob->UserName.Buffer =
77159b4d
SF
3074 cpu_to_le32(SecurityBlobLength);
3075 bcc_ptr += ln;
3076 SecurityBlobLength += ln;
3077 SecurityBlob->UserName.Length = cpu_to_le16(ln);
1da177e4
LT
3078 }
3079 /* BB fill in our workstation name if known BB */
3080
3081 strcpy(bcc_ptr, "Linux version ");
3082 bcc_ptr += strlen("Linux version ");
e9ff3990
SH
3083 strcpy(bcc_ptr, utsname()->release);
3084 bcc_ptr += strlen(utsname()->release) + 1;
1da177e4
LT
3085 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3086 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3087 bcc_ptr++; /* null domain */
3088 *bcc_ptr = 0;
3089 }
3090 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3091 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3092 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3093 smb_buffer->smb_buf_length += count;
3094 pSMB->req.ByteCount = cpu_to_le16(count);
3095
3096 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3097 &bytes_returned, 1);
3098 if (rc) {
3099/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
3100 } else if ((smb_buffer_response->WordCount == 3)
3101 || (smb_buffer_response->WordCount == 4)) {
3102 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3103 __u16 blob_len =
3104 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3105 if (action & GUEST_LOGIN)
50c2f753
SF
3106 cFYI(1, (" Guest login")); /* BB Should we set anything
3107 in SesInfo struct ? */
3108/* if (SecurityBlob2->MessageType != NtLm??) {
3109 cFYI("Unexpected message type on auth response is %d"));
3110 } */
3111
1da177e4
LT
3112 if (ses) {
3113 cFYI(1,
50c2f753 3114 ("Check challenge UID %d vs auth response UID %d",
1da177e4 3115 ses->Suid, smb_buffer_response->Uid));
50c2f753
SF
3116 /* UID left in wire format */
3117 ses->Suid = smb_buffer_response->Uid;
3118 bcc_ptr = pByteArea(smb_buffer_response);
3119 /* response can have either 3 or 4 word count - Samba sends 3 */
1da177e4
LT
3120 if ((pSMBr->resp.hdr.WordCount == 3)
3121 || ((pSMBr->resp.hdr.WordCount == 4)
3122 && (blob_len <
3123 pSMBr->resp.ByteCount))) {
3124 if (pSMBr->resp.hdr.WordCount == 4) {
3125 bcc_ptr +=
3126 blob_len;
3127 cFYI(1,
3128 ("Security Blob Length %d ",
3129 blob_len));
3130 }
3131
3132 cFYI(1,
3133 ("NTLMSSP response to Authenticate "));
3134
3135 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3136 if ((long) (bcc_ptr) % 2) {
3137 remaining_words =
3138 (BCC(smb_buffer_response)
3139 - 1) / 2;
3140 bcc_ptr++; /* Unicode strings must be word aligned */
3141 } else {
3142 remaining_words = BCC(smb_buffer_response) / 2;
3143 }
77159b4d
SF
3144 len = UniStrnlen((wchar_t *) bcc_ptr,
3145 remaining_words - 1);
1da177e4
LT
3146/* We look for obvious messed up bcc or strings in response so we do not go off
3147 the end since (at least) WIN2K and Windows XP have a major bug in not null
3148 terminating last Unicode string in response */
fb8c4b14 3149 if (ses->serverOS)
08775834 3150 kfree(ses->serverOS);
1da177e4 3151 ses->serverOS =
e915fc49 3152 kzalloc(2 * (len + 1), GFP_KERNEL);
1da177e4 3153 cifs_strfromUCS_le(ses->serverOS,
e89dc920 3154 (__le16 *)
1da177e4
LT
3155 bcc_ptr, len,
3156 nls_codepage);
3157 bcc_ptr += 2 * (len + 1);
3158 remaining_words -= len + 1;
3159 ses->serverOS[2 * len] = 0;
3160 ses->serverOS[1 + (2 * len)] = 0;
3161 if (remaining_words > 0) {
3162 len = UniStrnlen((wchar_t *)
3163 bcc_ptr,
3164 remaining_words
3165 - 1);
cd49b492 3166 kfree(ses->serverNOS);
1da177e4 3167 ses->serverNOS =
e915fc49 3168 kzalloc(2 * (len + 1),
1da177e4
LT
3169 GFP_KERNEL);
3170 cifs_strfromUCS_le(ses->
3171 serverNOS,
e89dc920 3172 (__le16 *)
1da177e4
LT
3173 bcc_ptr,
3174 len,
3175 nls_codepage);
3176 bcc_ptr += 2 * (len + 1);
3177 ses->serverNOS[2 * len] = 0;
3178 ses->serverNOS[1+(2*len)] = 0;
3179 remaining_words -= len + 1;
3180 if (remaining_words > 0) {
50c2f753 3181 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
1da177e4 3182 /* last string not always null terminated (e.g. for Windows XP & 2000) */
fb8c4b14 3183 if (ses->serverDomain)
a424f8bf 3184 kfree(ses->serverDomain);
1da177e4 3185 ses->serverDomain =
e915fc49 3186 kzalloc(2 *
1da177e4
LT
3187 (len +
3188 1),
3189 GFP_KERNEL);
3190 cifs_strfromUCS_le
3191 (ses->
3192 serverDomain,
e89dc920 3193 (__le16 *)
1da177e4
LT
3194 bcc_ptr, len,
3195 nls_codepage);
3196 bcc_ptr +=
3197 2 * (len + 1);
3198 ses->
3199 serverDomain[2
3200 * len]
3201 = 0;
3202 ses->
3203 serverDomain[1
3204 +
3205 (2
3206 *
3207 len)]
3208 = 0;
3209 } /* else no more room so create dummy domain string */
a424f8bf 3210 else {
fb8c4b14 3211 if (ses->serverDomain)
a424f8bf 3212 kfree(ses->serverDomain);
e915fc49 3213 ses->serverDomain = kzalloc(2,GFP_KERNEL);
a424f8bf 3214 }
1da177e4 3215 } else { /* no room so create dummy domain and NOS string */
fb8c4b14 3216 if (ses->serverDomain)
a424f8bf 3217 kfree(ses->serverDomain);
e915fc49 3218 ses->serverDomain = kzalloc(2, GFP_KERNEL);
cd49b492 3219 kfree(ses->serverNOS);
e915fc49 3220 ses->serverNOS = kzalloc(2, GFP_KERNEL);
1da177e4
LT
3221 }
3222 } else { /* ASCII */
3223 len = strnlen(bcc_ptr, 1024);
50c2f753
SF
3224 if (((long) bcc_ptr + len) -
3225 (long) pByteArea(smb_buffer_response)
63135e08 3226 <= BCC(smb_buffer_response)) {
fb8c4b14 3227 if (ses->serverOS)
a424f8bf 3228 kfree(ses->serverOS);
77159b4d 3229 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
1da177e4
LT
3230 strncpy(ses->serverOS,bcc_ptr, len);
3231
3232 bcc_ptr += len;
3233 bcc_ptr[0] = 0; /* null terminate the string */
3234 bcc_ptr++;
3235
3236 len = strnlen(bcc_ptr, 1024);
cd49b492 3237 kfree(ses->serverNOS);
50c2f753
SF
3238 ses->serverNOS = kzalloc(len+1,
3239 GFP_KERNEL);
63135e08
SF
3240 strncpy(ses->serverNOS,
3241 bcc_ptr, len);
1da177e4
LT
3242 bcc_ptr += len;
3243 bcc_ptr[0] = 0;
3244 bcc_ptr++;
3245
3246 len = strnlen(bcc_ptr, 1024);
fb8c4b14 3247 if (ses->serverDomain)
a424f8bf 3248 kfree(ses->serverDomain);
63135e08
SF
3249 ses->serverDomain =
3250 kzalloc(len+1,
3251 GFP_KERNEL);
3252 strncpy(ses->serverDomain,
3253 bcc_ptr, len);
1da177e4
LT
3254 bcc_ptr += len;
3255 bcc_ptr[0] = 0;
3256 bcc_ptr++;
3257 } else
3258 cFYI(1,
63135e08
SF
3259 ("field of length %d "
3260 "extends beyond end of smb ",
1da177e4
LT
3261 len));
3262 }
3263 } else {
3264 cERROR(1,
63135e08
SF
3265 (" Security Blob extends beyond end "
3266 "of SMB"));
1da177e4
LT
3267 }
3268 } else {
3269 cERROR(1, ("No session structure passed in."));
3270 }
3271 } else {
3272 cERROR(1,
3273 (" Invalid Word count %d: ",
3274 smb_buffer_response->WordCount));
3275 rc = -EIO;
3276 }
3277
3278 if (smb_buffer)
3279 cifs_buf_release(smb_buffer);
3280
3281 return rc;
3282}
3283
3284int
3285CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3286 const char *tree, struct cifsTconInfo *tcon,
3287 const struct nls_table *nls_codepage)
3288{
3289 struct smb_hdr *smb_buffer;
3290 struct smb_hdr *smb_buffer_response;
3291 TCONX_REQ *pSMB;
3292 TCONX_RSP *pSMBr;
3293 unsigned char *bcc_ptr;
3294 int rc = 0;
3295 int length;
3296 __u16 count;
3297
3298 if (ses == NULL)
3299 return -EIO;
3300
3301 smb_buffer = cifs_buf_get();
3302 if (smb_buffer == NULL) {
3303 return -ENOMEM;
3304 }
3305 smb_buffer_response = smb_buffer;
3306
3307 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3308 NULL /*no tid */ , 4 /*wct */ );
1982c344
SF
3309
3310 smb_buffer->Mid = GetNextMid(ses->server);
1da177e4
LT
3311 smb_buffer->Uid = ses->Suid;
3312 pSMB = (TCONX_REQ *) smb_buffer;
3313 pSMBr = (TCONX_RSP *) smb_buffer_response;
3314
3315 pSMB->AndXCommand = 0xFF;
3316 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
1da177e4 3317 bcc_ptr = &pSMB->Password[0];
fb8c4b14 3318 if ((ses->server->secMode) & SECMODE_USER) {
eeac8047 3319 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
7c7b25bc 3320 *bcc_ptr = 0; /* password is null byte */
eeac8047 3321 bcc_ptr++; /* skip password */
7c7b25bc 3322 /* already aligned so no need to do it below */
eeac8047 3323 } else {
7c7b25bc 3324 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
eeac8047
SF
3325 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3326 specified as required (when that support is added to
3327 the vfs in the future) as only NTLM or the much
7c7b25bc 3328 weaker LANMAN (which we do not send by default) is accepted
eeac8047
SF
3329 by Samba (not sure whether other servers allow
3330 NTLMv2 password here) */
7c7b25bc 3331#ifdef CONFIG_CIFS_WEAK_PW_HASH
50c2f753 3332 if ((extended_security & CIFSSEC_MAY_LANMAN) &&
7c7b25bc
SF
3333 (ses->server->secType == LANMAN))
3334 calc_lanman_hash(ses, bcc_ptr);
3335 else
3336#endif /* CIFS_WEAK_PW_HASH */
eeac8047
SF
3337 SMBNTencrypt(ses->password,
3338 ses->server->cryptKey,
3339 bcc_ptr);
3340
7c7b25bc 3341 bcc_ptr += CIFS_SESS_KEY_SIZE;
fb8c4b14 3342 if (ses->capabilities & CAP_UNICODE) {
7c7b25bc
SF
3343 /* must align unicode strings */
3344 *bcc_ptr = 0; /* null byte password */
3345 bcc_ptr++;
3346 }
eeac8047 3347 }
1da177e4 3348
50c2f753 3349 if (ses->server->secMode &
a878fb22 3350 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
1da177e4
LT
3351 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3352
3353 if (ses->capabilities & CAP_STATUS32) {
3354 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3355 }
3356 if (ses->capabilities & CAP_DFS) {
3357 smb_buffer->Flags2 |= SMBFLG2_DFS;
3358 }
3359 if (ses->capabilities & CAP_UNICODE) {
3360 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3361 length =
50c2f753
SF
3362 cifs_strtoUCS((__le16 *) bcc_ptr, tree,
3363 6 /* max utf8 char length in bytes */ *
a878fb22
SF
3364 (/* server len*/ + 256 /* share len */), nls_codepage);
3365 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
1da177e4
LT
3366 bcc_ptr += 2; /* skip trailing null */
3367 } else { /* ASCII */
1da177e4
LT
3368 strcpy(bcc_ptr, tree);
3369 bcc_ptr += strlen(tree) + 1;
3370 }
3371 strcpy(bcc_ptr, "?????");
3372 bcc_ptr += strlen("?????");
3373 bcc_ptr += 1;
3374 count = bcc_ptr - &pSMB->Password[0];
3375 pSMB->hdr.smb_buf_length += count;
3376 pSMB->ByteCount = cpu_to_le16(count);
3377
3378 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3379
3380 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3381 /* above now done in SendReceive */
3382 if ((rc == 0) && (tcon != NULL)) {
3383 tcon->tidStatus = CifsGood;
3384 tcon->tid = smb_buffer_response->Tid;
3385 bcc_ptr = pByteArea(smb_buffer_response);
3386 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
50c2f753
SF
3387 /* skip service field (NB: this field is always ASCII) */
3388 bcc_ptr += length + 1;
1da177e4
LT
3389 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3390 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3391 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3392 if ((bcc_ptr + (2 * length)) -
3393 pByteArea(smb_buffer_response) <=
3394 BCC(smb_buffer_response)) {
f99d49ad 3395 kfree(tcon->nativeFileSystem);
1da177e4 3396 tcon->nativeFileSystem =
e915fc49 3397 kzalloc(length + 2, GFP_KERNEL);
88f370a6
SF
3398 if (tcon->nativeFileSystem)
3399 cifs_strfromUCS_le(
3400 tcon->nativeFileSystem,
3401 (__le16 *) bcc_ptr,
3402 length, nls_codepage);
1da177e4
LT
3403 bcc_ptr += 2 * length;
3404 bcc_ptr[0] = 0; /* null terminate the string */
3405 bcc_ptr[1] = 0;
3406 bcc_ptr += 2;
3407 }
50c2f753 3408 /* else do not bother copying these information fields*/
1da177e4
LT
3409 } else {
3410 length = strnlen(bcc_ptr, 1024);
3411 if ((bcc_ptr + length) -
3412 pByteArea(smb_buffer_response) <=
3413 BCC(smb_buffer_response)) {
f99d49ad 3414 kfree(tcon->nativeFileSystem);
1da177e4 3415 tcon->nativeFileSystem =
e915fc49 3416 kzalloc(length + 1, GFP_KERNEL);
88f370a6
SF
3417 if (tcon->nativeFileSystem)
3418 strncpy(tcon->nativeFileSystem, bcc_ptr,
3419 length);
1da177e4 3420 }
50c2f753 3421 /* else do not bother copying these information fields*/
1da177e4 3422 }
fb8c4b14 3423 if ((smb_buffer_response->WordCount == 3) ||
1a4e15a0
SF
3424 (smb_buffer_response->WordCount == 7))
3425 /* field is in same location */
3979877e
SF
3426 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3427 else
3428 tcon->Flags = 0;
1da177e4
LT
3429 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3430 } else if ((rc == 0) && tcon == NULL) {
50c2f753 3431 /* all we need to save for IPC$ connection */
1da177e4
LT
3432 ses->ipc_tid = smb_buffer_response->Tid;
3433 }
3434
3435 if (smb_buffer)
3436 cifs_buf_release(smb_buffer);
3437 return rc;
3438}
3439
3440int
3441cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3442{
3443 int rc = 0;
3444 int xid;
3445 struct cifsSesInfo *ses = NULL;
3446 struct task_struct *cifsd_task;
50c2f753 3447 char *tmp;
1da177e4
LT
3448
3449 xid = GetXid();
3450
3451 if (cifs_sb->tcon) {
3452 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3453 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3454 if (rc == -EBUSY) {
3455 FreeXid(xid);
3456 return 0;
3457 }
3458 tconInfoFree(cifs_sb->tcon);
3459 if ((ses) && (ses->server)) {
3460 /* save off task so we do not refer to ses later */
3461 cifsd_task = ses->server->tsk;
3462 cFYI(1, ("About to do SMBLogoff "));
3463 rc = CIFSSMBLogoff(xid, ses);
3464 if (rc == -EBUSY) {
3465 FreeXid(xid);
3466 return 0;
3467 } else if (rc == -ESHUTDOWN) {
467a8f8d 3468 cFYI(1, ("Waking up socket by sending signal"));
f7f7c31c 3469 if (cifsd_task) {
50c2f753 3470 force_sig(SIGKILL, cifsd_task);
aaf737ad 3471 kthread_stop(cifsd_task);
f191401f 3472 }
1da177e4
LT
3473 rc = 0;
3474 } /* else - we have an smb session
3475 left on this socket do not kill cifsd */
3476 } else
3477 cFYI(1, ("No session or bad tcon"));
3478 }
50c2f753 3479
1da177e4 3480 cifs_sb->tcon = NULL;
2fe87f02
SF
3481 tmp = cifs_sb->prepath;
3482 cifs_sb->prepathlen = 0;
3483 cifs_sb->prepath = NULL;
3484 kfree(tmp);
041e0e3b
NA
3485 if (ses)
3486 schedule_timeout_interruptible(msecs_to_jiffies(500));
1da177e4
LT
3487 if (ses)
3488 sesInfoFree(ses);
3489
3490 FreeXid(xid);
50c2f753
SF
3491 return rc; /* BB check if we should always return zero here */
3492}
1da177e4
LT
3493
3494int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
50c2f753 3495 struct nls_table *nls_info)
1da177e4
LT
3496{
3497 int rc = 0;
7c7b25bc 3498 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
1da177e4 3499 int ntlmv2_flag = FALSE;
ad009ac9 3500 int first_time = 0;
1da177e4
LT
3501
3502 /* what if server changes its buffer size after dropping the session? */
fb8c4b14 3503 if (pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
1da177e4 3504 rc = CIFSSMBNegotiate(xid, pSesInfo);
fb8c4b14 3505 if (rc == -EAGAIN) /* retry only once on 1st time connection */ {
1da177e4 3506 rc = CIFSSMBNegotiate(xid, pSesInfo);
50c2f753 3507 if (rc == -EAGAIN)
1da177e4
LT
3508 rc = -EHOSTDOWN;
3509 }
fb8c4b14 3510 if (rc == 0) {
1da177e4 3511 spin_lock(&GlobalMid_Lock);
fb8c4b14 3512 if (pSesInfo->server->tcpStatus != CifsExiting)
1da177e4
LT
3513 pSesInfo->server->tcpStatus = CifsGood;
3514 else
3515 rc = -EHOSTDOWN;
3516 spin_unlock(&GlobalMid_Lock);
3517
3518 }
ad009ac9 3519 first_time = 1;
1da177e4
LT
3520 }
3521 if (!rc) {
9ac00b7d 3522 pSesInfo->flags = 0;
1da177e4 3523 pSesInfo->capabilities = pSesInfo->server->capabilities;
fb8c4b14 3524 if (linuxExtEnabled == 0)
1da177e4 3525 pSesInfo->capabilities &= (~CAP_UNIX);
ad009ac9 3526 /* pSesInfo->sequence_number = 0;*/
50c2f753
SF
3527 cFYI(1,
3528 ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
1da177e4
LT
3529 pSesInfo->server->secMode,
3530 pSesInfo->server->capabilities,
175ec9e1 3531 pSesInfo->server->timeAdj));
fb8c4b14 3532 if (experimEnabled < 2)
3979877e
SF
3533 rc = CIFS_SessSetup(xid, pSesInfo,
3534 first_time, nls_info);
189acaae 3535 else if (extended_security
50c2f753 3536 && (pSesInfo->capabilities
175ec9e1 3537 & CAP_EXTENDED_SECURITY)
1da177e4 3538 && (pSesInfo->server->secType == NTLMSSP)) {
189acaae 3539 rc = -EOPNOTSUPP;
1da177e4
LT
3540 } else if (extended_security
3541 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3542 && (pSesInfo->server->secType == RawNTLMSSP)) {
5815449d 3543 cFYI(1, ("NTLMSSP sesssetup"));
1da177e4
LT
3544 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3545 pSesInfo,
3546 &ntlmv2_flag,
3547 nls_info);
3548 if (!rc) {
fb8c4b14 3549 if (ntlmv2_flag) {
50c2f753 3550 char *v2_response;
467a8f8d 3551 cFYI(1, ("more secure NTLM ver2 hash"));
50c2f753 3552 if (CalcNTLMv2_partial_mac_key(pSesInfo,
1da177e4
LT
3553 nls_info)) {
3554 rc = -ENOMEM;
3555 goto ss_err_exit;
3556 } else
3557 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
fb8c4b14 3558 if (v2_response) {
50c2f753
SF
3559 CalcNTLMv2_response(pSesInfo,
3560 v2_response);
fb8c4b14 3561 /* if (first_time)
50c2f753
SF
3562 cifs_calculate_ntlmv2_mac_key(
3563 pSesInfo->server->mac_signing_key,
3564 response, ntlm_session_key,*/
1da177e4
LT
3565 kfree(v2_response);
3566 /* BB Put dummy sig in SessSetup PDU? */
3567 } else {
3568 rc = -ENOMEM;
3569 goto ss_err_exit;
3570 }
3571
3572 } else {
3573 SMBNTencrypt(pSesInfo->password,
3574 pSesInfo->server->cryptKey,
3575 ntlm_session_key);
3576
fb8c4b14 3577 if (first_time)
ad009ac9 3578 cifs_calculate_mac_key(
b609f06a 3579 &pSesInfo->server->mac_signing_key,
ad009ac9
SF
3580 ntlm_session_key,
3581 pSesInfo->password);
1da177e4
LT
3582 }
3583 /* for better security the weaker lanman hash not sent
3584 in AuthSessSetup so we no longer calculate it */
3585
3586 rc = CIFSNTLMSSPAuthSessSetup(xid,
3587 pSesInfo,
3588 ntlm_session_key,
3589 ntlmv2_flag,
3590 nls_info);
3591 }
3592 } else { /* old style NTLM 0.12 session setup */
3593 SMBNTencrypt(pSesInfo->password,
3594 pSesInfo->server->cryptKey,
3595 ntlm_session_key);
3596
fb8c4b14 3597 if (first_time)
ad009ac9 3598 cifs_calculate_mac_key(
b609f06a 3599 &pSesInfo->server->mac_signing_key,
ad009ac9
SF
3600 ntlm_session_key, pSesInfo->password);
3601
1da177e4
LT
3602 rc = CIFSSessSetup(xid, pSesInfo,
3603 ntlm_session_key, nls_info);
3604 }
3605 if (rc) {
fb8c4b14 3606 cERROR(1, ("Send error in SessSetup = %d", rc));
1da177e4 3607 } else {
467a8f8d 3608 cFYI(1, ("CIFS Session Established successfully"));
1da177e4
LT
3609 pSesInfo->status = CifsGood;
3610 }
3611 }
3612ss_err_exit:
3613 return rc;
3614}
3615