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