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