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