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