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