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