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