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