Freezer: make kernel threads nonfreezable by default
[linux-2.6/kmemtrace.git] / fs / cifs / connect.c
blob0a1b8bd1dfcbcf113274107b6ea3bb491bd03cd3
1 /*
2 * fs/cifs/connect.c
4 * Copyright (C) International Business Machines Corp., 2002,2006
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", server->ssocket->state,
165 server->ssocket->flags));
166 sock_release(server->ssocket);
167 server->ssocket = NULL;
170 spin_lock(&GlobalMid_Lock);
171 list_for_each(tmp, &server->pending_mid_q) {
172 mid_entry = list_entry(tmp, struct
173 mid_q_entry,
174 qhead);
175 if(mid_entry) {
176 if(mid_entry->midState == MID_REQUEST_SUBMITTED) {
177 /* Mark other intransit requests as needing
178 retry so we do not immediately mark the
179 session bad again (ie after we reconnect
180 below) as they timeout too */
181 mid_entry->midState = MID_RETRY_NEEDED;
185 spin_unlock(&GlobalMid_Lock);
186 up(&server->tcpSem);
188 while ( (!kthread_should_stop()) && (server->tcpStatus != CifsGood))
190 try_to_freeze();
191 if(server->protocolType == IPV6) {
192 rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket);
193 } else {
194 rc = ipv4_connect(&server->addr.sockAddr,
195 &server->ssocket,
196 server->workstation_RFC1001_name,
197 server->server_RFC1001_name);
199 if(rc) {
200 cFYI(1,("reconnect error %d",rc));
201 msleep(3000);
202 } else {
203 atomic_inc(&tcpSesReconnectCount);
204 spin_lock(&GlobalMid_Lock);
205 if( !kthread_should_stop() )
206 server->tcpStatus = CifsGood;
207 server->sequence_number = 0;
208 spin_unlock(&GlobalMid_Lock);
209 /* atomic_set(&server->inFlight,0);*/
210 wake_up(&server->response_q);
213 return rc;
217 return codes:
218 0 not a transact2, or all data present
219 >0 transact2 with that much data missing
220 -EINVAL = invalid transact2
223 static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize)
225 struct smb_t2_rsp * pSMBt;
226 int total_data_size;
227 int data_in_this_rsp;
228 int remaining;
230 if(pSMB->Command != SMB_COM_TRANSACTION2)
231 return 0;
233 /* check for plausible wct, bcc and t2 data and parm sizes */
234 /* check for parm and data offset going beyond end of smb */
235 if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */
236 cFYI(1,("invalid transact2 word count"));
237 return -EINVAL;
240 pSMBt = (struct smb_t2_rsp *)pSMB;
242 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
243 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
245 remaining = total_data_size - data_in_this_rsp;
247 if(remaining == 0)
248 return 0;
249 else if(remaining < 0) {
250 cFYI(1,("total data %d smaller than data in frame %d",
251 total_data_size, data_in_this_rsp));
252 return -EINVAL;
253 } else {
254 cFYI(1,("missing %d bytes from transact2, check next response",
255 remaining));
256 if(total_data_size > maxBufSize) {
257 cERROR(1,("TotalDataSize %d is over maximum buffer %d",
258 total_data_size,maxBufSize));
259 return -EINVAL;
261 return remaining;
265 static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB)
267 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
268 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
269 int total_data_size;
270 int total_in_buf;
271 int remaining;
272 int total_in_buf2;
273 char * data_area_of_target;
274 char * data_area_of_buf2;
275 __u16 byte_count;
277 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
279 if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
280 cFYI(1,("total data sizes of primary and secondary t2 differ"));
283 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
285 remaining = total_data_size - total_in_buf;
287 if(remaining < 0)
288 return -EINVAL;
290 if(remaining == 0) /* nothing to do, ignore */
291 return 0;
293 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
294 if(remaining < total_in_buf2) {
295 cFYI(1,("transact2 2nd response contains too much data"));
298 /* find end of first SMB data area */
299 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
300 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
301 /* validate target area */
303 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
304 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
306 data_area_of_target += total_in_buf;
308 /* copy second buffer into end of first buffer */
309 memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2);
310 total_in_buf += total_in_buf2;
311 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
312 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
313 byte_count += total_in_buf2;
314 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
316 byte_count = pTargetSMB->smb_buf_length;
317 byte_count += total_in_buf2;
319 /* BB also add check that we are not beyond maximum buffer size */
321 pTargetSMB->smb_buf_length = byte_count;
323 if(remaining == total_in_buf2) {
324 cFYI(1,("found the last secondary response"));
325 return 0; /* we are done */
326 } else /* more responses to go */
327 return 1;
331 static int
332 cifs_demultiplex_thread(struct TCP_Server_Info *server)
334 int length;
335 unsigned int pdu_length, total_read;
336 struct smb_hdr *smb_buffer = NULL;
337 struct smb_hdr *bigbuf = NULL;
338 struct smb_hdr *smallbuf = NULL;
339 struct msghdr smb_msg;
340 struct kvec iov;
341 struct socket *csocket = server->ssocket;
342 struct list_head *tmp;
343 struct cifsSesInfo *ses;
344 struct task_struct *task_to_wake = NULL;
345 struct mid_q_entry *mid_entry;
346 char temp;
347 int isLargeBuf = FALSE;
348 int isMultiRsp;
349 int reconnect;
351 allow_signal(SIGKILL);
352 current->flags |= PF_MEMALLOC;
353 server->tsk = current; /* save process info to wake at shutdown */
354 cFYI(1, ("Demultiplex PID: %d", current->pid));
355 write_lock(&GlobalSMBSeslock);
356 atomic_inc(&tcpSesAllocCount);
357 length = tcpSesAllocCount.counter;
358 write_unlock(&GlobalSMBSeslock);
359 complete(&cifsd_complete);
360 if(length > 1) {
361 mempool_resize(cifs_req_poolp,
362 length + cifs_min_rcv,
363 GFP_KERNEL);
366 set_freezable();
367 while (!kthread_should_stop()) {
368 if (try_to_freeze())
369 continue;
370 if (bigbuf == NULL) {
371 bigbuf = cifs_buf_get();
372 if (!bigbuf) {
373 cERROR(1, ("No memory for large SMB response"));
374 msleep(3000);
375 /* retry will check if exiting */
376 continue;
378 } else if (isLargeBuf) {
379 /* we are reusing a dirty large buf, clear its start */
380 memset(bigbuf, 0, sizeof (struct smb_hdr));
383 if (smallbuf == NULL) {
384 smallbuf = cifs_small_buf_get();
385 if (!smallbuf) {
386 cERROR(1, ("No memory for SMB response"));
387 msleep(1000);
388 /* retry will check if exiting */
389 continue;
391 /* beginning of smb buffer is cleared in our buf_get */
392 } else /* if existing small buf clear beginning */
393 memset(smallbuf, 0, sizeof (struct smb_hdr));
395 isLargeBuf = FALSE;
396 isMultiRsp = FALSE;
397 smb_buffer = smallbuf;
398 iov.iov_base = smb_buffer;
399 iov.iov_len = 4;
400 smb_msg.msg_control = NULL;
401 smb_msg.msg_controllen = 0;
402 length =
403 kernel_recvmsg(csocket, &smb_msg,
404 &iov, 1, 4, 0 /* BB see socket.h flags */);
406 if ( kthread_should_stop() ) {
407 break;
408 } else if (server->tcpStatus == CifsNeedReconnect) {
409 cFYI(1, ("Reconnect after server stopped responding"));
410 cifs_reconnect(server);
411 cFYI(1, ("call to reconnect done"));
412 csocket = server->ssocket;
413 continue;
414 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
415 msleep(1); /* minimum sleep to prevent looping
416 allowing socket to clear and app threads to set
417 tcpStatus CifsNeedReconnect if server hung */
418 continue;
419 } else if (length <= 0) {
420 if (server->tcpStatus == CifsNew) {
421 cFYI(1, ("tcp session abend after SMBnegprot"));
422 /* some servers kill the TCP session rather than
423 returning an SMB negprot error, in which
424 case reconnecting here is not going to help,
425 and so simply return error to mount */
426 break;
428 if (!try_to_freeze() && (length == -EINTR)) {
429 cFYI(1,("cifsd thread killed"));
430 break;
432 cFYI(1,("Reconnect after unexpected peek error %d",
433 length));
434 cifs_reconnect(server);
435 csocket = server->ssocket;
436 wake_up(&server->response_q);
437 continue;
438 } else if (length < 4) {
439 cFYI(1,
440 ("Frame under four bytes received (%d bytes long)",
441 length));
442 cifs_reconnect(server);
443 csocket = server->ssocket;
444 wake_up(&server->response_q);
445 continue;
448 /* The right amount was read from socket - 4 bytes */
449 /* so we can now interpret the length field */
451 /* the first byte big endian of the length field,
452 is actually not part of the length but the type
453 with the most common, zero, as regular data */
454 temp = *((char *) smb_buffer);
456 /* Note that FC 1001 length is big endian on the wire,
457 but we convert it here so it is always manipulated
458 as host byte order */
459 pdu_length = ntohl(smb_buffer->smb_buf_length);
460 smb_buffer->smb_buf_length = pdu_length;
462 cFYI(1,("rfc1002 length 0x%x)", pdu_length+4));
464 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
465 continue;
466 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
467 cFYI(1,("Good RFC 1002 session rsp"));
468 continue;
469 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
470 /* we get this from Windows 98 instead of
471 an error on SMB negprot response */
472 cFYI(1,("Negative RFC1002 Session Response Error 0x%x)",
473 pdu_length));
474 if(server->tcpStatus == CifsNew) {
475 /* if nack on negprot (rather than
476 ret of smb negprot error) reconnecting
477 not going to help, ret error to mount */
478 break;
479 } else {
480 /* give server a second to
481 clean up before reconnect attempt */
482 msleep(1000);
483 /* always try 445 first on reconnect
484 since we get NACK on some if we ever
485 connected to port 139 (the NACK is
486 since we do not begin with RFC1001
487 session initialize frame) */
488 server->addr.sockAddr.sin_port =
489 htons(CIFS_PORT);
490 cifs_reconnect(server);
491 csocket = server->ssocket;
492 wake_up(&server->response_q);
493 continue;
495 } else if (temp != (char) 0) {
496 cERROR(1,("Unknown RFC 1002 frame"));
497 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
498 length);
499 cifs_reconnect(server);
500 csocket = server->ssocket;
501 continue;
504 /* else we have an SMB response */
505 if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
506 (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) {
507 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
508 length, pdu_length+4));
509 cifs_reconnect(server);
510 csocket = server->ssocket;
511 wake_up(&server->response_q);
512 continue;
515 /* else length ok */
516 reconnect = 0;
518 if(pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
519 isLargeBuf = TRUE;
520 memcpy(bigbuf, smallbuf, 4);
521 smb_buffer = bigbuf;
523 length = 0;
524 iov.iov_base = 4 + (char *)smb_buffer;
525 iov.iov_len = pdu_length;
526 for (total_read = 0; total_read < pdu_length;
527 total_read += length) {
528 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
529 pdu_length - total_read, 0);
530 if( kthread_should_stop() ||
531 (length == -EINTR)) {
532 /* then will exit */
533 reconnect = 2;
534 break;
535 } else if (server->tcpStatus == CifsNeedReconnect) {
536 cifs_reconnect(server);
537 csocket = server->ssocket;
538 /* Reconnect wakes up rspns q */
539 /* Now we will reread sock */
540 reconnect = 1;
541 break;
542 } else if ((length == -ERESTARTSYS) ||
543 (length == -EAGAIN)) {
544 msleep(1); /* minimum sleep to prevent looping,
545 allowing socket to clear and app
546 threads to set tcpStatus
547 CifsNeedReconnect if server hung*/
548 continue;
549 } else if (length <= 0) {
550 cERROR(1,("Received no data, expecting %d",
551 pdu_length - total_read));
552 cifs_reconnect(server);
553 csocket = server->ssocket;
554 reconnect = 1;
555 break;
558 if(reconnect == 2)
559 break;
560 else if(reconnect == 1)
561 continue;
563 length += 4; /* account for rfc1002 hdr */
566 dump_smb(smb_buffer, length);
567 if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
568 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
569 continue;
573 task_to_wake = NULL;
574 spin_lock(&GlobalMid_Lock);
575 list_for_each(tmp, &server->pending_mid_q) {
576 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
578 if ((mid_entry->mid == smb_buffer->Mid) &&
579 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
580 (mid_entry->command == smb_buffer->Command)) {
581 if(check2ndT2(smb_buffer,server->maxBuf) > 0) {
582 /* We have a multipart transact2 resp */
583 isMultiRsp = TRUE;
584 if(mid_entry->resp_buf) {
585 /* merge response - fix up 1st*/
586 if(coalesce_t2(smb_buffer,
587 mid_entry->resp_buf)) {
588 mid_entry->multiRsp = 1;
589 break;
590 } else {
591 /* all parts received */
592 mid_entry->multiEnd = 1;
593 goto multi_t2_fnd;
595 } else {
596 if(!isLargeBuf) {
597 cERROR(1,("1st trans2 resp needs bigbuf"));
598 /* BB maybe we can fix this up, switch
599 to already allocated large buffer? */
600 } else {
601 /* Have first buffer */
602 mid_entry->resp_buf =
603 smb_buffer;
604 mid_entry->largeBuf = 1;
605 bigbuf = NULL;
608 break;
610 mid_entry->resp_buf = smb_buffer;
611 if(isLargeBuf)
612 mid_entry->largeBuf = 1;
613 else
614 mid_entry->largeBuf = 0;
615 multi_t2_fnd:
616 task_to_wake = mid_entry->tsk;
617 mid_entry->midState = MID_RESPONSE_RECEIVED;
618 #ifdef CONFIG_CIFS_STATS2
619 mid_entry->when_received = jiffies;
620 #endif
621 /* so we do not time out requests to server
622 which is still responding (since server could
623 be busy but not dead) */
624 server->lstrp = jiffies;
625 break;
628 spin_unlock(&GlobalMid_Lock);
629 if (task_to_wake) {
630 /* Was previous buf put in mpx struct for multi-rsp? */
631 if(!isMultiRsp) {
632 /* smb buffer will be freed by user thread */
633 if(isLargeBuf) {
634 bigbuf = NULL;
635 } else
636 smallbuf = NULL;
638 wake_up_process(task_to_wake);
639 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
640 && (isMultiRsp == FALSE)) {
641 cERROR(1, ("No task to wake, unknown frame rcvd! 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,
713 ("Clearing Mid 0x%x - waking up ",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,struct smb_vol *vol)
769 char *value;
770 char *data;
771 unsigned int temp_len, i, j;
772 char separator[2];
774 separator[0] = ',';
775 separator[1] = 0;
777 if (Local_System_Name[0] != 0)
778 memcpy(vol->source_rfc1001_name, Local_System_Name,15);
779 else {
780 char *nodename = utsname()->nodename;
781 int n = strnlen(nodename,15);
782 memset(vol->source_rfc1001_name,0x20,15);
783 for(i=0 ; i < n ; i++) {
784 /* does not have to be perfect mapping since field is
785 informational, only used for servers that do not support
786 port 445 and it can be overridden at mount time */
787 vol->source_rfc1001_name[i] = toupper(nodename[i]);
790 vol->source_rfc1001_name[15] = 0;
791 /* null target name indicates to use *SMBSERVR default called name
792 if we end up sending RFC1001 session initialize */
793 vol->target_rfc1001_name[0] = 0;
794 vol->linux_uid = current->uid; /* current->euid instead? */
795 vol->linux_gid = current->gid;
796 vol->dir_mode = S_IRWXUGO;
797 /* 2767 perms indicate mandatory locking support */
798 vol->file_mode = S_IALLUGO & ~(S_ISUID | S_IXGRP);
800 /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
801 vol->rw = TRUE;
802 /* default is always to request posix paths. */
803 vol->posix_paths = 1;
805 if (!options)
806 return 1;
808 if(strncmp(options,"sep=",4) == 0) {
809 if(options[4] != 0) {
810 separator[0] = options[4];
811 options += 5;
812 } else {
813 cFYI(1,("Null separator not allowed"));
817 while ((data = strsep(&options, separator)) != NULL) {
818 if (!*data)
819 continue;
820 if ((value = strchr(data, '=')) != NULL)
821 *value++ = '\0';
823 if (strnicmp(data, "user_xattr",10) == 0) {/*parse before user*/
824 vol->no_xattr = 0;
825 } else if (strnicmp(data, "nouser_xattr",12) == 0) {
826 vol->no_xattr = 1;
827 } else if (strnicmp(data, "user", 4) == 0) {
828 if (!value) {
829 printk(KERN_WARNING
830 "CIFS: invalid or missing username\n");
831 return 1; /* needs_arg; */
832 } else if(!*value) {
833 /* null user, ie anonymous, authentication */
834 vol->nullauth = 1;
836 if (strnlen(value, 200) < 200) {
837 vol->username = value;
838 } else {
839 printk(KERN_WARNING "CIFS: username too long\n");
840 return 1;
842 } else if (strnicmp(data, "pass", 4) == 0) {
843 if (!value) {
844 vol->password = NULL;
845 continue;
846 } else if(value[0] == 0) {
847 /* check if string begins with double comma
848 since that would mean the password really
849 does start with a comma, and would not
850 indicate an empty string */
851 if(value[1] != separator[0]) {
852 vol->password = NULL;
853 continue;
856 temp_len = strlen(value);
857 /* removed password length check, NTLM passwords
858 can be arbitrarily long */
860 /* if comma in password, the string will be
861 prematurely null terminated. Commas in password are
862 specified across the cifs mount interface by a double
863 comma ie ,, and a comma used as in other cases ie ','
864 as a parameter delimiter/separator is single and due
865 to the strsep above is temporarily zeroed. */
867 /* NB: password legally can have multiple commas and
868 the only illegal character in a password is null */
870 if ((value[temp_len] == 0) &&
871 (value[temp_len+1] == separator[0])) {
872 /* reinsert comma */
873 value[temp_len] = separator[0];
874 temp_len+=2; /* move after the second comma */
875 while(value[temp_len] != 0) {
876 if (value[temp_len] == separator[0]) {
877 if (value[temp_len+1] ==
878 separator[0]) {
879 /* skip second comma */
880 temp_len++;
881 } else {
882 /* single comma indicating start
883 of next parm */
884 break;
887 temp_len++;
889 if(value[temp_len] == 0) {
890 options = NULL;
891 } else {
892 value[temp_len] = 0;
893 /* point option to start of next parm */
894 options = value + temp_len + 1;
896 /* go from value to value + temp_len condensing
897 double commas to singles. Note that this ends up
898 allocating a few bytes too many, which is ok */
899 vol->password = kzalloc(temp_len, GFP_KERNEL);
900 if(vol->password == NULL) {
901 printk("CIFS: no memory for pass\n");
902 return 1;
904 for(i=0,j=0;i<temp_len;i++,j++) {
905 vol->password[j] = value[i];
906 if(value[i] == separator[0]
907 && value[i+1] == separator[0]) {
908 /* skip second comma */
909 i++;
912 vol->password[j] = 0;
913 } else {
914 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
915 if(vol->password == NULL) {
916 printk("CIFS: no memory for pass\n");
917 return 1;
919 strcpy(vol->password, value);
921 } else if (strnicmp(data, "ip", 2) == 0) {
922 if (!value || !*value) {
923 vol->UNCip = NULL;
924 } else if (strnlen(value, 35) < 35) {
925 vol->UNCip = value;
926 } else {
927 printk(KERN_WARNING "CIFS: ip address too long\n");
928 return 1;
930 } else if (strnicmp(data, "sec", 3) == 0) {
931 if (!value || !*value) {
932 cERROR(1,("no security value specified"));
933 continue;
934 } else if (strnicmp(value, "krb5i", 5) == 0) {
935 vol->secFlg |= CIFSSEC_MAY_KRB5 |
936 CIFSSEC_MUST_SIGN;
937 } else if (strnicmp(value, "krb5p", 5) == 0) {
938 /* vol->secFlg |= CIFSSEC_MUST_SEAL |
939 CIFSSEC_MAY_KRB5; */
940 cERROR(1,("Krb5 cifs privacy not supported"));
941 return 1;
942 } else if (strnicmp(value, "krb5", 4) == 0) {
943 vol->secFlg |= CIFSSEC_MAY_KRB5;
944 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
945 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
946 CIFSSEC_MUST_SIGN;
947 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
948 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
949 } else if (strnicmp(value, "ntlmi", 5) == 0) {
950 vol->secFlg |= CIFSSEC_MAY_NTLM |
951 CIFSSEC_MUST_SIGN;
952 } else if (strnicmp(value, "ntlm", 4) == 0) {
953 /* ntlm is default so can be turned off too */
954 vol->secFlg |= CIFSSEC_MAY_NTLM;
955 } else if (strnicmp(value, "nontlm", 6) == 0) {
956 /* BB is there a better way to do this? */
957 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
958 #ifdef CONFIG_CIFS_WEAK_PW_HASH
959 } else if (strnicmp(value, "lanman", 6) == 0) {
960 vol->secFlg |= CIFSSEC_MAY_LANMAN;
961 #endif
962 } else if (strnicmp(value, "none", 4) == 0) {
963 vol->nullauth = 1;
964 } else {
965 cERROR(1,("bad security option: %s", value));
966 return 1;
968 } else if ((strnicmp(data, "unc", 3) == 0)
969 || (strnicmp(data, "target", 6) == 0)
970 || (strnicmp(data, "path", 4) == 0)) {
971 if (!value || !*value) {
972 printk(KERN_WARNING
973 "CIFS: invalid path to network resource\n");
974 return 1; /* needs_arg; */
976 if ((temp_len = strnlen(value, 300)) < 300) {
977 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
978 if (vol->UNC == NULL)
979 return 1;
980 strcpy(vol->UNC,value);
981 if (strncmp(vol->UNC, "//", 2) == 0) {
982 vol->UNC[0] = '\\';
983 vol->UNC[1] = '\\';
984 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
985 printk(KERN_WARNING
986 "CIFS: UNC Path does not begin with // or \\\\ \n");
987 return 1;
989 } else {
990 printk(KERN_WARNING "CIFS: UNC name too long\n");
991 return 1;
993 } else if ((strnicmp(data, "domain", 3) == 0)
994 || (strnicmp(data, "workgroup", 5) == 0)) {
995 if (!value || !*value) {
996 printk(KERN_WARNING "CIFS: invalid domain name\n");
997 return 1; /* needs_arg; */
999 /* BB are there cases in which a comma can be valid in
1000 a domain name and need special handling? */
1001 if (strnlen(value, 256) < 256) {
1002 vol->domainname = value;
1003 cFYI(1, ("Domain name set"));
1004 } else {
1005 printk(KERN_WARNING "CIFS: domain name too long\n");
1006 return 1;
1008 } else if (strnicmp(data, "prefixpath", 10) == 0) {
1009 if (!value || !*value) {
1010 printk(KERN_WARNING
1011 "CIFS: invalid path prefix\n");
1012 return 1; /* needs_arg; */
1014 if ((temp_len = strnlen(value, 1024)) < 1024) {
1015 if (value[0] != '/')
1016 temp_len++; /* missing leading slash */
1017 vol->prepath = kmalloc(temp_len+1,GFP_KERNEL);
1018 if (vol->prepath == NULL)
1019 return 1;
1020 if (value[0] != '/') {
1021 vol->prepath[0] = '/';
1022 strcpy(vol->prepath+1,value);
1023 } else
1024 strcpy(vol->prepath,value);
1025 cFYI(1,("prefix path %s",vol->prepath));
1026 } else {
1027 printk(KERN_WARNING "CIFS: prefix too long\n");
1028 return 1;
1030 } else if (strnicmp(data, "iocharset", 9) == 0) {
1031 if (!value || !*value) {
1032 printk(KERN_WARNING "CIFS: invalid iocharset specified\n");
1033 return 1; /* needs_arg; */
1035 if (strnlen(value, 65) < 65) {
1036 if (strnicmp(value,"default",7))
1037 vol->iocharset = value;
1038 /* if iocharset not set load_nls_default used by caller */
1039 cFYI(1, ("iocharset set to %s",value));
1040 } else {
1041 printk(KERN_WARNING "CIFS: iocharset name too long.\n");
1042 return 1;
1044 } else if (strnicmp(data, "uid", 3) == 0) {
1045 if (value && *value) {
1046 vol->linux_uid =
1047 simple_strtoul(value, &value, 0);
1048 vol->override_uid = 1;
1050 } else if (strnicmp(data, "gid", 3) == 0) {
1051 if (value && *value) {
1052 vol->linux_gid =
1053 simple_strtoul(value, &value, 0);
1054 vol->override_gid = 1;
1056 } else if (strnicmp(data, "file_mode", 4) == 0) {
1057 if (value && *value) {
1058 vol->file_mode =
1059 simple_strtoul(value, &value, 0);
1061 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1062 if (value && *value) {
1063 vol->dir_mode =
1064 simple_strtoul(value, &value, 0);
1066 } else if (strnicmp(data, "dirmode", 4) == 0) {
1067 if (value && *value) {
1068 vol->dir_mode =
1069 simple_strtoul(value, &value, 0);
1071 } else if (strnicmp(data, "port", 4) == 0) {
1072 if (value && *value) {
1073 vol->port =
1074 simple_strtoul(value, &value, 0);
1076 } else if (strnicmp(data, "rsize", 5) == 0) {
1077 if (value && *value) {
1078 vol->rsize =
1079 simple_strtoul(value, &value, 0);
1081 } else if (strnicmp(data, "wsize", 5) == 0) {
1082 if (value && *value) {
1083 vol->wsize =
1084 simple_strtoul(value, &value, 0);
1086 } else if (strnicmp(data, "sockopt", 5) == 0) {
1087 if (value && *value) {
1088 vol->sockopt =
1089 simple_strtoul(value, &value, 0);
1091 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1092 if (!value || !*value || (*value == ' ')) {
1093 cFYI(1,("invalid (empty) netbiosname specified"));
1094 } else {
1095 memset(vol->source_rfc1001_name,0x20,15);
1096 for(i=0;i<15;i++) {
1097 /* BB are there cases in which a comma can be
1098 valid in this workstation netbios name (and need
1099 special handling)? */
1101 /* We do not uppercase netbiosname for user */
1102 if (value[i]==0)
1103 break;
1104 else
1105 vol->source_rfc1001_name[i] = value[i];
1107 /* The string has 16th byte zero still from
1108 set at top of the function */
1109 if ((i==15) && (value[i] != 0))
1110 printk(KERN_WARNING "CIFS: netbiosname longer than 15 truncated.\n");
1112 } else if (strnicmp(data, "servern", 7) == 0) {
1113 /* servernetbiosname specified override *SMBSERVER */
1114 if (!value || !*value || (*value == ' ')) {
1115 cFYI(1,("empty server netbiosname specified"));
1116 } else {
1117 /* last byte, type, is 0x20 for servr type */
1118 memset(vol->target_rfc1001_name,0x20,16);
1120 for(i=0;i<15;i++) {
1121 /* BB are there cases in which a comma can be
1122 valid in this workstation netbios name (and need
1123 special handling)? */
1125 /* user or mount helper must uppercase netbiosname */
1126 if (value[i]==0)
1127 break;
1128 else
1129 vol->target_rfc1001_name[i] = value[i];
1131 /* The string has 16th byte zero still from
1132 set at top of the function */
1133 if ((i==15) && (value[i] != 0))
1134 printk(KERN_WARNING "CIFS: server netbiosname longer than 15 truncated.\n");
1136 } else if (strnicmp(data, "credentials", 4) == 0) {
1137 /* ignore */
1138 } else if (strnicmp(data, "version", 3) == 0) {
1139 /* ignore */
1140 } else if (strnicmp(data, "guest",5) == 0) {
1141 /* ignore */
1142 } else if (strnicmp(data, "rw", 2) == 0) {
1143 vol->rw = TRUE;
1144 } else if ((strnicmp(data, "suid", 4) == 0) ||
1145 (strnicmp(data, "nosuid", 6) == 0) ||
1146 (strnicmp(data, "exec", 4) == 0) ||
1147 (strnicmp(data, "noexec", 6) == 0) ||
1148 (strnicmp(data, "nodev", 5) == 0) ||
1149 (strnicmp(data, "noauto", 6) == 0) ||
1150 (strnicmp(data, "dev", 3) == 0)) {
1151 /* The mount tool or mount.cifs helper (if present)
1152 uses these opts to set flags, and the flags are read
1153 by the kernel vfs layer before we get here (ie
1154 before read super) so there is no point trying to
1155 parse these options again and set anything and it
1156 is ok to just ignore them */
1157 continue;
1158 } else if (strnicmp(data, "ro", 2) == 0) {
1159 vol->rw = FALSE;
1160 } else if (strnicmp(data, "hard", 4) == 0) {
1161 vol->retry = 1;
1162 } else if (strnicmp(data, "soft", 4) == 0) {
1163 vol->retry = 0;
1164 } else if (strnicmp(data, "perm", 4) == 0) {
1165 vol->noperm = 0;
1166 } else if (strnicmp(data, "noperm", 6) == 0) {
1167 vol->noperm = 1;
1168 } else if (strnicmp(data, "mapchars", 8) == 0) {
1169 vol->remap = 1;
1170 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1171 vol->remap = 0;
1172 } else if (strnicmp(data, "sfu", 3) == 0) {
1173 vol->sfu_emul = 1;
1174 } else if (strnicmp(data, "nosfu", 5) == 0) {
1175 vol->sfu_emul = 0;
1176 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1177 vol->posix_paths = 1;
1178 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1179 vol->posix_paths = 0;
1180 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1181 (strnicmp(data, "ignorecase", 10) == 0)) {
1182 vol->nocase = 1;
1183 } else if (strnicmp(data, "brl", 3) == 0) {
1184 vol->nobrl = 0;
1185 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1186 (strnicmp(data, "nolock", 6) == 0)) {
1187 vol->nobrl = 1;
1188 /* turn off mandatory locking in mode
1189 if remote locking is turned off since the
1190 local vfs will do advisory */
1191 if(vol->file_mode == (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1192 vol->file_mode = S_IALLUGO;
1193 } else if (strnicmp(data, "setuids", 7) == 0) {
1194 vol->setuids = 1;
1195 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1196 vol->setuids = 0;
1197 } else if (strnicmp(data, "nohard", 6) == 0) {
1198 vol->retry = 0;
1199 } else if (strnicmp(data, "nosoft", 6) == 0) {
1200 vol->retry = 1;
1201 } else if (strnicmp(data, "nointr", 6) == 0) {
1202 vol->intr = 0;
1203 } else if (strnicmp(data, "intr", 4) == 0) {
1204 vol->intr = 1;
1205 } else if (strnicmp(data, "serverino",7) == 0) {
1206 vol->server_ino = 1;
1207 } else if (strnicmp(data, "noserverino",9) == 0) {
1208 vol->server_ino = 0;
1209 } else if (strnicmp(data, "cifsacl",7) == 0) {
1210 vol->cifs_acl = 1;
1211 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1212 vol->cifs_acl = 0;
1213 } else if (strnicmp(data, "acl",3) == 0) {
1214 vol->no_psx_acl = 0;
1215 } else if (strnicmp(data, "noacl",5) == 0) {
1216 vol->no_psx_acl = 1;
1217 } else if (strnicmp(data, "sign",4) == 0) {
1218 vol->secFlg |= CIFSSEC_MUST_SIGN;
1219 /* } else if (strnicmp(data, "seal",4) == 0) {
1220 vol->secFlg |= CIFSSEC_MUST_SEAL; */
1221 } else if (strnicmp(data, "direct",6) == 0) {
1222 vol->direct_io = 1;
1223 } else if (strnicmp(data, "forcedirectio",13) == 0) {
1224 vol->direct_io = 1;
1225 } else if (strnicmp(data, "in6_addr",8) == 0) {
1226 if (!value || !*value) {
1227 vol->in6_addr = NULL;
1228 } else if (strnlen(value, 49) == 48) {
1229 vol->in6_addr = value;
1230 } else {
1231 printk(KERN_WARNING "CIFS: ip v6 address not 48 characters long\n");
1232 return 1;
1234 } else if (strnicmp(data, "noac", 4) == 0) {
1235 printk(KERN_WARNING "CIFS: Mount option noac not supported. Instead set /proc/fs/cifs/LookupCacheEnabled to 0\n");
1236 } else
1237 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",data);
1239 if (vol->UNC == NULL) {
1240 if (devname == NULL) {
1241 printk(KERN_WARNING "CIFS: Missing UNC name for mount target\n");
1242 return 1;
1244 if ((temp_len = strnlen(devname, 300)) < 300) {
1245 vol->UNC = kmalloc(temp_len+1,GFP_KERNEL);
1246 if (vol->UNC == NULL)
1247 return 1;
1248 strcpy(vol->UNC,devname);
1249 if (strncmp(vol->UNC, "//", 2) == 0) {
1250 vol->UNC[0] = '\\';
1251 vol->UNC[1] = '\\';
1252 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1253 printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n");
1254 return 1;
1256 } else {
1257 printk(KERN_WARNING "CIFS: UNC name too long\n");
1258 return 1;
1261 if(vol->UNCip == NULL)
1262 vol->UNCip = &vol->UNC[2];
1264 return 0;
1267 static struct cifsSesInfo *
1268 cifs_find_tcp_session(struct in_addr * target_ip_addr,
1269 struct in6_addr *target_ip6_addr,
1270 char *userName, struct TCP_Server_Info **psrvTcp)
1272 struct list_head *tmp;
1273 struct cifsSesInfo *ses;
1274 *psrvTcp = NULL;
1275 read_lock(&GlobalSMBSeslock);
1277 list_for_each(tmp, &GlobalSMBSessionList) {
1278 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1279 if (ses->server) {
1280 if((target_ip_addr &&
1281 (ses->server->addr.sockAddr.sin_addr.s_addr
1282 == target_ip_addr->s_addr)) || (target_ip6_addr
1283 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1284 target_ip6_addr,sizeof(*target_ip6_addr)))){
1285 /* BB lock server and tcp session and increment use count here?? */
1286 *psrvTcp = ses->server; /* found a match on the TCP session */
1287 /* BB check if reconnection needed */
1288 if (strncmp
1289 (ses->userName, userName,
1290 MAX_USERNAME_SIZE) == 0){
1291 read_unlock(&GlobalSMBSeslock);
1292 return ses; /* found exact match on both tcp and SMB sessions */
1296 /* else tcp and smb sessions need reconnection */
1298 read_unlock(&GlobalSMBSeslock);
1299 return NULL;
1302 static struct cifsTconInfo *
1303 find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1305 struct list_head *tmp;
1306 struct cifsTconInfo *tcon;
1308 read_lock(&GlobalSMBSeslock);
1309 list_for_each(tmp, &GlobalTreeConnectionList) {
1310 cFYI(1, ("Next tcon"));
1311 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1312 if (tcon->ses) {
1313 if (tcon->ses->server) {
1314 cFYI(1,
1315 ("old ip addr: %x == new ip %x ?",
1316 tcon->ses->server->addr.sockAddr.sin_addr.
1317 s_addr, new_target_ip_addr));
1318 if (tcon->ses->server->addr.sockAddr.sin_addr.
1319 s_addr == new_target_ip_addr) {
1320 /* BB lock tcon, server and tcp session and increment use count here? */
1321 /* found a match on the TCP session */
1322 /* BB check if reconnection needed */
1323 cFYI(1,("IP match, old UNC: %s new: %s",
1324 tcon->treeName, uncName));
1325 if (strncmp
1326 (tcon->treeName, uncName,
1327 MAX_TREE_SIZE) == 0) {
1328 cFYI(1,
1329 ("and old usr: %s new: %s",
1330 tcon->treeName, uncName));
1331 if (strncmp
1332 (tcon->ses->userName,
1333 userName,
1334 MAX_USERNAME_SIZE) == 0) {
1335 read_unlock(&GlobalSMBSeslock);
1336 /* matched smb session
1337 (user name */
1338 return tcon;
1345 read_unlock(&GlobalSMBSeslock);
1346 return NULL;
1350 connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1351 const char *old_path, const struct nls_table *nls_codepage,
1352 int remap)
1354 unsigned char *referrals = NULL;
1355 unsigned int num_referrals;
1356 int rc = 0;
1358 rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage,
1359 &num_referrals, &referrals, remap);
1361 /* BB Add in code to: if valid refrl, if not ip address contact
1362 the helper that resolves tcp names, mount to it, try to
1363 tcon to it unmount it if fail */
1365 kfree(referrals);
1367 return rc;
1371 get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1372 const char *old_path, const struct nls_table *nls_codepage,
1373 unsigned int *pnum_referrals,
1374 unsigned char ** preferrals, int remap)
1376 char *temp_unc;
1377 int rc = 0;
1379 *pnum_referrals = 0;
1381 if (pSesInfo->ipc_tid == 0) {
1382 temp_unc = kmalloc(2 /* for slashes */ +
1383 strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2)
1384 + 1 + 4 /* slash IPC$ */ + 2,
1385 GFP_KERNEL);
1386 if (temp_unc == NULL)
1387 return -ENOMEM;
1388 temp_unc[0] = '\\';
1389 temp_unc[1] = '\\';
1390 strcpy(temp_unc + 2, pSesInfo->serverName);
1391 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1392 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1393 cFYI(1,
1394 ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid));
1395 kfree(temp_unc);
1397 if (rc == 0)
1398 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1399 pnum_referrals, nls_codepage, remap);
1401 return rc;
1404 /* See RFC1001 section 14 on representation of Netbios names */
1405 static void rfc1002mangle(char * target,char * source, unsigned int length)
1407 unsigned int i,j;
1409 for(i=0,j=0;i<(length);i++) {
1410 /* mask a nibble at a time and encode */
1411 target[j] = 'A' + (0x0F & (source[i] >> 4));
1412 target[j+1] = 'A' + (0x0F & source[i]);
1413 j+=2;
1419 static int
1420 ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1421 char * netbios_name, char * target_name)
1423 int rc = 0;
1424 int connected = 0;
1425 __be16 orig_port = 0;
1427 if(*csocket == NULL) {
1428 rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, csocket);
1429 if (rc < 0) {
1430 cERROR(1, ("Error %d creating socket",rc));
1431 *csocket = NULL;
1432 return rc;
1433 } else {
1434 /* BB other socket options to set KEEPALIVE, NODELAY? */
1435 cFYI(1,("Socket created"));
1436 (*csocket)->sk->sk_allocation = GFP_NOFS;
1440 psin_server->sin_family = AF_INET;
1441 if(psin_server->sin_port) { /* user overrode default port */
1442 rc = (*csocket)->ops->connect(*csocket,
1443 (struct sockaddr *) psin_server,
1444 sizeof (struct sockaddr_in),0);
1445 if (rc >= 0)
1446 connected = 1;
1449 if(!connected) {
1450 /* save original port so we can retry user specified port
1451 later if fall back ports fail this time */
1452 orig_port = psin_server->sin_port;
1454 /* do not retry on the same port we just failed on */
1455 if(psin_server->sin_port != htons(CIFS_PORT)) {
1456 psin_server->sin_port = htons(CIFS_PORT);
1458 rc = (*csocket)->ops->connect(*csocket,
1459 (struct sockaddr *) psin_server,
1460 sizeof (struct sockaddr_in),0);
1461 if (rc >= 0)
1462 connected = 1;
1465 if (!connected) {
1466 psin_server->sin_port = htons(RFC1001_PORT);
1467 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1468 psin_server, sizeof (struct sockaddr_in),0);
1469 if (rc >= 0)
1470 connected = 1;
1473 /* give up here - unless we want to retry on different
1474 protocol families some day */
1475 if (!connected) {
1476 if(orig_port)
1477 psin_server->sin_port = orig_port;
1478 cFYI(1,("Error %d connecting to server via ipv4",rc));
1479 sock_release(*csocket);
1480 *csocket = NULL;
1481 return rc;
1483 /* Eventually check for other socket options to change from
1484 the default. sock_setsockopt not used because it expects
1485 user space buffer */
1486 cFYI(1,("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",(*csocket)->sk->sk_sndbuf,
1487 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1488 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1489 /* make the bufsizes depend on wsize/rsize and max requests */
1490 if((*csocket)->sk->sk_sndbuf < (200 * 1024))
1491 (*csocket)->sk->sk_sndbuf = 200 * 1024;
1492 if((*csocket)->sk->sk_rcvbuf < (140 * 1024))
1493 (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1495 /* send RFC1001 sessinit */
1496 if(psin_server->sin_port == htons(RFC1001_PORT)) {
1497 /* some servers require RFC1001 sessinit before sending
1498 negprot - BB check reconnection in case where second
1499 sessinit is sent but no second negprot */
1500 struct rfc1002_session_packet * ses_init_buf;
1501 struct smb_hdr * smb_buf;
1502 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL);
1503 if(ses_init_buf) {
1504 ses_init_buf->trailer.session_req.called_len = 32;
1505 if(target_name && (target_name[0] != 0)) {
1506 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1507 target_name, 16);
1508 } else {
1509 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1510 DEFAULT_CIFS_CALLED_NAME,16);
1513 ses_init_buf->trailer.session_req.calling_len = 32;
1514 /* calling name ends in null (byte 16) from old smb
1515 convention. */
1516 if(netbios_name && (netbios_name[0] !=0)) {
1517 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1518 netbios_name,16);
1519 } else {
1520 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1521 "LINUX_CIFS_CLNT",16);
1523 ses_init_buf->trailer.session_req.scope1 = 0;
1524 ses_init_buf->trailer.session_req.scope2 = 0;
1525 smb_buf = (struct smb_hdr *)ses_init_buf;
1526 /* sizeof RFC1002_SESSION_REQUEST with no scope */
1527 smb_buf->smb_buf_length = 0x81000044;
1528 rc = smb_send(*csocket, smb_buf, 0x44,
1529 (struct sockaddr *)psin_server);
1530 kfree(ses_init_buf);
1531 msleep(1); /* RFC1001 layer in at least one server
1532 requires very short break before negprot
1533 presumably because not expecting negprot
1534 to follow so fast. This is a simple
1535 solution that works without
1536 complicating the code and causes no
1537 significant slowing down on mount
1538 for everyone else */
1540 /* else the negprot may still work without this
1541 even though malloc failed */
1545 return rc;
1548 static int
1549 ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1551 int rc = 0;
1552 int connected = 0;
1553 __be16 orig_port = 0;
1555 if(*csocket == NULL) {
1556 rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, csocket);
1557 if (rc < 0) {
1558 cERROR(1, ("Error %d creating ipv6 socket",rc));
1559 *csocket = NULL;
1560 return rc;
1561 } else {
1562 /* BB other socket options to set KEEPALIVE, NODELAY? */
1563 cFYI(1,("ipv6 Socket created"));
1564 (*csocket)->sk->sk_allocation = GFP_NOFS;
1568 psin_server->sin6_family = AF_INET6;
1570 if(psin_server->sin6_port) { /* user overrode default port */
1571 rc = (*csocket)->ops->connect(*csocket,
1572 (struct sockaddr *) psin_server,
1573 sizeof (struct sockaddr_in6),0);
1574 if (rc >= 0)
1575 connected = 1;
1578 if(!connected) {
1579 /* save original port so we can retry user specified port
1580 later if fall back ports fail this time */
1582 orig_port = psin_server->sin6_port;
1583 /* do not retry on the same port we just failed on */
1584 if(psin_server->sin6_port != htons(CIFS_PORT)) {
1585 psin_server->sin6_port = htons(CIFS_PORT);
1587 rc = (*csocket)->ops->connect(*csocket,
1588 (struct sockaddr *) psin_server,
1589 sizeof (struct sockaddr_in6),0);
1590 if (rc >= 0)
1591 connected = 1;
1594 if (!connected) {
1595 psin_server->sin6_port = htons(RFC1001_PORT);
1596 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1597 psin_server, sizeof (struct sockaddr_in6),0);
1598 if (rc >= 0)
1599 connected = 1;
1602 /* give up here - unless we want to retry on different
1603 protocol families some day */
1604 if (!connected) {
1605 if(orig_port)
1606 psin_server->sin6_port = orig_port;
1607 cFYI(1,("Error %d connecting to server via ipv6",rc));
1608 sock_release(*csocket);
1609 *csocket = NULL;
1610 return rc;
1612 /* Eventually check for other socket options to change from
1613 the default. sock_setsockopt not used because it expects
1614 user space buffer */
1615 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1617 return rc;
1620 void reset_cifs_unix_caps(int xid, struct cifsTconInfo * tcon,
1621 struct super_block * sb, struct smb_vol * vol_info)
1623 /* if we are reconnecting then should we check to see if
1624 * any requested capabilities changed locally e.g. via
1625 * remount but we can not do much about it here
1626 * if they have (even if we could detect it by the following)
1627 * Perhaps we could add a backpointer to array of sb from tcon
1628 * or if we change to make all sb to same share the same
1629 * sb as NFS - then we only have one backpointer to sb.
1630 * What if we wanted to mount the server share twice once with
1631 * and once without posixacls or posix paths? */
1632 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1635 if(!CIFSSMBQFSUnixInfo(xid, tcon)) {
1636 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1638 /* check for reconnect case in which we do not
1639 want to change the mount behavior if we can avoid it */
1640 if(vol_info == NULL) {
1641 /* turn off POSIX ACL and PATHNAMES if not set
1642 originally at mount time */
1643 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
1644 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1645 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
1646 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1653 cap &= CIFS_UNIX_CAP_MASK;
1654 if(vol_info && vol_info->no_psx_acl)
1655 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1656 else if(CIFS_UNIX_POSIX_ACL_CAP & cap) {
1657 cFYI(1,("negotiated posix acl support"));
1658 if(sb)
1659 sb->s_flags |= MS_POSIXACL;
1662 if(vol_info && vol_info->posix_paths == 0)
1663 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1664 else if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
1665 cFYI(1,("negotiate posix pathnames"));
1666 if(sb)
1667 CIFS_SB(sb)->mnt_cifs_flags |=
1668 CIFS_MOUNT_POSIX_PATHS;
1671 /* We might be setting the path sep back to a different
1672 form if we are reconnecting and the server switched its
1673 posix path capability for this share */
1674 if(sb && (CIFS_SB(sb)->prepathlen > 0))
1675 CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
1677 cFYI(1,("Negotiate caps 0x%x",(int)cap));
1678 #ifdef CONFIG_CIFS_DEBUG2
1679 if(cap & CIFS_UNIX_FCNTL_CAP)
1680 cFYI(1,("FCNTL cap"));
1681 if(cap & CIFS_UNIX_EXTATTR_CAP)
1682 cFYI(1,("EXTATTR cap"));
1683 if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
1684 cFYI(1,("POSIX path cap"));
1685 if(cap & CIFS_UNIX_XATTR_CAP)
1686 cFYI(1,("XATTR cap"));
1687 if(cap & CIFS_UNIX_POSIX_ACL_CAP)
1688 cFYI(1,("POSIX ACL cap"));
1689 #endif /* CIFS_DEBUG2 */
1690 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1691 cFYI(1,("setting capabilities failed"));
1697 cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1698 char *mount_data, const char *devname)
1700 int rc = 0;
1701 int xid;
1702 int address_type = AF_INET;
1703 struct socket *csocket = NULL;
1704 struct sockaddr_in sin_server;
1705 struct sockaddr_in6 sin_server6;
1706 struct smb_vol volume_info;
1707 struct cifsSesInfo *pSesInfo = NULL;
1708 struct cifsSesInfo *existingCifsSes = NULL;
1709 struct cifsTconInfo *tcon = NULL;
1710 struct TCP_Server_Info *srvTcp = NULL;
1712 xid = GetXid();
1714 /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */
1716 memset(&volume_info,0,sizeof(struct smb_vol));
1717 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1718 kfree(volume_info.UNC);
1719 kfree(volume_info.password);
1720 kfree(volume_info.prepath);
1721 FreeXid(xid);
1722 return -EINVAL;
1725 if (volume_info.nullauth) {
1726 cFYI(1,("null user"));
1727 volume_info.username = NULL;
1728 } else if (volume_info.username) {
1729 /* BB fixme parse for domain name here */
1730 cFYI(1, ("Username: %s ", volume_info.username));
1731 } else {
1732 cifserror("No username specified");
1733 /* In userspace mount helper we can get user name from alternate
1734 locations such as env variables and files on disk */
1735 kfree(volume_info.UNC);
1736 kfree(volume_info.password);
1737 kfree(volume_info.prepath);
1738 FreeXid(xid);
1739 return -EINVAL;
1742 if (volume_info.UNCip && volume_info.UNC) {
1743 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,&sin_server.sin_addr.s_addr);
1745 if(rc <= 0) {
1746 /* not ipv4 address, try ipv6 */
1747 rc = cifs_inet_pton(AF_INET6,volume_info.UNCip,&sin_server6.sin6_addr.in6_u);
1748 if(rc > 0)
1749 address_type = AF_INET6;
1750 } else {
1751 address_type = AF_INET;
1754 if(rc <= 0) {
1755 /* we failed translating address */
1756 kfree(volume_info.UNC);
1757 kfree(volume_info.password);
1758 kfree(volume_info.prepath);
1759 FreeXid(xid);
1760 return -EINVAL;
1763 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1764 /* success */
1765 rc = 0;
1766 } else if (volume_info.UNCip){
1767 /* BB using ip addr as server name connect to the DFS root below */
1768 cERROR(1,("Connecting to DFS root not implemented yet"));
1769 kfree(volume_info.UNC);
1770 kfree(volume_info.password);
1771 kfree(volume_info.prepath);
1772 FreeXid(xid);
1773 return -EINVAL;
1774 } else /* which servers DFS root would we conect to */ {
1775 cERROR(1,
1776 ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified"));
1777 kfree(volume_info.UNC);
1778 kfree(volume_info.password);
1779 kfree(volume_info.prepath);
1780 FreeXid(xid);
1781 return -EINVAL;
1784 /* this is needed for ASCII cp to Unicode converts */
1785 if(volume_info.iocharset == NULL) {
1786 cifs_sb->local_nls = load_nls_default();
1787 /* load_nls_default can not return null */
1788 } else {
1789 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1790 if(cifs_sb->local_nls == NULL) {
1791 cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset));
1792 kfree(volume_info.UNC);
1793 kfree(volume_info.password);
1794 kfree(volume_info.prepath);
1795 FreeXid(xid);
1796 return -ELIBACC;
1800 if(address_type == AF_INET)
1801 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1802 NULL /* no ipv6 addr */,
1803 volume_info.username, &srvTcp);
1804 else if(address_type == AF_INET6) {
1805 cFYI(1,("looking for ipv6 address"));
1806 existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */,
1807 &sin_server6.sin6_addr,
1808 volume_info.username, &srvTcp);
1809 } else {
1810 kfree(volume_info.UNC);
1811 kfree(volume_info.password);
1812 kfree(volume_info.prepath);
1813 FreeXid(xid);
1814 return -EINVAL;
1818 if (srvTcp) {
1819 cFYI(1, ("Existing tcp session with server found"));
1820 } else { /* create socket */
1821 if (volume_info.port)
1822 sin_server.sin_port = htons(volume_info.port);
1823 else
1824 sin_server.sin_port = 0;
1825 if (address_type == AF_INET6) {
1826 cFYI(1,("attempting ipv6 connect"));
1827 /* BB should we allow ipv6 on port 139? */
1828 /* other OS never observed in Wild doing 139 with v6 */
1829 rc = ipv6_connect(&sin_server6,&csocket);
1830 } else
1831 rc = ipv4_connect(&sin_server,&csocket,
1832 volume_info.source_rfc1001_name,
1833 volume_info.target_rfc1001_name);
1834 if (rc < 0) {
1835 cERROR(1,
1836 ("Error connecting to IPv4 socket. Aborting operation"));
1837 if (csocket != NULL)
1838 sock_release(csocket);
1839 kfree(volume_info.UNC);
1840 kfree(volume_info.password);
1841 kfree(volume_info.prepath);
1842 FreeXid(xid);
1843 return rc;
1846 srvTcp = kmalloc(sizeof (struct TCP_Server_Info), GFP_KERNEL);
1847 if (srvTcp == NULL) {
1848 rc = -ENOMEM;
1849 sock_release(csocket);
1850 kfree(volume_info.UNC);
1851 kfree(volume_info.password);
1852 kfree(volume_info.prepath);
1853 FreeXid(xid);
1854 return rc;
1855 } else {
1856 memset(srvTcp, 0, sizeof (struct TCP_Server_Info));
1857 memcpy(&srvTcp->addr.sockAddr, &sin_server, sizeof (struct sockaddr_in));
1858 atomic_set(&srvTcp->inFlight,0);
1859 /* BB Add code for ipv6 case too */
1860 srvTcp->ssocket = csocket;
1861 srvTcp->protocolType = IPV4;
1862 init_waitqueue_head(&srvTcp->response_q);
1863 init_waitqueue_head(&srvTcp->request_q);
1864 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1865 /* at this point we are the only ones with the pointer
1866 to the struct since the kernel thread not created yet
1867 so no need to spinlock this init of tcpStatus */
1868 srvTcp->tcpStatus = CifsNew;
1869 init_MUTEX(&srvTcp->tcpSem);
1870 srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd");
1871 if ( IS_ERR(srvTcp->tsk) ) {
1872 rc = PTR_ERR(srvTcp->tsk);
1873 cERROR(1,("error %d create cifsd thread", rc));
1874 srvTcp->tsk = NULL;
1875 sock_release(csocket);
1876 kfree(volume_info.UNC);
1877 kfree(volume_info.password);
1878 kfree(volume_info.prepath);
1879 FreeXid(xid);
1880 return rc;
1882 wait_for_completion(&cifsd_complete);
1883 rc = 0;
1884 memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16);
1885 memcpy(srvTcp->server_RFC1001_name, volume_info.target_rfc1001_name,16);
1886 srvTcp->sequence_number = 0;
1890 if (existingCifsSes) {
1891 pSesInfo = existingCifsSes;
1892 cFYI(1, ("Existing smb sess found"));
1893 kfree(volume_info.password);
1894 /* volume_info.UNC freed at end of function */
1895 } else if (!rc) {
1896 cFYI(1, ("Existing smb sess not found"));
1897 pSesInfo = sesInfoAlloc();
1898 if (pSesInfo == NULL)
1899 rc = -ENOMEM;
1900 else {
1901 pSesInfo->server = srvTcp;
1902 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1903 NIPQUAD(sin_server.sin_addr.s_addr));
1906 if (!rc){
1907 /* volume_info.password freed at unmount */
1908 if (volume_info.password)
1909 pSesInfo->password = volume_info.password;
1910 if (volume_info.username)
1911 strncpy(pSesInfo->userName,
1912 volume_info.username,MAX_USERNAME_SIZE);
1913 if (volume_info.domainname) {
1914 int len = strlen(volume_info.domainname);
1915 pSesInfo->domainName =
1916 kmalloc(len + 1, GFP_KERNEL);
1917 if (pSesInfo->domainName)
1918 strcpy(pSesInfo->domainName,
1919 volume_info.domainname);
1921 pSesInfo->linux_uid = volume_info.linux_uid;
1922 pSesInfo->overrideSecFlg = volume_info.secFlg;
1923 down(&pSesInfo->sesSem);
1924 /* BB FIXME need to pass vol->secFlgs BB */
1925 rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
1926 up(&pSesInfo->sesSem);
1927 if (!rc)
1928 atomic_inc(&srvTcp->socketUseCount);
1929 } else
1930 kfree(volume_info.password);
1933 /* search for existing tcon to this server share */
1934 if (!rc) {
1935 if (volume_info.rsize > CIFSMaxBufSize) {
1936 cERROR(1,("rsize %d too large, using MaxBufSize",
1937 volume_info.rsize));
1938 cifs_sb->rsize = CIFSMaxBufSize;
1939 } else if((volume_info.rsize) && (volume_info.rsize <= CIFSMaxBufSize))
1940 cifs_sb->rsize = volume_info.rsize;
1941 else /* default */
1942 cifs_sb->rsize = CIFSMaxBufSize;
1944 if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
1945 cERROR(1,("wsize %d too large using 4096 instead",
1946 volume_info.wsize));
1947 cifs_sb->wsize = 4096;
1948 } else if (volume_info.wsize)
1949 cifs_sb->wsize = volume_info.wsize;
1950 else
1951 cifs_sb->wsize =
1952 min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
1953 127*1024);
1954 /* old default of CIFSMaxBufSize was too small now
1955 that SMB Write2 can send multiple pages in kvec.
1956 RFC1001 does not describe what happens when frame
1957 bigger than 128K is sent so use that as max in
1958 conjunction with 52K kvec constraint on arch with 4K
1959 page size */
1961 if (cifs_sb->rsize < 2048) {
1962 cifs_sb->rsize = 2048;
1963 /* Windows ME may prefer this */
1964 cFYI(1,("readsize set to minimum 2048"));
1966 /* calculate prepath */
1967 cifs_sb->prepath = volume_info.prepath;
1968 if (cifs_sb->prepath) {
1969 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
1970 cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb);
1971 volume_info.prepath = NULL;
1972 } else
1973 cifs_sb->prepathlen = 0;
1974 cifs_sb->mnt_uid = volume_info.linux_uid;
1975 cifs_sb->mnt_gid = volume_info.linux_gid;
1976 cifs_sb->mnt_file_mode = volume_info.file_mode;
1977 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
1978 cFYI(1,("file mode: 0x%x dir mode: 0x%x",
1979 cifs_sb->mnt_file_mode,cifs_sb->mnt_dir_mode));
1981 if (volume_info.noperm)
1982 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
1983 if (volume_info.setuids)
1984 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
1985 if (volume_info.server_ino)
1986 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
1987 if (volume_info.remap)
1988 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
1989 if (volume_info.no_xattr)
1990 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
1991 if (volume_info.sfu_emul)
1992 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
1993 if (volume_info.nobrl)
1994 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
1995 if (volume_info.cifs_acl)
1996 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
1997 if (volume_info.override_uid)
1998 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
1999 if (volume_info.override_gid)
2000 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2001 if (volume_info.direct_io) {
2002 cFYI(1,("mounting share using direct i/o"));
2003 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
2006 tcon =
2007 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
2008 volume_info.username);
2009 if (tcon) {
2010 cFYI(1, ("Found match on UNC path"));
2011 /* we can have only one retry value for a connection
2012 to a share so for resources mounted more than once
2013 to the same server share the last value passed in
2014 for the retry flag is used */
2015 tcon->retry = volume_info.retry;
2016 tcon->nocase = volume_info.nocase;
2017 } else {
2018 tcon = tconInfoAlloc();
2019 if (tcon == NULL)
2020 rc = -ENOMEM;
2021 else {
2022 /* check for null share name ie connecting to
2023 * dfs root */
2025 /* BB check if this works for exactly length
2026 * three strings */
2027 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
2028 && (strchr(volume_info.UNC + 3, '/') ==
2029 NULL)) {
2030 rc = connect_to_dfs_path(xid, pSesInfo,
2031 "", cifs_sb->local_nls,
2032 cifs_sb->mnt_cifs_flags &
2033 CIFS_MOUNT_MAP_SPECIAL_CHR);
2034 kfree(volume_info.UNC);
2035 FreeXid(xid);
2036 return -ENODEV;
2037 } else {
2038 /* BB Do we need to wrap sesSem around
2039 * this TCon call and Unix SetFS as
2040 * we do on SessSetup and reconnect? */
2041 rc = CIFSTCon(xid, pSesInfo,
2042 volume_info.UNC,
2043 tcon, cifs_sb->local_nls);
2044 cFYI(1, ("CIFS Tcon rc = %d", rc));
2046 if (!rc) {
2047 atomic_inc(&pSesInfo->inUse);
2048 tcon->retry = volume_info.retry;
2049 tcon->nocase = volume_info.nocase;
2054 if (pSesInfo) {
2055 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
2056 sb->s_maxbytes = (u64) 1 << 63;
2057 } else
2058 sb->s_maxbytes = (u64) 1 << 31; /* 2 GB */
2061 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
2062 sb->s_time_gran = 100;
2064 /* on error free sesinfo and tcon struct if needed */
2065 if (rc) {
2066 /* if session setup failed, use count is zero but
2067 we still need to free cifsd thread */
2068 if (atomic_read(&srvTcp->socketUseCount) == 0) {
2069 spin_lock(&GlobalMid_Lock);
2070 srvTcp->tcpStatus = CifsExiting;
2071 spin_unlock(&GlobalMid_Lock);
2072 if (srvTcp->tsk) {
2073 struct task_struct *tsk;
2074 /* If we could verify that kthread_stop would
2075 always wake up processes blocked in
2076 tcp in recv_mesg then we could remove the
2077 send_sig call */
2078 send_sig(SIGKILL,srvTcp->tsk,1);
2079 tsk = srvTcp->tsk;
2080 if(tsk)
2081 kthread_stop(tsk);
2084 /* If find_unc succeeded then rc == 0 so we can not end */
2085 if (tcon) /* up accidently freeing someone elses tcon struct */
2086 tconInfoFree(tcon);
2087 if (existingCifsSes == NULL) {
2088 if (pSesInfo) {
2089 if ((pSesInfo->server) &&
2090 (pSesInfo->status == CifsGood)) {
2091 int temp_rc;
2092 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
2093 /* if the socketUseCount is now zero */
2094 if ((temp_rc == -ESHUTDOWN) &&
2095 (pSesInfo->server) && (pSesInfo->server->tsk)) {
2096 struct task_struct *tsk;
2097 send_sig(SIGKILL,pSesInfo->server->tsk,1);
2098 tsk = pSesInfo->server->tsk;
2099 if (tsk)
2100 kthread_stop(tsk);
2102 } else
2103 cFYI(1, ("No session or bad tcon"));
2104 sesInfoFree(pSesInfo);
2105 /* pSesInfo = NULL; */
2108 } else {
2109 atomic_inc(&tcon->useCount);
2110 cifs_sb->tcon = tcon;
2111 tcon->ses = pSesInfo;
2113 /* do not care if following two calls succeed - informational */
2114 CIFSSMBQFSDeviceInfo(xid, tcon);
2115 CIFSSMBQFSAttributeInfo(xid, tcon);
2117 /* tell server which Unix caps we support */
2118 if (tcon->ses->capabilities & CAP_UNIX)
2119 reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
2121 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
2122 cifs_sb->wsize = min(cifs_sb->wsize,
2123 (tcon->ses->server->maxBuf -
2124 MAX_CIFS_HDR_SIZE));
2125 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
2126 cifs_sb->rsize = min(cifs_sb->rsize,
2127 (tcon->ses->server->maxBuf -
2128 MAX_CIFS_HDR_SIZE));
2131 /* volume_info.password is freed above when existing session found
2132 (in which case it is not needed anymore) but when new sesion is created
2133 the password ptr is put in the new session structure (in which case the
2134 password will be freed at unmount time) */
2135 kfree(volume_info.UNC);
2136 kfree(volume_info.prepath);
2137 FreeXid(xid);
2138 return rc;
2141 static int
2142 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2143 char session_key[CIFS_SESS_KEY_SIZE],
2144 const struct nls_table *nls_codepage)
2146 struct smb_hdr *smb_buffer;
2147 struct smb_hdr *smb_buffer_response;
2148 SESSION_SETUP_ANDX *pSMB;
2149 SESSION_SETUP_ANDX *pSMBr;
2150 char *bcc_ptr;
2151 char *user;
2152 char *domain;
2153 int rc = 0;
2154 int remaining_words = 0;
2155 int bytes_returned = 0;
2156 int len;
2157 __u32 capabilities;
2158 __u16 count;
2160 cFYI(1, ("In sesssetup"));
2161 if (ses == NULL)
2162 return -EINVAL;
2163 user = ses->userName;
2164 domain = ses->domainName;
2165 smb_buffer = cifs_buf_get();
2166 if (smb_buffer == NULL) {
2167 return -ENOMEM;
2169 smb_buffer_response = smb_buffer;
2170 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2172 /* send SMBsessionSetup here */
2173 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2174 NULL /* no tCon exists yet */ , 13 /* wct */ );
2176 smb_buffer->Mid = GetNextMid(ses->server);
2177 pSMB->req_no_secext.AndXCommand = 0xFF;
2178 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2179 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2181 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2182 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2184 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2185 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
2186 if (ses->capabilities & CAP_UNICODE) {
2187 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2188 capabilities |= CAP_UNICODE;
2190 if (ses->capabilities & CAP_STATUS32) {
2191 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2192 capabilities |= CAP_STATUS32;
2194 if (ses->capabilities & CAP_DFS) {
2195 smb_buffer->Flags2 |= SMBFLG2_DFS;
2196 capabilities |= CAP_DFS;
2198 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2200 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2201 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2203 pSMB->req_no_secext.CaseSensitivePasswordLength =
2204 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2205 bcc_ptr = pByteArea(smb_buffer);
2206 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2207 bcc_ptr += CIFS_SESS_KEY_SIZE;
2208 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2209 bcc_ptr += CIFS_SESS_KEY_SIZE;
2211 if (ses->capabilities & CAP_UNICODE) {
2212 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
2213 *bcc_ptr = 0;
2214 bcc_ptr++;
2216 if (user == NULL)
2217 bytes_returned = 0; /* skip null user */
2218 else
2219 bytes_returned =
2220 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
2221 nls_codepage);
2222 /* convert number of 16 bit words to bytes */
2223 bcc_ptr += 2 * bytes_returned;
2224 bcc_ptr += 2; /* trailing null */
2225 if (domain == NULL)
2226 bytes_returned =
2227 cifs_strtoUCS((__le16 *) bcc_ptr,
2228 "CIFS_LINUX_DOM", 32, nls_codepage);
2229 else
2230 bytes_returned =
2231 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2232 nls_codepage);
2233 bcc_ptr += 2 * bytes_returned;
2234 bcc_ptr += 2;
2235 bytes_returned =
2236 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2237 32, nls_codepage);
2238 bcc_ptr += 2 * bytes_returned;
2239 bytes_returned =
2240 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release,
2241 32, nls_codepage);
2242 bcc_ptr += 2 * bytes_returned;
2243 bcc_ptr += 2;
2244 bytes_returned =
2245 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2246 64, nls_codepage);
2247 bcc_ptr += 2 * bytes_returned;
2248 bcc_ptr += 2;
2249 } else {
2250 if (user != NULL) {
2251 strncpy(bcc_ptr, user, 200);
2252 bcc_ptr += strnlen(user, 200);
2254 *bcc_ptr = 0;
2255 bcc_ptr++;
2256 if (domain == NULL) {
2257 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2258 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2259 } else {
2260 strncpy(bcc_ptr, domain, 64);
2261 bcc_ptr += strnlen(domain, 64);
2262 *bcc_ptr = 0;
2263 bcc_ptr++;
2265 strcpy(bcc_ptr, "Linux version ");
2266 bcc_ptr += strlen("Linux version ");
2267 strcpy(bcc_ptr, utsname()->release);
2268 bcc_ptr += strlen(utsname()->release) + 1;
2269 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2270 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2272 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2273 smb_buffer->smb_buf_length += count;
2274 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2276 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2277 &bytes_returned, 1);
2278 if (rc) {
2279 /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2280 } else if ((smb_buffer_response->WordCount == 3)
2281 || (smb_buffer_response->WordCount == 4)) {
2282 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2283 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2284 if (action & GUEST_LOGIN)
2285 cFYI(1, (" Guest login")); /* do we want to mark SesInfo struct ? */
2286 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format (le) */
2287 cFYI(1, ("UID = %d ", ses->Suid));
2288 /* response can have either 3 or 4 word count - Samba sends 3 */
2289 bcc_ptr = pByteArea(smb_buffer_response);
2290 if ((pSMBr->resp.hdr.WordCount == 3)
2291 || ((pSMBr->resp.hdr.WordCount == 4)
2292 && (blob_len < pSMBr->resp.ByteCount))) {
2293 if (pSMBr->resp.hdr.WordCount == 4)
2294 bcc_ptr += blob_len;
2296 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2297 if ((long) (bcc_ptr) % 2) {
2298 remaining_words =
2299 (BCC(smb_buffer_response) - 1) /2;
2300 bcc_ptr++; /* Unicode strings must be word aligned */
2301 } else {
2302 remaining_words =
2303 BCC(smb_buffer_response) / 2;
2305 len =
2306 UniStrnlen((wchar_t *) bcc_ptr,
2307 remaining_words - 1);
2308 /* We look for obvious messed up bcc or strings in response so we do not go off
2309 the end since (at least) WIN2K and Windows XP have a major bug in not null
2310 terminating last Unicode string in response */
2311 if(ses->serverOS)
2312 kfree(ses->serverOS);
2313 ses->serverOS = kzalloc(2 * (len + 1), GFP_KERNEL);
2314 if(ses->serverOS == NULL)
2315 goto sesssetup_nomem;
2316 cifs_strfromUCS_le(ses->serverOS,
2317 (__le16 *)bcc_ptr, len,nls_codepage);
2318 bcc_ptr += 2 * (len + 1);
2319 remaining_words -= len + 1;
2320 ses->serverOS[2 * len] = 0;
2321 ses->serverOS[1 + (2 * len)] = 0;
2322 if (remaining_words > 0) {
2323 len = UniStrnlen((wchar_t *)bcc_ptr,
2324 remaining_words-1);
2325 kfree(ses->serverNOS);
2326 ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
2327 if(ses->serverNOS == NULL)
2328 goto sesssetup_nomem;
2329 cifs_strfromUCS_le(ses->serverNOS,
2330 (__le16 *)bcc_ptr,len,nls_codepage);
2331 bcc_ptr += 2 * (len + 1);
2332 ses->serverNOS[2 * len] = 0;
2333 ses->serverNOS[1 + (2 * len)] = 0;
2334 if(strncmp(ses->serverNOS,
2335 "NT LAN Manager 4",16) == 0) {
2336 cFYI(1,("NT4 server"));
2337 ses->flags |= CIFS_SES_NT4;
2339 remaining_words -= len + 1;
2340 if (remaining_words > 0) {
2341 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2342 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2343 if(ses->serverDomain)
2344 kfree(ses->serverDomain);
2345 ses->serverDomain =
2346 kzalloc(2*(len+1),GFP_KERNEL);
2347 if(ses->serverDomain == NULL)
2348 goto sesssetup_nomem;
2349 cifs_strfromUCS_le(ses->serverDomain,
2350 (__le16 *)bcc_ptr,len,nls_codepage);
2351 bcc_ptr += 2 * (len + 1);
2352 ses->serverDomain[2*len] = 0;
2353 ses->serverDomain[1+(2*len)] = 0;
2354 } /* else no more room so create dummy domain string */
2355 else {
2356 if(ses->serverDomain)
2357 kfree(ses->serverDomain);
2358 ses->serverDomain =
2359 kzalloc(2, GFP_KERNEL);
2361 } else { /* no room so create dummy domain and NOS string */
2362 /* if these kcallocs fail not much we
2363 can do, but better to not fail the
2364 sesssetup itself */
2365 kfree(ses->serverDomain);
2366 ses->serverDomain =
2367 kzalloc(2, GFP_KERNEL);
2368 kfree(ses->serverNOS);
2369 ses->serverNOS =
2370 kzalloc(2, GFP_KERNEL);
2372 } else { /* ASCII */
2373 len = strnlen(bcc_ptr, 1024);
2374 if (((long) bcc_ptr + len) - (long)
2375 pByteArea(smb_buffer_response)
2376 <= BCC(smb_buffer_response)) {
2377 kfree(ses->serverOS);
2378 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
2379 if(ses->serverOS == NULL)
2380 goto sesssetup_nomem;
2381 strncpy(ses->serverOS,bcc_ptr, len);
2383 bcc_ptr += len;
2384 bcc_ptr[0] = 0; /* null terminate the string */
2385 bcc_ptr++;
2387 len = strnlen(bcc_ptr, 1024);
2388 kfree(ses->serverNOS);
2389 ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
2390 if(ses->serverNOS == NULL)
2391 goto sesssetup_nomem;
2392 strncpy(ses->serverNOS, bcc_ptr, len);
2393 bcc_ptr += len;
2394 bcc_ptr[0] = 0;
2395 bcc_ptr++;
2397 len = strnlen(bcc_ptr, 1024);
2398 if(ses->serverDomain)
2399 kfree(ses->serverDomain);
2400 ses->serverDomain = kzalloc(len + 1,GFP_KERNEL);
2401 if(ses->serverDomain == NULL)
2402 goto sesssetup_nomem;
2403 strncpy(ses->serverDomain, bcc_ptr, len);
2404 bcc_ptr += len;
2405 bcc_ptr[0] = 0;
2406 bcc_ptr++;
2407 } else
2408 cFYI(1,
2409 ("Variable field of length %d extends beyond end of smb ",
2410 len));
2412 } else {
2413 cERROR(1,
2414 (" Security Blob Length extends beyond end of SMB"));
2416 } else {
2417 cERROR(1,
2418 (" Invalid Word count %d: ",
2419 smb_buffer_response->WordCount));
2420 rc = -EIO;
2422 sesssetup_nomem: /* do not return an error on nomem for the info strings,
2423 since that could make reconnection harder, and
2424 reconnection might be needed to free memory */
2425 if (smb_buffer)
2426 cifs_buf_release(smb_buffer);
2428 return rc;
2431 static int
2432 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2433 struct cifsSesInfo *ses, int * pNTLMv2_flag,
2434 const struct nls_table *nls_codepage)
2436 struct smb_hdr *smb_buffer;
2437 struct smb_hdr *smb_buffer_response;
2438 SESSION_SETUP_ANDX *pSMB;
2439 SESSION_SETUP_ANDX *pSMBr;
2440 char *bcc_ptr;
2441 char *domain;
2442 int rc = 0;
2443 int remaining_words = 0;
2444 int bytes_returned = 0;
2445 int len;
2446 int SecurityBlobLength = sizeof (NEGOTIATE_MESSAGE);
2447 PNEGOTIATE_MESSAGE SecurityBlob;
2448 PCHALLENGE_MESSAGE SecurityBlob2;
2449 __u32 negotiate_flags, capabilities;
2450 __u16 count;
2452 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
2453 if(ses == NULL)
2454 return -EINVAL;
2455 domain = ses->domainName;
2456 *pNTLMv2_flag = FALSE;
2457 smb_buffer = cifs_buf_get();
2458 if (smb_buffer == NULL) {
2459 return -ENOMEM;
2461 smb_buffer_response = smb_buffer;
2462 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2463 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2465 /* send SMBsessionSetup here */
2466 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2467 NULL /* no tCon exists yet */ , 12 /* wct */ );
2469 smb_buffer->Mid = GetNextMid(ses->server);
2470 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2471 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2473 pSMB->req.AndXCommand = 0xFF;
2474 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2475 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2477 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2478 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2480 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2481 CAP_EXTENDED_SECURITY;
2482 if (ses->capabilities & CAP_UNICODE) {
2483 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2484 capabilities |= CAP_UNICODE;
2486 if (ses->capabilities & CAP_STATUS32) {
2487 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2488 capabilities |= CAP_STATUS32;
2490 if (ses->capabilities & CAP_DFS) {
2491 smb_buffer->Flags2 |= SMBFLG2_DFS;
2492 capabilities |= CAP_DFS;
2494 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2496 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2497 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2498 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2499 SecurityBlob->MessageType = NtLmNegotiate;
2500 negotiate_flags =
2501 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2502 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2503 NTLMSSP_NEGOTIATE_56 |
2504 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2505 if(sign_CIFS_PDUs)
2506 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2507 /* if(ntlmv2_support)
2508 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2509 /* setup pointers to domain name and workstation name */
2510 bcc_ptr += SecurityBlobLength;
2512 SecurityBlob->WorkstationName.Buffer = 0;
2513 SecurityBlob->WorkstationName.Length = 0;
2514 SecurityBlob->WorkstationName.MaximumLength = 0;
2516 /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2517 along with username on auth request (ie the response to challenge) */
2518 SecurityBlob->DomainName.Buffer = 0;
2519 SecurityBlob->DomainName.Length = 0;
2520 SecurityBlob->DomainName.MaximumLength = 0;
2521 if (ses->capabilities & CAP_UNICODE) {
2522 if ((long) bcc_ptr % 2) {
2523 *bcc_ptr = 0;
2524 bcc_ptr++;
2527 bytes_returned =
2528 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2529 32, nls_codepage);
2530 bcc_ptr += 2 * bytes_returned;
2531 bytes_returned =
2532 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
2533 nls_codepage);
2534 bcc_ptr += 2 * bytes_returned;
2535 bcc_ptr += 2; /* null terminate Linux version */
2536 bytes_returned =
2537 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2538 64, nls_codepage);
2539 bcc_ptr += 2 * bytes_returned;
2540 *(bcc_ptr + 1) = 0;
2541 *(bcc_ptr + 2) = 0;
2542 bcc_ptr += 2; /* null terminate network opsys string */
2543 *(bcc_ptr + 1) = 0;
2544 *(bcc_ptr + 2) = 0;
2545 bcc_ptr += 2; /* null domain */
2546 } else { /* ASCII */
2547 strcpy(bcc_ptr, "Linux version ");
2548 bcc_ptr += strlen("Linux version ");
2549 strcpy(bcc_ptr, utsname()->release);
2550 bcc_ptr += strlen(utsname()->release) + 1;
2551 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2552 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2553 bcc_ptr++; /* empty domain field */
2554 *bcc_ptr = 0;
2556 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2557 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2558 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2559 smb_buffer->smb_buf_length += count;
2560 pSMB->req.ByteCount = cpu_to_le16(count);
2562 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2563 &bytes_returned, 1);
2565 if (smb_buffer_response->Status.CifsError ==
2566 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2567 rc = 0;
2569 if (rc) {
2570 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2571 } else if ((smb_buffer_response->WordCount == 3)
2572 || (smb_buffer_response->WordCount == 4)) {
2573 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2574 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2576 if (action & GUEST_LOGIN)
2577 cFYI(1, (" Guest login"));
2578 /* Do we want to set anything in SesInfo struct when guest login? */
2580 bcc_ptr = pByteArea(smb_buffer_response);
2581 /* response can have either 3 or 4 word count - Samba sends 3 */
2583 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2584 if (SecurityBlob2->MessageType != NtLmChallenge) {
2585 cFYI(1,
2586 ("Unexpected NTLMSSP message type received %d",
2587 SecurityBlob2->MessageType));
2588 } else if (ses) {
2589 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2590 cFYI(1, ("UID = %d", ses->Suid));
2591 if ((pSMBr->resp.hdr.WordCount == 3)
2592 || ((pSMBr->resp.hdr.WordCount == 4)
2593 && (blob_len <
2594 pSMBr->resp.ByteCount))) {
2596 if (pSMBr->resp.hdr.WordCount == 4) {
2597 bcc_ptr += blob_len;
2598 cFYI(1, ("Security Blob Length %d",
2599 blob_len));
2602 cFYI(1, ("NTLMSSP Challenge rcvd"));
2604 memcpy(ses->server->cryptKey,
2605 SecurityBlob2->Challenge,
2606 CIFS_CRYPTO_KEY_SIZE);
2607 if(SecurityBlob2->NegotiateFlags &
2608 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2609 *pNTLMv2_flag = TRUE;
2611 if((SecurityBlob2->NegotiateFlags &
2612 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2613 || (sign_CIFS_PDUs > 1))
2614 ses->server->secMode |=
2615 SECMODE_SIGN_REQUIRED;
2616 if ((SecurityBlob2->NegotiateFlags &
2617 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2618 ses->server->secMode |=
2619 SECMODE_SIGN_ENABLED;
2621 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2622 if ((long) (bcc_ptr) % 2) {
2623 remaining_words =
2624 (BCC(smb_buffer_response)
2625 - 1) / 2;
2626 bcc_ptr++; /* Unicode strings must be word aligned */
2627 } else {
2628 remaining_words =
2630 (smb_buffer_response) / 2;
2632 len =
2633 UniStrnlen((wchar_t *) bcc_ptr,
2634 remaining_words - 1);
2635 /* We look for obvious messed up bcc or strings in response so we do not go off
2636 the end since (at least) WIN2K and Windows XP have a major bug in not null
2637 terminating last Unicode string in response */
2638 if(ses->serverOS)
2639 kfree(ses->serverOS);
2640 ses->serverOS =
2641 kzalloc(2 * (len + 1), GFP_KERNEL);
2642 cifs_strfromUCS_le(ses->serverOS,
2643 (__le16 *)
2644 bcc_ptr, len,
2645 nls_codepage);
2646 bcc_ptr += 2 * (len + 1);
2647 remaining_words -= len + 1;
2648 ses->serverOS[2 * len] = 0;
2649 ses->serverOS[1 + (2 * len)] = 0;
2650 if (remaining_words > 0) {
2651 len = UniStrnlen((wchar_t *)
2652 bcc_ptr,
2653 remaining_words
2654 - 1);
2655 kfree(ses->serverNOS);
2656 ses->serverNOS =
2657 kzalloc(2 * (len + 1),
2658 GFP_KERNEL);
2659 cifs_strfromUCS_le(ses->
2660 serverNOS,
2661 (__le16 *)
2662 bcc_ptr,
2663 len,
2664 nls_codepage);
2665 bcc_ptr += 2 * (len + 1);
2666 ses->serverNOS[2 * len] = 0;
2667 ses->serverNOS[1 +
2668 (2 * len)] = 0;
2669 remaining_words -= len + 1;
2670 if (remaining_words > 0) {
2671 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2672 /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
2673 kfree(ses->serverDomain);
2674 ses->serverDomain =
2675 kzalloc(2 *
2676 (len +
2678 GFP_KERNEL);
2679 cifs_strfromUCS_le
2680 (ses->serverDomain,
2681 (__le16 *)bcc_ptr,
2682 len, nls_codepage);
2683 bcc_ptr +=
2684 2 * (len + 1);
2685 ses->serverDomain[2*len]
2686 = 0;
2687 ses->serverDomain
2688 [1 + (2 * len)]
2689 = 0;
2690 } /* else no more room so create dummy domain string */
2691 else {
2692 kfree(ses->serverDomain);
2693 ses->serverDomain =
2694 kzalloc(2,
2695 GFP_KERNEL);
2697 } else { /* no room so create dummy domain and NOS string */
2698 kfree(ses->serverDomain);
2699 ses->serverDomain =
2700 kzalloc(2, GFP_KERNEL);
2701 kfree(ses->serverNOS);
2702 ses->serverNOS =
2703 kzalloc(2, GFP_KERNEL);
2705 } else { /* ASCII */
2706 len = strnlen(bcc_ptr, 1024);
2707 if (((long) bcc_ptr + len) - (long)
2708 pByteArea(smb_buffer_response)
2709 <= BCC(smb_buffer_response)) {
2710 if(ses->serverOS)
2711 kfree(ses->serverOS);
2712 ses->serverOS =
2713 kzalloc(len + 1,
2714 GFP_KERNEL);
2715 strncpy(ses->serverOS,
2716 bcc_ptr, len);
2718 bcc_ptr += len;
2719 bcc_ptr[0] = 0; /* null terminate string */
2720 bcc_ptr++;
2722 len = strnlen(bcc_ptr, 1024);
2723 kfree(ses->serverNOS);
2724 ses->serverNOS =
2725 kzalloc(len + 1,
2726 GFP_KERNEL);
2727 strncpy(ses->serverNOS, bcc_ptr, len);
2728 bcc_ptr += len;
2729 bcc_ptr[0] = 0;
2730 bcc_ptr++;
2732 len = strnlen(bcc_ptr, 1024);
2733 kfree(ses->serverDomain);
2734 ses->serverDomain =
2735 kzalloc(len + 1,
2736 GFP_KERNEL);
2737 strncpy(ses->serverDomain, bcc_ptr, len);
2738 bcc_ptr += len;
2739 bcc_ptr[0] = 0;
2740 bcc_ptr++;
2741 } else
2742 cFYI(1,
2743 ("Variable field of length %d extends beyond end of smb",
2744 len));
2746 } else {
2747 cERROR(1,
2748 (" Security Blob Length extends beyond end of SMB"));
2750 } else {
2751 cERROR(1, ("No session structure passed in."));
2753 } else {
2754 cERROR(1,
2755 (" Invalid Word count %d:",
2756 smb_buffer_response->WordCount));
2757 rc = -EIO;
2760 if (smb_buffer)
2761 cifs_buf_release(smb_buffer);
2763 return rc;
2765 static int
2766 CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2767 char *ntlm_session_key, int ntlmv2_flag,
2768 const struct nls_table *nls_codepage)
2770 struct smb_hdr *smb_buffer;
2771 struct smb_hdr *smb_buffer_response;
2772 SESSION_SETUP_ANDX *pSMB;
2773 SESSION_SETUP_ANDX *pSMBr;
2774 char *bcc_ptr;
2775 char *user;
2776 char *domain;
2777 int rc = 0;
2778 int remaining_words = 0;
2779 int bytes_returned = 0;
2780 int len;
2781 int SecurityBlobLength = sizeof (AUTHENTICATE_MESSAGE);
2782 PAUTHENTICATE_MESSAGE SecurityBlob;
2783 __u32 negotiate_flags, capabilities;
2784 __u16 count;
2786 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2787 if(ses == NULL)
2788 return -EINVAL;
2789 user = ses->userName;
2790 domain = ses->domainName;
2791 smb_buffer = cifs_buf_get();
2792 if (smb_buffer == NULL) {
2793 return -ENOMEM;
2795 smb_buffer_response = smb_buffer;
2796 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2797 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2799 /* send SMBsessionSetup here */
2800 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2801 NULL /* no tCon exists yet */ , 12 /* wct */ );
2803 smb_buffer->Mid = GetNextMid(ses->server);
2804 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2805 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2806 pSMB->req.AndXCommand = 0xFF;
2807 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2808 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2810 pSMB->req.hdr.Uid = ses->Suid;
2812 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2813 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2815 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2816 CAP_EXTENDED_SECURITY;
2817 if (ses->capabilities & CAP_UNICODE) {
2818 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2819 capabilities |= CAP_UNICODE;
2821 if (ses->capabilities & CAP_STATUS32) {
2822 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2823 capabilities |= CAP_STATUS32;
2825 if (ses->capabilities & CAP_DFS) {
2826 smb_buffer->Flags2 |= SMBFLG2_DFS;
2827 capabilities |= CAP_DFS;
2829 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2831 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2832 SecurityBlob = (PAUTHENTICATE_MESSAGE) bcc_ptr;
2833 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2834 SecurityBlob->MessageType = NtLmAuthenticate;
2835 bcc_ptr += SecurityBlobLength;
2836 negotiate_flags =
2837 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2838 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2839 0x80000000 | NTLMSSP_NEGOTIATE_128;
2840 if(sign_CIFS_PDUs)
2841 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
2842 if(ntlmv2_flag)
2843 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2845 /* setup pointers to domain name and workstation name */
2847 SecurityBlob->WorkstationName.Buffer = 0;
2848 SecurityBlob->WorkstationName.Length = 0;
2849 SecurityBlob->WorkstationName.MaximumLength = 0;
2850 SecurityBlob->SessionKey.Length = 0;
2851 SecurityBlob->SessionKey.MaximumLength = 0;
2852 SecurityBlob->SessionKey.Buffer = 0;
2854 SecurityBlob->LmChallengeResponse.Length = 0;
2855 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2856 SecurityBlob->LmChallengeResponse.Buffer = 0;
2858 SecurityBlob->NtChallengeResponse.Length =
2859 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2860 SecurityBlob->NtChallengeResponse.MaximumLength =
2861 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2862 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
2863 SecurityBlob->NtChallengeResponse.Buffer =
2864 cpu_to_le32(SecurityBlobLength);
2865 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
2866 bcc_ptr += CIFS_SESS_KEY_SIZE;
2868 if (ses->capabilities & CAP_UNICODE) {
2869 if (domain == NULL) {
2870 SecurityBlob->DomainName.Buffer = 0;
2871 SecurityBlob->DomainName.Length = 0;
2872 SecurityBlob->DomainName.MaximumLength = 0;
2873 } else {
2874 __u16 len =
2875 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2876 nls_codepage);
2877 len *= 2;
2878 SecurityBlob->DomainName.MaximumLength =
2879 cpu_to_le16(len);
2880 SecurityBlob->DomainName.Buffer =
2881 cpu_to_le32(SecurityBlobLength);
2882 bcc_ptr += len;
2883 SecurityBlobLength += len;
2884 SecurityBlob->DomainName.Length =
2885 cpu_to_le16(len);
2887 if (user == NULL) {
2888 SecurityBlob->UserName.Buffer = 0;
2889 SecurityBlob->UserName.Length = 0;
2890 SecurityBlob->UserName.MaximumLength = 0;
2891 } else {
2892 __u16 len =
2893 cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
2894 nls_codepage);
2895 len *= 2;
2896 SecurityBlob->UserName.MaximumLength =
2897 cpu_to_le16(len);
2898 SecurityBlob->UserName.Buffer =
2899 cpu_to_le32(SecurityBlobLength);
2900 bcc_ptr += len;
2901 SecurityBlobLength += len;
2902 SecurityBlob->UserName.Length =
2903 cpu_to_le16(len);
2906 /* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
2907 SecurityBlob->WorkstationName.Length *= 2;
2908 SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
2909 SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
2910 bcc_ptr += SecurityBlob->WorkstationName.Length;
2911 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
2912 SecurityBlob->WorkstationName.Length = cpu_to_le16(SecurityBlob->WorkstationName.Length); */
2914 if ((long) bcc_ptr % 2) {
2915 *bcc_ptr = 0;
2916 bcc_ptr++;
2918 bytes_returned =
2919 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2920 32, nls_codepage);
2921 bcc_ptr += 2 * bytes_returned;
2922 bytes_returned =
2923 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
2924 nls_codepage);
2925 bcc_ptr += 2 * bytes_returned;
2926 bcc_ptr += 2; /* null term version string */
2927 bytes_returned =
2928 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2929 64, nls_codepage);
2930 bcc_ptr += 2 * bytes_returned;
2931 *(bcc_ptr + 1) = 0;
2932 *(bcc_ptr + 2) = 0;
2933 bcc_ptr += 2; /* null terminate network opsys string */
2934 *(bcc_ptr + 1) = 0;
2935 *(bcc_ptr + 2) = 0;
2936 bcc_ptr += 2; /* null domain */
2937 } else { /* ASCII */
2938 if (domain == NULL) {
2939 SecurityBlob->DomainName.Buffer = 0;
2940 SecurityBlob->DomainName.Length = 0;
2941 SecurityBlob->DomainName.MaximumLength = 0;
2942 } else {
2943 __u16 len;
2944 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
2945 strncpy(bcc_ptr, domain, 63);
2946 len = strnlen(domain, 64);
2947 SecurityBlob->DomainName.MaximumLength =
2948 cpu_to_le16(len);
2949 SecurityBlob->DomainName.Buffer =
2950 cpu_to_le32(SecurityBlobLength);
2951 bcc_ptr += len;
2952 SecurityBlobLength += len;
2953 SecurityBlob->DomainName.Length = cpu_to_le16(len);
2955 if (user == NULL) {
2956 SecurityBlob->UserName.Buffer = 0;
2957 SecurityBlob->UserName.Length = 0;
2958 SecurityBlob->UserName.MaximumLength = 0;
2959 } else {
2960 __u16 len;
2961 strncpy(bcc_ptr, user, 63);
2962 len = strnlen(user, 64);
2963 SecurityBlob->UserName.MaximumLength =
2964 cpu_to_le16(len);
2965 SecurityBlob->UserName.Buffer =
2966 cpu_to_le32(SecurityBlobLength);
2967 bcc_ptr += len;
2968 SecurityBlobLength += len;
2969 SecurityBlob->UserName.Length = cpu_to_le16(len);
2971 /* BB fill in our workstation name if known BB */
2973 strcpy(bcc_ptr, "Linux version ");
2974 bcc_ptr += strlen("Linux version ");
2975 strcpy(bcc_ptr, utsname()->release);
2976 bcc_ptr += strlen(utsname()->release) + 1;
2977 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2978 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2979 bcc_ptr++; /* null domain */
2980 *bcc_ptr = 0;
2982 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2983 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2984 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2985 smb_buffer->smb_buf_length += count;
2986 pSMB->req.ByteCount = cpu_to_le16(count);
2988 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2989 &bytes_returned, 1);
2990 if (rc) {
2991 /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2992 } else if ((smb_buffer_response->WordCount == 3)
2993 || (smb_buffer_response->WordCount == 4)) {
2994 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2995 __u16 blob_len =
2996 le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2997 if (action & GUEST_LOGIN)
2998 cFYI(1, (" Guest login")); /* BB do we want to set anything in SesInfo struct ? */
2999 /* if(SecurityBlob2->MessageType != NtLm??){
3000 cFYI("Unexpected message type on auth response is %d "));
3001 } */
3002 if (ses) {
3003 cFYI(1,
3004 ("Does UID on challenge %d match auth response UID %d ",
3005 ses->Suid, smb_buffer_response->Uid));
3006 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format */
3007 bcc_ptr = pByteArea(smb_buffer_response);
3008 /* response can have either 3 or 4 word count - Samba sends 3 */
3009 if ((pSMBr->resp.hdr.WordCount == 3)
3010 || ((pSMBr->resp.hdr.WordCount == 4)
3011 && (blob_len <
3012 pSMBr->resp.ByteCount))) {
3013 if (pSMBr->resp.hdr.WordCount == 4) {
3014 bcc_ptr +=
3015 blob_len;
3016 cFYI(1,
3017 ("Security Blob Length %d ",
3018 blob_len));
3021 cFYI(1,
3022 ("NTLMSSP response to Authenticate "));
3024 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3025 if ((long) (bcc_ptr) % 2) {
3026 remaining_words =
3027 (BCC(smb_buffer_response)
3028 - 1) / 2;
3029 bcc_ptr++; /* Unicode strings must be word aligned */
3030 } else {
3031 remaining_words = BCC(smb_buffer_response) / 2;
3033 len =
3034 UniStrnlen((wchar_t *) bcc_ptr,remaining_words - 1);
3035 /* We look for obvious messed up bcc or strings in response so we do not go off
3036 the end since (at least) WIN2K and Windows XP have a major bug in not null
3037 terminating last Unicode string in response */
3038 if(ses->serverOS)
3039 kfree(ses->serverOS);
3040 ses->serverOS =
3041 kzalloc(2 * (len + 1), GFP_KERNEL);
3042 cifs_strfromUCS_le(ses->serverOS,
3043 (__le16 *)
3044 bcc_ptr, len,
3045 nls_codepage);
3046 bcc_ptr += 2 * (len + 1);
3047 remaining_words -= len + 1;
3048 ses->serverOS[2 * len] = 0;
3049 ses->serverOS[1 + (2 * len)] = 0;
3050 if (remaining_words > 0) {
3051 len = UniStrnlen((wchar_t *)
3052 bcc_ptr,
3053 remaining_words
3054 - 1);
3055 kfree(ses->serverNOS);
3056 ses->serverNOS =
3057 kzalloc(2 * (len + 1),
3058 GFP_KERNEL);
3059 cifs_strfromUCS_le(ses->
3060 serverNOS,
3061 (__le16 *)
3062 bcc_ptr,
3063 len,
3064 nls_codepage);
3065 bcc_ptr += 2 * (len + 1);
3066 ses->serverNOS[2 * len] = 0;
3067 ses->serverNOS[1+(2*len)] = 0;
3068 remaining_words -= len + 1;
3069 if (remaining_words > 0) {
3070 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3071 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3072 if(ses->serverDomain)
3073 kfree(ses->serverDomain);
3074 ses->serverDomain =
3075 kzalloc(2 *
3076 (len +
3078 GFP_KERNEL);
3079 cifs_strfromUCS_le
3080 (ses->
3081 serverDomain,
3082 (__le16 *)
3083 bcc_ptr, len,
3084 nls_codepage);
3085 bcc_ptr +=
3086 2 * (len + 1);
3087 ses->
3088 serverDomain[2
3089 * len]
3090 = 0;
3091 ses->
3092 serverDomain[1
3096 len)]
3097 = 0;
3098 } /* else no more room so create dummy domain string */
3099 else {
3100 if(ses->serverDomain)
3101 kfree(ses->serverDomain);
3102 ses->serverDomain = kzalloc(2,GFP_KERNEL);
3104 } else { /* no room so create dummy domain and NOS string */
3105 if(ses->serverDomain)
3106 kfree(ses->serverDomain);
3107 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3108 kfree(ses->serverNOS);
3109 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3111 } else { /* ASCII */
3112 len = strnlen(bcc_ptr, 1024);
3113 if (((long) bcc_ptr + len) -
3114 (long) pByteArea(smb_buffer_response)
3115 <= BCC(smb_buffer_response)) {
3116 if(ses->serverOS)
3117 kfree(ses->serverOS);
3118 ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
3119 strncpy(ses->serverOS,bcc_ptr, len);
3121 bcc_ptr += len;
3122 bcc_ptr[0] = 0; /* null terminate the string */
3123 bcc_ptr++;
3125 len = strnlen(bcc_ptr, 1024);
3126 kfree(ses->serverNOS);
3127 ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
3128 strncpy(ses->serverNOS, bcc_ptr, len);
3129 bcc_ptr += len;
3130 bcc_ptr[0] = 0;
3131 bcc_ptr++;
3133 len = strnlen(bcc_ptr, 1024);
3134 if(ses->serverDomain)
3135 kfree(ses->serverDomain);
3136 ses->serverDomain = kzalloc(len+1,GFP_KERNEL);
3137 strncpy(ses->serverDomain, bcc_ptr, len);
3138 bcc_ptr += len;
3139 bcc_ptr[0] = 0;
3140 bcc_ptr++;
3141 } else
3142 cFYI(1,
3143 ("Variable field of length %d extends beyond end of smb ",
3144 len));
3146 } else {
3147 cERROR(1,
3148 (" Security Blob Length extends beyond end of SMB"));
3150 } else {
3151 cERROR(1, ("No session structure passed in."));
3153 } else {
3154 cERROR(1,
3155 (" Invalid Word count %d: ",
3156 smb_buffer_response->WordCount));
3157 rc = -EIO;
3160 if (smb_buffer)
3161 cifs_buf_release(smb_buffer);
3163 return rc;
3167 CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3168 const char *tree, struct cifsTconInfo *tcon,
3169 const struct nls_table *nls_codepage)
3171 struct smb_hdr *smb_buffer;
3172 struct smb_hdr *smb_buffer_response;
3173 TCONX_REQ *pSMB;
3174 TCONX_RSP *pSMBr;
3175 unsigned char *bcc_ptr;
3176 int rc = 0;
3177 int length;
3178 __u16 count;
3180 if (ses == NULL)
3181 return -EIO;
3183 smb_buffer = cifs_buf_get();
3184 if (smb_buffer == NULL) {
3185 return -ENOMEM;
3187 smb_buffer_response = smb_buffer;
3189 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3190 NULL /*no tid */ , 4 /*wct */ );
3192 smb_buffer->Mid = GetNextMid(ses->server);
3193 smb_buffer->Uid = ses->Suid;
3194 pSMB = (TCONX_REQ *) smb_buffer;
3195 pSMBr = (TCONX_RSP *) smb_buffer_response;
3197 pSMB->AndXCommand = 0xFF;
3198 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3199 bcc_ptr = &pSMB->Password[0];
3200 if((ses->server->secMode) & SECMODE_USER) {
3201 pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
3202 *bcc_ptr = 0; /* password is null byte */
3203 bcc_ptr++; /* skip password */
3204 /* already aligned so no need to do it below */
3205 } else {
3206 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
3207 /* BB FIXME add code to fail this if NTLMv2 or Kerberos
3208 specified as required (when that support is added to
3209 the vfs in the future) as only NTLM or the much
3210 weaker LANMAN (which we do not send by default) is accepted
3211 by Samba (not sure whether other servers allow
3212 NTLMv2 password here) */
3213 #ifdef CONFIG_CIFS_WEAK_PW_HASH
3214 if((extended_security & CIFSSEC_MAY_LANMAN) &&
3215 (ses->server->secType == LANMAN))
3216 calc_lanman_hash(ses, bcc_ptr);
3217 else
3218 #endif /* CIFS_WEAK_PW_HASH */
3219 SMBNTencrypt(ses->password,
3220 ses->server->cryptKey,
3221 bcc_ptr);
3223 bcc_ptr += CIFS_SESS_KEY_SIZE;
3224 if(ses->capabilities & CAP_UNICODE) {
3225 /* must align unicode strings */
3226 *bcc_ptr = 0; /* null byte password */
3227 bcc_ptr++;
3231 if(ses->server->secMode &
3232 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3233 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3235 if (ses->capabilities & CAP_STATUS32) {
3236 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3238 if (ses->capabilities & CAP_DFS) {
3239 smb_buffer->Flags2 |= SMBFLG2_DFS;
3241 if (ses->capabilities & CAP_UNICODE) {
3242 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3243 length =
3244 cifs_strtoUCS((__le16 *) bcc_ptr, tree,
3245 6 /* max utf8 char length in bytes */ *
3246 (/* server len*/ + 256 /* share len */), nls_codepage);
3247 bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */
3248 bcc_ptr += 2; /* skip trailing null */
3249 } else { /* ASCII */
3250 strcpy(bcc_ptr, tree);
3251 bcc_ptr += strlen(tree) + 1;
3253 strcpy(bcc_ptr, "?????");
3254 bcc_ptr += strlen("?????");
3255 bcc_ptr += 1;
3256 count = bcc_ptr - &pSMB->Password[0];
3257 pSMB->hdr.smb_buf_length += count;
3258 pSMB->ByteCount = cpu_to_le16(count);
3260 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 0);
3262 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3263 /* above now done in SendReceive */
3264 if ((rc == 0) && (tcon != NULL)) {
3265 tcon->tidStatus = CifsGood;
3266 tcon->tid = smb_buffer_response->Tid;
3267 bcc_ptr = pByteArea(smb_buffer_response);
3268 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3269 /* skip service field (NB: this field is always ASCII) */
3270 bcc_ptr += length + 1;
3271 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3272 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3273 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3274 if ((bcc_ptr + (2 * length)) -
3275 pByteArea(smb_buffer_response) <=
3276 BCC(smb_buffer_response)) {
3277 kfree(tcon->nativeFileSystem);
3278 tcon->nativeFileSystem =
3279 kzalloc(length + 2, GFP_KERNEL);
3280 cifs_strfromUCS_le(tcon->nativeFileSystem,
3281 (__le16 *) bcc_ptr,
3282 length, nls_codepage);
3283 bcc_ptr += 2 * length;
3284 bcc_ptr[0] = 0; /* null terminate the string */
3285 bcc_ptr[1] = 0;
3286 bcc_ptr += 2;
3288 /* else do not bother copying these informational fields */
3289 } else {
3290 length = strnlen(bcc_ptr, 1024);
3291 if ((bcc_ptr + length) -
3292 pByteArea(smb_buffer_response) <=
3293 BCC(smb_buffer_response)) {
3294 kfree(tcon->nativeFileSystem);
3295 tcon->nativeFileSystem =
3296 kzalloc(length + 1, GFP_KERNEL);
3297 strncpy(tcon->nativeFileSystem, bcc_ptr,
3298 length);
3300 /* else do not bother copying these informational fields */
3302 if((smb_buffer_response->WordCount == 3) ||
3303 (smb_buffer_response->WordCount == 7))
3304 /* field is in same location */
3305 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3306 else
3307 tcon->Flags = 0;
3308 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3309 } else if ((rc == 0) && tcon == NULL) {
3310 /* all we need to save for IPC$ connection */
3311 ses->ipc_tid = smb_buffer_response->Tid;
3314 if (smb_buffer)
3315 cifs_buf_release(smb_buffer);
3316 return rc;
3320 cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3322 int rc = 0;
3323 int xid;
3324 struct cifsSesInfo *ses = NULL;
3325 struct task_struct *cifsd_task;
3326 char * tmp;
3328 xid = GetXid();
3330 if (cifs_sb->tcon) {
3331 ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/
3332 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3333 if (rc == -EBUSY) {
3334 FreeXid(xid);
3335 return 0;
3337 tconInfoFree(cifs_sb->tcon);
3338 if ((ses) && (ses->server)) {
3339 /* save off task so we do not refer to ses later */
3340 cifsd_task = ses->server->tsk;
3341 cFYI(1, ("About to do SMBLogoff "));
3342 rc = CIFSSMBLogoff(xid, ses);
3343 if (rc == -EBUSY) {
3344 FreeXid(xid);
3345 return 0;
3346 } else if (rc == -ESHUTDOWN) {
3347 cFYI(1,("Waking up socket by sending it signal"));
3348 if (cifsd_task) {
3349 send_sig(SIGKILL,cifsd_task,1);
3350 kthread_stop(cifsd_task);
3352 rc = 0;
3353 } /* else - we have an smb session
3354 left on this socket do not kill cifsd */
3355 } else
3356 cFYI(1, ("No session or bad tcon"));
3359 cifs_sb->tcon = NULL;
3360 tmp = cifs_sb->prepath;
3361 cifs_sb->prepathlen = 0;
3362 cifs_sb->prepath = NULL;
3363 kfree(tmp);
3364 if (ses)
3365 schedule_timeout_interruptible(msecs_to_jiffies(500));
3366 if (ses)
3367 sesInfoFree(ses);
3369 FreeXid(xid);
3370 return rc; /* BB check if we should always return zero here */
3373 int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3374 struct nls_table * nls_info)
3376 int rc = 0;
3377 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3378 int ntlmv2_flag = FALSE;
3379 int first_time = 0;
3381 /* what if server changes its buffer size after dropping the session? */
3382 if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ {
3383 rc = CIFSSMBNegotiate(xid, pSesInfo);
3384 if(rc == -EAGAIN) /* retry only once on 1st time connection */ {
3385 rc = CIFSSMBNegotiate(xid, pSesInfo);
3386 if(rc == -EAGAIN)
3387 rc = -EHOSTDOWN;
3389 if(rc == 0) {
3390 spin_lock(&GlobalMid_Lock);
3391 if(pSesInfo->server->tcpStatus != CifsExiting)
3392 pSesInfo->server->tcpStatus = CifsGood;
3393 else
3394 rc = -EHOSTDOWN;
3395 spin_unlock(&GlobalMid_Lock);
3398 first_time = 1;
3400 if (!rc) {
3401 pSesInfo->flags = 0;
3402 pSesInfo->capabilities = pSesInfo->server->capabilities;
3403 if(linuxExtEnabled == 0)
3404 pSesInfo->capabilities &= (~CAP_UNIX);
3405 /* pSesInfo->sequence_number = 0;*/
3406 cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
3407 pSesInfo->server->secMode,
3408 pSesInfo->server->capabilities,
3409 pSesInfo->server->timeAdj));
3410 if(experimEnabled < 2)
3411 rc = CIFS_SessSetup(xid, pSesInfo,
3412 first_time, nls_info);
3413 else if (extended_security
3414 && (pSesInfo->capabilities
3415 & CAP_EXTENDED_SECURITY)
3416 && (pSesInfo->server->secType == NTLMSSP)) {
3417 rc = -EOPNOTSUPP;
3418 } else if (extended_security
3419 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3420 && (pSesInfo->server->secType == RawNTLMSSP)) {
3421 cFYI(1, ("NTLMSSP sesssetup"));
3422 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3423 pSesInfo,
3424 &ntlmv2_flag,
3425 nls_info);
3426 if (!rc) {
3427 if(ntlmv2_flag) {
3428 char * v2_response;
3429 cFYI(1,("more secure NTLM ver2 hash"));
3430 if(CalcNTLMv2_partial_mac_key(pSesInfo,
3431 nls_info)) {
3432 rc = -ENOMEM;
3433 goto ss_err_exit;
3434 } else
3435 v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL);
3436 if(v2_response) {
3437 CalcNTLMv2_response(pSesInfo,v2_response);
3438 /* if(first_time)
3439 cifs_calculate_ntlmv2_mac_key(
3440 pSesInfo->server->mac_signing_key,
3441 response, ntlm_session_key, */
3442 kfree(v2_response);
3443 /* BB Put dummy sig in SessSetup PDU? */
3444 } else {
3445 rc = -ENOMEM;
3446 goto ss_err_exit;
3449 } else {
3450 SMBNTencrypt(pSesInfo->password,
3451 pSesInfo->server->cryptKey,
3452 ntlm_session_key);
3454 if(first_time)
3455 cifs_calculate_mac_key(
3456 pSesInfo->server->mac_signing_key,
3457 ntlm_session_key,
3458 pSesInfo->password);
3460 /* for better security the weaker lanman hash not sent
3461 in AuthSessSetup so we no longer calculate it */
3463 rc = CIFSNTLMSSPAuthSessSetup(xid,
3464 pSesInfo,
3465 ntlm_session_key,
3466 ntlmv2_flag,
3467 nls_info);
3469 } else { /* old style NTLM 0.12 session setup */
3470 SMBNTencrypt(pSesInfo->password,
3471 pSesInfo->server->cryptKey,
3472 ntlm_session_key);
3474 if(first_time)
3475 cifs_calculate_mac_key(
3476 pSesInfo->server->mac_signing_key,
3477 ntlm_session_key, pSesInfo->password);
3479 rc = CIFSSessSetup(xid, pSesInfo,
3480 ntlm_session_key, nls_info);
3482 if (rc) {
3483 cERROR(1,("Send error in SessSetup = %d",rc));
3484 } else {
3485 cFYI(1,("CIFS Session Established successfully"));
3486 pSesInfo->status = CifsGood;
3489 ss_err_exit:
3490 return rc;