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