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