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