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