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