1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/fs.h>
22#include <linux/net.h>
23#include <linux/string.h>
24#include <linux/list.h>
25#include <linux/wait.h>
26#include <linux/ipv6.h>
27#include <linux/pagemap.h>
28#include <linux/ctype.h>
29#include <linux/utsname.h>
30#include <linux/mempool.h>
31#include <linux/delay.h>
32#include <linux/completion.h>
33#include <linux/kthread.h>
34#include <linux/pagevec.h>
35#include <linux/freezer.h>
36#include <asm/uaccess.h>
37#include <asm/processor.h>
38#include "cifspdu.h"
39#include "cifsglob.h"
40#include "cifsproto.h"
41#include "cifs_unicode.h"
42#include "cifs_debug.h"
43#include "cifs_fs_sb.h"
44#include "ntlmssp.h"
45#include "nterr.h"
46#include "rfc1002pdu.h"
47#include "cn_cifs.h"
48
49#define CIFS_PORT 445
50#define RFC1001_PORT 139
51
52static DECLARE_COMPLETION(cifsd_complete);
53
54extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
55 unsigned char *p24);
56
57extern mempool_t *cifs_req_poolp;
58
59struct smb_vol {
60 char *username;
61 char *password;
62 char *domainname;
63 char *UNC;
64 char *UNCip;
65 char *in6_addr;
66 char *iocharset;
67 char source_rfc1001_name[16];
68 char target_rfc1001_name[16];
69 uid_t linux_uid;
70 gid_t linux_gid;
71 mode_t file_mode;
72 mode_t dir_mode;
73 unsigned secFlg;
74 unsigned rw:1;
75 unsigned retry:1;
76 unsigned intr:1;
77 unsigned setuids:1;
78 unsigned override_uid:1;
79 unsigned override_gid:1;
80 unsigned noperm:1;
81 unsigned no_psx_acl:1;
82 unsigned cifs_acl:1;
83 unsigned no_xattr:1;
84 unsigned server_ino:1;
85 unsigned direct_io:1;
86 unsigned remap:1;
87 unsigned posix_paths:1;
88 unsigned no_linux_ext:1;
89 unsigned sfu_emul:1;
90 unsigned nullauth:1;
91 unsigned nocase;
92 unsigned nobrl;
93 unsigned int rsize;
94 unsigned int wsize;
95 unsigned int sockopt;
96 unsigned short int port;
97 char *prepath;
98};
99
100static int ipv4_connect(struct sockaddr_in *psin_server,
101 struct socket **csocket,
102 char *netb_name,
103 char *server_netb_name);
104static int ipv6_connect(struct sockaddr_in6 *psin_server,
105 struct socket **csocket);
106
107
108
109
110
111
112
113
114
115
116
117static int
118cifs_reconnect(struct TCP_Server_Info *server)
119{
120 int rc = 0;
121 struct list_head *tmp;
122 struct cifsSesInfo *ses;
123 struct cifsTconInfo *tcon;
124 struct mid_q_entry *mid_entry;
125
126 spin_lock(&GlobalMid_Lock);
127 if (kthread_should_stop()) {
128
129
130 spin_unlock(&GlobalMid_Lock);
131 return rc;
132 } else
133 server->tcpStatus = CifsNeedReconnect;
134 spin_unlock(&GlobalMid_Lock);
135 server->maxBuf = 0;
136
137 cFYI(1, ("Reconnecting tcp session"));
138
139
140
141 read_lock(&GlobalSMBSeslock);
142 list_for_each(tmp, &GlobalSMBSessionList) {
143 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
144 if (ses->server) {
145 if (ses->server == server) {
146 ses->status = CifsNeedReconnect;
147 ses->ipc_tid = 0;
148 }
149 }
150
151 }
152 list_for_each(tmp, &GlobalTreeConnectionList) {
153 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
154 if ((tcon) && (tcon->ses) && (tcon->ses->server == server))
155 tcon->tidStatus = CifsNeedReconnect;
156 }
157 read_unlock(&GlobalSMBSeslock);
158
159 down(&server->tcpSem);
160 if (server->ssocket) {
161 cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state,
162 server->ssocket->flags));
163 kernel_sock_shutdown(server->ssocket, SHUT_WR);
164 cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx",
165 server->ssocket->state,
166 server->ssocket->flags));
167 sock_release(server->ssocket);
168 server->ssocket = NULL;
169 }
170
171 spin_lock(&GlobalMid_Lock);
172 list_for_each(tmp, &server->pending_mid_q) {
173 mid_entry = list_entry(tmp, struct
174 mid_q_entry,
175 qhead);
176 if (mid_entry) {
177 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
178
179
180
181
182 mid_entry->midState = MID_RETRY_NEEDED;
183 }
184 }
185 }
186 spin_unlock(&GlobalMid_Lock);
187 up(&server->tcpSem);
188
189 while ((!kthread_should_stop()) && (server->tcpStatus != CifsGood)) {
190 try_to_freeze();
191 if (server->protocolType == IPV6) {
192 rc = ipv6_connect(&server->addr.sockAddr6,
193 &server->ssocket);
194 } else {
195 rc = ipv4_connect(&server->addr.sockAddr,
196 &server->ssocket,
197 server->workstation_RFC1001_name,
198 server->server_RFC1001_name);
199 }
200 if (rc) {
201 cFYI(1, ("reconnect error %d", rc));
202 msleep(3000);
203 } else {
204 atomic_inc(&tcpSesReconnectCount);
205 spin_lock(&GlobalMid_Lock);
206 if (!kthread_should_stop())
207 server->tcpStatus = CifsGood;
208 server->sequence_number = 0;
209 spin_unlock(&GlobalMid_Lock);
210
211 wake_up(&server->response_q);
212 }
213 }
214 return rc;
215}
216
217
218
219
220
221
222
223
224static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize)
225{
226 struct smb_t2_rsp *pSMBt;
227 int total_data_size;
228 int data_in_this_rsp;
229 int remaining;
230
231 if (pSMB->Command != SMB_COM_TRANSACTION2)
232 return 0;
233
234
235
236 if (pSMB->WordCount != 10) {
237 cFYI(1, ("invalid transact2 word count"));
238 return -EINVAL;
239 }
240
241 pSMBt = (struct smb_t2_rsp *)pSMB;
242
243 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
244 data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount);
245
246 remaining = total_data_size - data_in_this_rsp;
247
248 if (remaining == 0)
249 return 0;
250 else if (remaining < 0) {
251 cFYI(1, ("total data %d smaller than data in frame %d",
252 total_data_size, data_in_this_rsp));
253 return -EINVAL;
254 } else {
255 cFYI(1, ("missing %d bytes from transact2, check next response",
256 remaining));
257 if (total_data_size > maxBufSize) {
258 cERROR(1, ("TotalDataSize %d is over maximum buffer %d",
259 total_data_size, maxBufSize));
260 return -EINVAL;
261 }
262 return remaining;
263 }
264}
265
266static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
267{
268 struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond;
269 struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB;
270 int total_data_size;
271 int total_in_buf;
272 int remaining;
273 int total_in_buf2;
274 char *data_area_of_target;
275 char *data_area_of_buf2;
276 __u16 byte_count;
277
278 total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount);
279
280 if (total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) {
281 cFYI(1, ("total data size of primary and secondary t2 differ"));
282 }
283
284 total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount);
285
286 remaining = total_data_size - total_in_buf;
287
288 if (remaining < 0)
289 return -EINVAL;
290
291 if (remaining == 0)
292 return 0;
293
294 total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount);
295 if (remaining < total_in_buf2) {
296 cFYI(1, ("transact2 2nd response contains too much data"));
297 }
298
299
300 data_area_of_target = (char *)&pSMBt->hdr.Protocol +
301 le16_to_cpu(pSMBt->t2_rsp.DataOffset);
302
303
304 data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol +
305 le16_to_cpu(pSMB2->t2_rsp.DataOffset);
306
307 data_area_of_target += total_in_buf;
308
309
310 memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2);
311 total_in_buf += total_in_buf2;
312 pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf);
313 byte_count = le16_to_cpu(BCC_LE(pTargetSMB));
314 byte_count += total_in_buf2;
315 BCC_LE(pTargetSMB) = cpu_to_le16(byte_count);
316
317 byte_count = pTargetSMB->smb_buf_length;
318 byte_count += total_in_buf2;
319
320
321
322 pTargetSMB->smb_buf_length = byte_count;
323
324 if (remaining == total_in_buf2) {
325 cFYI(1, ("found the last secondary response"));
326 return 0;
327 } else
328 return 1;
329
330}
331
332static int
333cifs_demultiplex_thread(struct TCP_Server_Info *server)
334{
335 int length;
336 unsigned int pdu_length, total_read;
337 struct smb_hdr *smb_buffer = NULL;
338 struct smb_hdr *bigbuf = NULL;
339 struct smb_hdr *smallbuf = NULL;
340 struct msghdr smb_msg;
341 struct kvec iov;
342 struct socket *csocket = server->ssocket;
343 struct list_head *tmp;
344 struct cifsSesInfo *ses;
345 struct task_struct *task_to_wake = NULL;
346 struct mid_q_entry *mid_entry;
347 char temp;
348 int isLargeBuf = FALSE;
349 int isMultiRsp;
350 int reconnect;
351
352 current->flags |= PF_MEMALLOC;
353 server->tsk = current;
354 cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current)));
355 write_lock(&GlobalSMBSeslock);
356 atomic_inc(&tcpSesAllocCount);
357 length = tcpSesAllocCount.counter;
358 write_unlock(&GlobalSMBSeslock);
359 complete(&cifsd_complete);
360 if (length > 1)
361 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
362 GFP_KERNEL);
363
364 set_freezable();
365 while (!kthread_should_stop()) {
366 if (try_to_freeze())
367 continue;
368 if (bigbuf == NULL) {
369 bigbuf = cifs_buf_get();
370 if (!bigbuf) {
371 cERROR(1, ("No memory for large SMB response"));
372 msleep(3000);
373
374 continue;
375 }
376 } else if (isLargeBuf) {
377
378 memset(bigbuf, 0, sizeof(struct smb_hdr));
379 }
380
381 if (smallbuf == NULL) {
382 smallbuf = cifs_small_buf_get();
383 if (!smallbuf) {
384 cERROR(1, ("No memory for SMB response"));
385 msleep(1000);
386
387 continue;
388 }
389
390 } else
391 memset(smallbuf, 0, sizeof(struct smb_hdr));
392
393 isLargeBuf = FALSE;
394 isMultiRsp = FALSE;
395 smb_buffer = smallbuf;
396 iov.iov_base = smb_buffer;
397 iov.iov_len = 4;
398 smb_msg.msg_control = NULL;
399 smb_msg.msg_controllen = 0;
400 pdu_length = 4;
401incomplete_rcv:
402 length =
403 kernel_recvmsg(csocket, &smb_msg,
404 &iov, 1, pdu_length, 0 );
405
406 if (kthread_should_stop()) {
407 break;
408 } else if (server->tcpStatus == CifsNeedReconnect) {
409 cFYI(1, ("Reconnect after server stopped responding"));
410 cifs_reconnect(server);
411 cFYI(1, ("call to reconnect done"));
412 csocket = server->ssocket;
413 continue;
414 } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
415 msleep(1);
416
417
418 if (pdu_length < 4)
419 goto incomplete_rcv;
420 else
421 continue;
422 } else if (length <= 0) {
423 if (server->tcpStatus == CifsNew) {
424 cFYI(1, ("tcp session abend after SMBnegprot"));
425
426
427
428
429 break;
430 }
431 if (!try_to_freeze() && (length == -EINTR)) {
432 cFYI(1, ("cifsd thread killed"));
433 break;
434 }
435 cFYI(1, ("Reconnect after unexpected peek error %d",
436 length));
437 cifs_reconnect(server);
438 csocket = server->ssocket;
439 wake_up(&server->response_q);
440 continue;
441 } else if (length < pdu_length) {
442 cFYI(1, ("requested %d bytes but only got %d bytes",
443 pdu_length, length));
444 pdu_length -= length;
445 msleep(1);
446 goto incomplete_rcv;
447 }
448
449
450
451
452
453
454
455 temp = *((char *) smb_buffer);
456
457
458
459
460 pdu_length = ntohl(smb_buffer->smb_buf_length);
461 smb_buffer->smb_buf_length = pdu_length;
462
463 cFYI(1, ("rfc1002 length 0x%x", pdu_length+4));
464
465 if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) {
466 continue;
467 } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) {
468 cFYI(1, ("Good RFC 1002 session rsp"));
469 continue;
470 } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) {
471
472
473 cFYI(1, ("Negative RFC1002 Session Response Error 0x%x)",
474 pdu_length));
475 if (server->tcpStatus == CifsNew) {
476
477
478
479 break;
480 } else {
481
482
483 msleep(1000);
484
485
486
487
488
489 server->addr.sockAddr.sin_port =
490 htons(CIFS_PORT);
491 cifs_reconnect(server);
492 csocket = server->ssocket;
493 wake_up(&server->response_q);
494 continue;
495 }
496 } else if (temp != (char) 0) {
497 cERROR(1, ("Unknown RFC 1002 frame"));
498 cifs_dump_mem(" Received Data: ", (char *)smb_buffer,
499 length);
500 cifs_reconnect(server);
501 csocket = server->ssocket;
502 continue;
503 }
504
505
506 if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) ||
507 (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) {
508 cERROR(1, ("Invalid size SMB length %d pdu_length %d",
509 length, pdu_length+4));
510 cifs_reconnect(server);
511 csocket = server->ssocket;
512 wake_up(&server->response_q);
513 continue;
514 }
515
516
517 reconnect = 0;
518
519 if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
520 isLargeBuf = TRUE;
521 memcpy(bigbuf, smallbuf, 4);
522 smb_buffer = bigbuf;
523 }
524 length = 0;
525 iov.iov_base = 4 + (char *)smb_buffer;
526 iov.iov_len = pdu_length;
527 for (total_read = 0; total_read < pdu_length;
528 total_read += length) {
529 length = kernel_recvmsg(csocket, &smb_msg, &iov, 1,
530 pdu_length - total_read, 0);
531 if (kthread_should_stop() ||
532 (length == -EINTR)) {
533
534 reconnect = 2;
535 break;
536 } else if (server->tcpStatus == CifsNeedReconnect) {
537 cifs_reconnect(server);
538 csocket = server->ssocket;
539
540
541 reconnect = 1;
542 break;
543 } else if ((length == -ERESTARTSYS) ||
544 (length == -EAGAIN)) {
545 msleep(1);
546
547
548
549 length = 0;
550 continue;
551 } else if (length <= 0) {
552 cERROR(1, ("Received no data, expecting %d",
553 pdu_length - total_read));
554 cifs_reconnect(server);
555 csocket = server->ssocket;
556 reconnect = 1;
557 break;
558 }
559 }
560 if (reconnect == 2)
561 break;
562 else if (reconnect == 1)
563 continue;
564
565 length += 4;
566
567
568 dump_smb(smb_buffer, length);
569 if (checkSMB(smb_buffer, smb_buffer->Mid, total_read+4)) {
570 cifs_dump_mem("Bad SMB: ", smb_buffer, 48);
571 continue;
572 }
573
574
575 task_to_wake = NULL;
576 spin_lock(&GlobalMid_Lock);
577 list_for_each(tmp, &server->pending_mid_q) {
578 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
579
580 if ((mid_entry->mid == smb_buffer->Mid) &&
581 (mid_entry->midState == MID_REQUEST_SUBMITTED) &&
582 (mid_entry->command == smb_buffer->Command)) {
583 if (check2ndT2(smb_buffer,server->maxBuf) > 0) {
584
585 isMultiRsp = TRUE;
586 if (mid_entry->resp_buf) {
587
588 if (coalesce_t2(smb_buffer,
589 mid_entry->resp_buf)) {
590 mid_entry->multiRsp = 1;
591 break;
592 } else {
593
594 mid_entry->multiEnd = 1;
595 goto multi_t2_fnd;
596 }
597 } else {
598 if (!isLargeBuf) {
599 cERROR(1,("1st trans2 resp needs bigbuf"));
600
601
602 } else {
603
604 mid_entry->resp_buf =
605 smb_buffer;
606 mid_entry->largeBuf = 1;
607 bigbuf = NULL;
608 }
609 }
610 break;
611 }
612 mid_entry->resp_buf = smb_buffer;
613 if (isLargeBuf)
614 mid_entry->largeBuf = 1;
615 else
616 mid_entry->largeBuf = 0;
617multi_t2_fnd:
618 task_to_wake = mid_entry->tsk;
619 mid_entry->midState = MID_RESPONSE_RECEIVED;
620#ifdef CONFIG_CIFS_STATS2
621 mid_entry->when_received = jiffies;
622#endif
623
624
625
626 server->lstrp = jiffies;
627 break;
628 }
629 }
630 spin_unlock(&GlobalMid_Lock);
631 if (task_to_wake) {
632
633 if (!isMultiRsp) {
634
635 if (isLargeBuf)
636 bigbuf = NULL;
637 else
638 smallbuf = NULL;
639 }
640 wake_up_process(task_to_wake);
641 } else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
642 && (isMultiRsp == FALSE)) {
643 cERROR(1, ("No task to wake, unknown frame received! "
644 "NumMids %d", midCount.counter));
645 cifs_dump_mem("Received Data is: ", (char *)smb_buffer,
646 sizeof(struct smb_hdr));
647#ifdef CONFIG_CIFS_DEBUG2
648 cifs_dump_detail(smb_buffer);
649 cifs_dump_mids(server);
650#endif
651
652 }
653 }
654
655 spin_lock(&GlobalMid_Lock);
656 server->tcpStatus = CifsExiting;
657 server->tsk = NULL;
658
659
660
661 if (atomic_read(&server->inFlight) >= cifs_max_pending)
662 atomic_set(&server->inFlight, cifs_max_pending - 1);
663
664
665 spin_unlock(&GlobalMid_Lock);
666
667
668
669
670
671 wake_up_all(&server->request_q);
672
673 msleep(125);
674
675 if (server->ssocket) {
676 sock_release(csocket);
677 server->ssocket = NULL;
678 }
679
680 cifs_buf_release(bigbuf);
681 if (smallbuf)
682 cifs_small_buf_release(smallbuf);
683
684 read_lock(&GlobalSMBSeslock);
685 if (list_empty(&server->pending_mid_q)) {
686
687
688 list_for_each(tmp, &GlobalSMBSessionList) {
689 ses =
690 list_entry(tmp, struct cifsSesInfo,
691 cifsSessionList);
692 if (ses->server == server) {
693 ses->status = CifsExiting;
694 ses->server = NULL;
695 }
696 }
697 read_unlock(&GlobalSMBSeslock);
698 } else {
699
700
701
702 list_for_each(tmp, &GlobalSMBSessionList) {
703 ses = list_entry(tmp, struct cifsSesInfo,
704 cifsSessionList);
705 if (ses->server == server)
706 ses->status = CifsExiting;
707 }
708
709 spin_lock(&GlobalMid_Lock);
710 list_for_each(tmp, &server->pending_mid_q) {
711 mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
712 if (mid_entry->midState == MID_REQUEST_SUBMITTED) {
713 cFYI(1, ("Clearing Mid 0x%x - waking up ",
714 mid_entry->mid));
715 task_to_wake = mid_entry->tsk;
716 if (task_to_wake)
717 wake_up_process(task_to_wake);
718 }
719 }
720 spin_unlock(&GlobalMid_Lock);
721 read_unlock(&GlobalSMBSeslock);
722
723 msleep(125);
724 }
725
726 if (!list_empty(&server->pending_mid_q)) {
727
728
729
730
731
732
733 cFYI(1, ("Wait for exit from demultiplex thread"));
734 msleep(46000);
735
736
737 }
738
739 write_lock(&GlobalSMBSeslock);
740 atomic_dec(&tcpSesAllocCount);
741 length = tcpSesAllocCount.counter;
742
743
744
745
746
747 list_for_each(tmp, &GlobalSMBSessionList) {
748 ses = list_entry(tmp, struct cifsSesInfo,
749 cifsSessionList);
750 if (ses->server == server)
751 ses->server = NULL;
752 }
753 write_unlock(&GlobalSMBSeslock);
754
755 kfree(server->hostname);
756 kfree(server);
757 if (length > 0)
758 mempool_resize(cifs_req_poolp, length + cifs_min_rcv,
759 GFP_KERNEL);
760
761 return 0;
762}
763
764
765static char *
766extract_hostname(const char *unc)
767{
768 const char *src;
769 char *dst, *delim;
770 unsigned int len;
771
772
773
774 src = unc + 2;
775
776
777 delim = strchr(src, '\\');
778 if (!delim)
779 return ERR_PTR(-EINVAL);
780
781 len = delim - src;
782 dst = kmalloc((len + 1), GFP_KERNEL);
783 if (dst == NULL)
784 return ERR_PTR(-ENOMEM);
785
786 memcpy(dst, src, len);
787 dst[len] = '\0';
788
789 return dst;
790}
791
792static int
793cifs_parse_mount_options(char *options, const char *devname,
794 struct smb_vol *vol)
795{
796 char *value;
797 char *data;
798 unsigned int temp_len, i, j;
799 char separator[2];
800
801 separator[0] = ',';
802 separator[1] = 0;
803
804 if (Local_System_Name[0] != 0)
805 memcpy(vol->source_rfc1001_name, Local_System_Name, 15);
806 else {
807 char *nodename = utsname()->nodename;
808 int n = strnlen(nodename, 15);
809 memset(vol->source_rfc1001_name, 0x20, 15);
810 for (i = 0; i < n; i++) {
811
812
813
814 vol->source_rfc1001_name[i] = toupper(nodename[i]);
815 }
816 }
817 vol->source_rfc1001_name[15] = 0;
818
819
820 vol->target_rfc1001_name[0] = 0;
821 vol->linux_uid = current->uid;
822 vol->linux_gid = current->gid;
823 vol->dir_mode = S_IRWXUGO;
824
825 vol->file_mode = (S_IRWXUGO | S_ISGID) & (~S_IXGRP);
826
827
828 vol->rw = TRUE;
829
830 vol->posix_paths = 1;
831
832 if (!options)
833 return 1;
834
835 if (strncmp(options, "sep=", 4) == 0) {
836 if (options[4] != 0) {
837 separator[0] = options[4];
838 options += 5;
839 } else {
840 cFYI(1, ("Null separator not allowed"));
841 }
842 }
843
844 while ((data = strsep(&options, separator)) != NULL) {
845 if (!*data)
846 continue;
847 if ((value = strchr(data, '=')) != NULL)
848 *value++ = '\0';
849
850
851 if (strnicmp(data, "user_xattr", 10) == 0) {
852 vol->no_xattr = 0;
853 } else if (strnicmp(data, "nouser_xattr", 12) == 0) {
854 vol->no_xattr = 1;
855 } else if (strnicmp(data, "user", 4) == 0) {
856 if (!value) {
857 printk(KERN_WARNING
858 "CIFS: invalid or missing username\n");
859 return 1;
860 } else if (!*value) {
861
862 vol->nullauth = 1;
863 }
864 if (strnlen(value, 200) < 200) {
865 vol->username = value;
866 } else {
867 printk(KERN_WARNING "CIFS: username too long\n");
868 return 1;
869 }
870 } else if (strnicmp(data, "pass", 4) == 0) {
871 if (!value) {
872 vol->password = NULL;
873 continue;
874 } else if (value[0] == 0) {
875
876
877
878
879 if (value[1] != separator[0]) {
880 vol->password = NULL;
881 continue;
882 }
883 }
884 temp_len = strlen(value);
885
886
887
888
889
890
891
892
893
894
895
896
897
898 if ((value[temp_len] == 0) &&
899 (value[temp_len+1] == separator[0])) {
900
901 value[temp_len] = separator[0];
902 temp_len += 2;
903 while (value[temp_len] != 0) {
904 if (value[temp_len] == separator[0]) {
905 if (value[temp_len+1] ==
906 separator[0]) {
907
908 temp_len++;
909 } else {
910
911
912 break;
913 }
914 }
915 temp_len++;
916 }
917 if (value[temp_len] == 0) {
918 options = NULL;
919 } else {
920 value[temp_len] = 0;
921
922 options = value + temp_len + 1;
923 }
924
925
926
927 vol->password = kzalloc(temp_len, GFP_KERNEL);
928 if (vol->password == NULL) {
929 printk(KERN_WARNING "CIFS: no memory "
930 "for password\n");
931 return 1;
932 }
933 for (i = 0, j = 0; i < temp_len; i++, j++) {
934 vol->password[j] = value[i];
935 if (value[i] == separator[0]
936 && value[i+1] == separator[0]) {
937
938 i++;
939 }
940 }
941 vol->password[j] = 0;
942 } else {
943 vol->password = kzalloc(temp_len+1, GFP_KERNEL);
944 if (vol->password == NULL) {
945 printk(KERN_WARNING "CIFS: no memory "
946 "for password\n");
947 return 1;
948 }
949 strcpy(vol->password, value);
950 }
951 } else if (strnicmp(data, "ip", 2) == 0) {
952 if (!value || !*value) {
953 vol->UNCip = NULL;
954 } else if (strnlen(value, 35) < 35) {
955 vol->UNCip = value;
956 } else {
957 printk(KERN_WARNING "CIFS: ip address "
958 "too long\n");
959 return 1;
960 }
961 } else if (strnicmp(data, "sec", 3) == 0) {
962 if (!value || !*value) {
963 cERROR(1, ("no security value specified"));
964 continue;
965 } else if (strnicmp(value, "krb5i", 5) == 0) {
966 vol->secFlg |= CIFSSEC_MAY_KRB5 |
967 CIFSSEC_MUST_SIGN;
968 } else if (strnicmp(value, "krb5p", 5) == 0) {
969
970
971 cERROR(1, ("Krb5 cifs privacy not supported"));
972 return 1;
973 } else if (strnicmp(value, "krb5", 4) == 0) {
974 vol->secFlg |= CIFSSEC_MAY_KRB5;
975 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
976 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
977 CIFSSEC_MUST_SIGN;
978 } else if (strnicmp(value, "ntlmv2", 6) == 0) {
979 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
980 } else if (strnicmp(value, "ntlmi", 5) == 0) {
981 vol->secFlg |= CIFSSEC_MAY_NTLM |
982 CIFSSEC_MUST_SIGN;
983 } else if (strnicmp(value, "ntlm", 4) == 0) {
984
985 vol->secFlg |= CIFSSEC_MAY_NTLM;
986 } else if (strnicmp(value, "nontlm", 6) == 0) {
987
988 vol->secFlg |= CIFSSEC_MAY_NTLMV2;
989#ifdef CONFIG_CIFS_WEAK_PW_HASH
990 } else if (strnicmp(value, "lanman", 6) == 0) {
991 vol->secFlg |= CIFSSEC_MAY_LANMAN;
992#endif
993 } else if (strnicmp(value, "none", 4) == 0) {
994 vol->nullauth = 1;
995 } else {
996 cERROR(1, ("bad security option: %s", value));
997 return 1;
998 }
999 } else if ((strnicmp(data, "unc", 3) == 0)
1000 || (strnicmp(data, "target", 6) == 0)
1001 || (strnicmp(data, "path", 4) == 0)) {
1002 if (!value || !*value) {
1003 printk(KERN_WARNING "CIFS: invalid path to "
1004 "network resource\n");
1005 return 1;
1006 }
1007 if ((temp_len = strnlen(value, 300)) < 300) {
1008 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1009 if (vol->UNC == NULL)
1010 return 1;
1011 strcpy(vol->UNC, value);
1012 if (strncmp(vol->UNC, "//", 2) == 0) {
1013 vol->UNC[0] = '\\';
1014 vol->UNC[1] = '\\';
1015 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1016 printk(KERN_WARNING
1017 "CIFS: UNC Path does not begin "
1018 "with // or \\\\ \n");
1019 return 1;
1020 }
1021 } else {
1022 printk(KERN_WARNING "CIFS: UNC name too long\n");
1023 return 1;
1024 }
1025 } else if ((strnicmp(data, "domain", 3) == 0)
1026 || (strnicmp(data, "workgroup", 5) == 0)) {
1027 if (!value || !*value) {
1028 printk(KERN_WARNING "CIFS: invalid domain name\n");
1029 return 1;
1030 }
1031
1032
1033 if (strnlen(value, 256) < 256) {
1034 vol->domainname = value;
1035 cFYI(1, ("Domain name set"));
1036 } else {
1037 printk(KERN_WARNING "CIFS: domain name too "
1038 "long\n");
1039 return 1;
1040 }
1041 } else if (strnicmp(data, "prefixpath", 10) == 0) {
1042 if (!value || !*value) {
1043 printk(KERN_WARNING
1044 "CIFS: invalid path prefix\n");
1045 return 1;
1046 }
1047 if ((temp_len = strnlen(value, 1024)) < 1024) {
1048 if (value[0] != '/')
1049 temp_len++;
1050 vol->prepath = kmalloc(temp_len+1, GFP_KERNEL);
1051 if (vol->prepath == NULL)
1052 return 1;
1053 if (value[0] != '/') {
1054 vol->prepath[0] = '/';
1055 strcpy(vol->prepath+1, value);
1056 } else
1057 strcpy(vol->prepath, value);
1058 cFYI(1, ("prefix path %s", vol->prepath));
1059 } else {
1060 printk(KERN_WARNING "CIFS: prefix too long\n");
1061 return 1;
1062 }
1063 } else if (strnicmp(data, "iocharset", 9) == 0) {
1064 if (!value || !*value) {
1065 printk(KERN_WARNING "CIFS: invalid iocharset "
1066 "specified\n");
1067 return 1;
1068 }
1069 if (strnlen(value, 65) < 65) {
1070 if (strnicmp(value, "default", 7))
1071 vol->iocharset = value;
1072
1073
1074 cFYI(1, ("iocharset set to %s", value));
1075 } else {
1076 printk(KERN_WARNING "CIFS: iocharset name "
1077 "too long.\n");
1078 return 1;
1079 }
1080 } else if (strnicmp(data, "uid", 3) == 0) {
1081 if (value && *value) {
1082 vol->linux_uid =
1083 simple_strtoul(value, &value, 0);
1084 vol->override_uid = 1;
1085 }
1086 } else if (strnicmp(data, "gid", 3) == 0) {
1087 if (value && *value) {
1088 vol->linux_gid =
1089 simple_strtoul(value, &value, 0);
1090 vol->override_gid = 1;
1091 }
1092 } else if (strnicmp(data, "file_mode", 4) == 0) {
1093 if (value && *value) {
1094 vol->file_mode =
1095 simple_strtoul(value, &value, 0);
1096 }
1097 } else if (strnicmp(data, "dir_mode", 4) == 0) {
1098 if (value && *value) {
1099 vol->dir_mode =
1100 simple_strtoul(value, &value, 0);
1101 }
1102 } else if (strnicmp(data, "dirmode", 4) == 0) {
1103 if (value && *value) {
1104 vol->dir_mode =
1105 simple_strtoul(value, &value, 0);
1106 }
1107 } else if (strnicmp(data, "port", 4) == 0) {
1108 if (value && *value) {
1109 vol->port =
1110 simple_strtoul(value, &value, 0);
1111 }
1112 } else if (strnicmp(data, "rsize", 5) == 0) {
1113 if (value && *value) {
1114 vol->rsize =
1115 simple_strtoul(value, &value, 0);
1116 }
1117 } else if (strnicmp(data, "wsize", 5) == 0) {
1118 if (value && *value) {
1119 vol->wsize =
1120 simple_strtoul(value, &value, 0);
1121 }
1122 } else if (strnicmp(data, "sockopt", 5) == 0) {
1123 if (value && *value) {
1124 vol->sockopt =
1125 simple_strtoul(value, &value, 0);
1126 }
1127 } else if (strnicmp(data, "netbiosname", 4) == 0) {
1128 if (!value || !*value || (*value == ' ')) {
1129 cFYI(1, ("invalid (empty) netbiosname"));
1130 } else {
1131 memset(vol->source_rfc1001_name, 0x20, 15);
1132 for (i = 0; i < 15; i++) {
1133
1134
1135
1136
1137
1138 if (value[i] == 0)
1139 break;
1140 else
1141 vol->source_rfc1001_name[i] =
1142 value[i];
1143 }
1144
1145
1146 if ((i == 15) && (value[i] != 0))
1147 printk(KERN_WARNING "CIFS: netbiosname"
1148 " longer than 15 truncated.\n");
1149 }
1150 } else if (strnicmp(data, "servern", 7) == 0) {
1151
1152 if (!value || !*value || (*value == ' ')) {
1153 cFYI(1, ("empty server netbiosname specified"));
1154 } else {
1155
1156 memset(vol->target_rfc1001_name, 0x20, 16);
1157
1158 for (i = 0; i < 15; i++) {
1159
1160
1161
1162
1163
1164
1165 if (value[i] == 0)
1166 break;
1167 else
1168 vol->target_rfc1001_name[i] =
1169 value[i];
1170 }
1171
1172
1173 if ((i == 15) && (value[i] != 0))
1174 printk(KERN_WARNING "CIFS: server net"
1175 "biosname longer than 15 truncated.\n");
1176 }
1177 } else if (strnicmp(data, "credentials", 4) == 0) {
1178
1179 } else if (strnicmp(data, "version", 3) == 0) {
1180
1181 } else if (strnicmp(data, "guest", 5) == 0) {
1182
1183 } else if (strnicmp(data, "rw", 2) == 0) {
1184 vol->rw = TRUE;
1185 } else if ((strnicmp(data, "suid", 4) == 0) ||
1186 (strnicmp(data, "nosuid", 6) == 0) ||
1187 (strnicmp(data, "exec", 4) == 0) ||
1188 (strnicmp(data, "noexec", 6) == 0) ||
1189 (strnicmp(data, "nodev", 5) == 0) ||
1190 (strnicmp(data, "noauto", 6) == 0) ||
1191 (strnicmp(data, "dev", 3) == 0)) {
1192
1193
1194
1195
1196
1197
1198 continue;
1199 } else if (strnicmp(data, "ro", 2) == 0) {
1200 vol->rw = FALSE;
1201 } else if (strnicmp(data, "hard", 4) == 0) {
1202 vol->retry = 1;
1203 } else if (strnicmp(data, "soft", 4) == 0) {
1204 vol->retry = 0;
1205 } else if (strnicmp(data, "perm", 4) == 0) {
1206 vol->noperm = 0;
1207 } else if (strnicmp(data, "noperm", 6) == 0) {
1208 vol->noperm = 1;
1209 } else if (strnicmp(data, "mapchars", 8) == 0) {
1210 vol->remap = 1;
1211 } else if (strnicmp(data, "nomapchars", 10) == 0) {
1212 vol->remap = 0;
1213 } else if (strnicmp(data, "sfu", 3) == 0) {
1214 vol->sfu_emul = 1;
1215 } else if (strnicmp(data, "nosfu", 5) == 0) {
1216 vol->sfu_emul = 0;
1217 } else if (strnicmp(data, "posixpaths", 10) == 0) {
1218 vol->posix_paths = 1;
1219 } else if (strnicmp(data, "noposixpaths", 12) == 0) {
1220 vol->posix_paths = 0;
1221 } else if (strnicmp(data, "nounix", 6) == 0) {
1222 vol->no_linux_ext = 1;
1223 } else if (strnicmp(data, "nolinux", 7) == 0) {
1224 vol->no_linux_ext = 1;
1225 } else if ((strnicmp(data, "nocase", 6) == 0) ||
1226 (strnicmp(data, "ignorecase", 10) == 0)) {
1227 vol->nocase = 1;
1228 } else if (strnicmp(data, "brl", 3) == 0) {
1229 vol->nobrl = 0;
1230 } else if ((strnicmp(data, "nobrl", 5) == 0) ||
1231 (strnicmp(data, "nolock", 6) == 0)) {
1232 vol->nobrl = 1;
1233
1234
1235
1236 if (vol->file_mode ==
1237 (S_IALLUGO & ~(S_ISUID | S_IXGRP)))
1238 vol->file_mode = S_IALLUGO;
1239 } else if (strnicmp(data, "setuids", 7) == 0) {
1240 vol->setuids = 1;
1241 } else if (strnicmp(data, "nosetuids", 9) == 0) {
1242 vol->setuids = 0;
1243 } else if (strnicmp(data, "nohard", 6) == 0) {
1244 vol->retry = 0;
1245 } else if (strnicmp(data, "nosoft", 6) == 0) {
1246 vol->retry = 1;
1247 } else if (strnicmp(data, "nointr", 6) == 0) {
1248 vol->intr = 0;
1249 } else if (strnicmp(data, "intr", 4) == 0) {
1250 vol->intr = 1;
1251 } else if (strnicmp(data, "serverino", 7) == 0) {
1252 vol->server_ino = 1;
1253 } else if (strnicmp(data, "noserverino", 9) == 0) {
1254 vol->server_ino = 0;
1255 } else if (strnicmp(data, "cifsacl", 7) == 0) {
1256 vol->cifs_acl = 1;
1257 } else if (strnicmp(data, "nocifsacl", 9) == 0) {
1258 vol->cifs_acl = 0;
1259 } else if (strnicmp(data, "acl", 3) == 0) {
1260 vol->no_psx_acl = 0;
1261 } else if (strnicmp(data, "noacl", 5) == 0) {
1262 vol->no_psx_acl = 1;
1263 } else if (strnicmp(data, "sign", 4) == 0) {
1264 vol->secFlg |= CIFSSEC_MUST_SIGN;
1265
1266
1267 } else if (strnicmp(data, "direct", 6) == 0) {
1268 vol->direct_io = 1;
1269 } else if (strnicmp(data, "forcedirectio", 13) == 0) {
1270 vol->direct_io = 1;
1271 } else if (strnicmp(data, "in6_addr", 8) == 0) {
1272 if (!value || !*value) {
1273 vol->in6_addr = NULL;
1274 } else if (strnlen(value, 49) == 48) {
1275 vol->in6_addr = value;
1276 } else {
1277 printk(KERN_WARNING "CIFS: ip v6 address not "
1278 "48 characters long\n");
1279 return 1;
1280 }
1281 } else if (strnicmp(data, "noac", 4) == 0) {
1282 printk(KERN_WARNING "CIFS: Mount option noac not "
1283 "supported. Instead set "
1284 "/proc/fs/cifs/LookupCacheEnabled to 0\n");
1285 } else
1286 printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
1287 data);
1288 }
1289 if (vol->UNC == NULL) {
1290 if (devname == NULL) {
1291 printk(KERN_WARNING "CIFS: Missing UNC name for mount "
1292 "target\n");
1293 return 1;
1294 }
1295 if ((temp_len = strnlen(devname, 300)) < 300) {
1296 vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
1297 if (vol->UNC == NULL)
1298 return 1;
1299 strcpy(vol->UNC, devname);
1300 if (strncmp(vol->UNC, "//", 2) == 0) {
1301 vol->UNC[0] = '\\';
1302 vol->UNC[1] = '\\';
1303 } else if (strncmp(vol->UNC, "\\\\", 2) != 0) {
1304 printk(KERN_WARNING "CIFS: UNC Path does not "
1305 "begin with // or \\\\ \n");
1306 return 1;
1307 }
1308 } else {
1309 printk(KERN_WARNING "CIFS: UNC name too long\n");
1310 return 1;
1311 }
1312 }
1313 if (vol->UNCip == NULL)
1314 vol->UNCip = &vol->UNC[2];
1315
1316 return 0;
1317}
1318
1319static struct cifsSesInfo *
1320cifs_find_tcp_session(struct in_addr *target_ip_addr,
1321 struct in6_addr *target_ip6_addr,
1322 char *userName, struct TCP_Server_Info **psrvTcp)
1323{
1324 struct list_head *tmp;
1325 struct cifsSesInfo *ses;
1326 *psrvTcp = NULL;
1327 read_lock(&GlobalSMBSeslock);
1328
1329 list_for_each(tmp, &GlobalSMBSessionList) {
1330 ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
1331 if (ses->server) {
1332 if ((target_ip_addr &&
1333 (ses->server->addr.sockAddr.sin_addr.s_addr
1334 == target_ip_addr->s_addr)) || (target_ip6_addr
1335 && memcmp(&ses->server->addr.sockAddr6.sin6_addr,
1336 target_ip6_addr, sizeof(*target_ip6_addr)))) {
1337
1338
1339
1340
1341 *psrvTcp = ses->server;
1342
1343
1344 if (strncmp
1345 (ses->userName, userName,
1346 MAX_USERNAME_SIZE) == 0){
1347 read_unlock(&GlobalSMBSeslock);
1348
1349
1350 return ses;
1351 }
1352 }
1353 }
1354
1355 }
1356 read_unlock(&GlobalSMBSeslock);
1357 return NULL;
1358}
1359
1360static struct cifsTconInfo *
1361find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
1362{
1363 struct list_head *tmp;
1364 struct cifsTconInfo *tcon;
1365
1366 read_lock(&GlobalSMBSeslock);
1367 list_for_each(tmp, &GlobalTreeConnectionList) {
1368 cFYI(1, ("Next tcon"));
1369 tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
1370 if (tcon->ses) {
1371 if (tcon->ses->server) {
1372 cFYI(1,
1373 ("old ip addr: %x == new ip %x ?",
1374 tcon->ses->server->addr.sockAddr.sin_addr.
1375 s_addr, new_target_ip_addr));
1376 if (tcon->ses->server->addr.sockAddr.sin_addr.
1377 s_addr == new_target_ip_addr) {
1378
1379
1380
1381 cFYI(1,
1382 ("IP match, old UNC: %s new: %s",
1383 tcon->treeName, uncName));
1384 if (strncmp
1385 (tcon->treeName, uncName,
1386 MAX_TREE_SIZE) == 0) {
1387 cFYI(1,
1388 ("and old usr: %s new: %s",
1389 tcon->treeName, uncName));
1390 if (strncmp
1391 (tcon->ses->userName,
1392 userName,
1393 MAX_USERNAME_SIZE) == 0) {
1394 read_unlock(&GlobalSMBSeslock);
1395
1396
1397 return tcon;
1398 }
1399 }
1400 }
1401 }
1402 }
1403 }
1404 read_unlock(&GlobalSMBSeslock);
1405 return NULL;
1406}
1407
1408int
1409connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
1410 const char *old_path, const struct nls_table *nls_codepage,
1411 int remap)
1412{
1413 unsigned char *referrals = NULL;
1414 unsigned int num_referrals;
1415 int rc = 0;
1416
1417 rc = get_dfs_path(xid, pSesInfo, old_path, nls_codepage,
1418 &num_referrals, &referrals, remap);
1419
1420
1421
1422
1423
1424 kfree(referrals);
1425
1426 return rc;
1427}
1428
1429int
1430get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
1431 const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
1432 unsigned char **preferrals, int remap)
1433{
1434 char *temp_unc;
1435 int rc = 0;
1436
1437 *pnum_referrals = 0;
1438
1439 if (pSesInfo->ipc_tid == 0) {
1440 temp_unc = kmalloc(2 +
1441 strnlen(pSesInfo->serverName,
1442 SERVER_NAME_LEN_WITH_NULL * 2)
1443 + 1 + 4 + 2,
1444 GFP_KERNEL);
1445 if (temp_unc == NULL)
1446 return -ENOMEM;
1447 temp_unc[0] = '\\';
1448 temp_unc[1] = '\\';
1449 strcpy(temp_unc + 2, pSesInfo->serverName);
1450 strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$");
1451 rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage);
1452 cFYI(1,
1453 ("CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid));
1454 kfree(temp_unc);
1455 }
1456 if (rc == 0)
1457 rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
1458 pnum_referrals, nls_codepage, remap);
1459
1460 return rc;
1461}
1462
1463
1464static void rfc1002mangle(char *target, char *source, unsigned int length)
1465{
1466 unsigned int i, j;
1467
1468 for (i = 0, j = 0; i < (length); i++) {
1469
1470 target[j] = 'A' + (0x0F & (source[i] >> 4));
1471 target[j+1] = 'A' + (0x0F & source[i]);
1472 j += 2;
1473 }
1474
1475}
1476
1477
1478static int
1479ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
1480 char *netbios_name, char *target_name)
1481{
1482 int rc = 0;
1483 int connected = 0;
1484 __be16 orig_port = 0;
1485
1486 if (*csocket == NULL) {
1487 rc = sock_create_kern(PF_INET, SOCK_STREAM,
1488 IPPROTO_TCP, csocket);
1489 if (rc < 0) {
1490 cERROR(1, ("Error %d creating socket", rc));
1491 *csocket = NULL;
1492 return rc;
1493 } else {
1494
1495 cFYI(1, ("Socket created"));
1496 (*csocket)->sk->sk_allocation = GFP_NOFS;
1497 }
1498 }
1499
1500 psin_server->sin_family = AF_INET;
1501 if (psin_server->sin_port) {
1502 rc = (*csocket)->ops->connect(*csocket,
1503 (struct sockaddr *) psin_server,
1504 sizeof(struct sockaddr_in), 0);
1505 if (rc >= 0)
1506 connected = 1;
1507 }
1508
1509 if (!connected) {
1510
1511
1512 orig_port = psin_server->sin_port;
1513
1514
1515 if (psin_server->sin_port != htons(CIFS_PORT)) {
1516 psin_server->sin_port = htons(CIFS_PORT);
1517
1518 rc = (*csocket)->ops->connect(*csocket,
1519 (struct sockaddr *) psin_server,
1520 sizeof(struct sockaddr_in), 0);
1521 if (rc >= 0)
1522 connected = 1;
1523 }
1524 }
1525 if (!connected) {
1526 psin_server->sin_port = htons(RFC1001_PORT);
1527 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1528 psin_server,
1529 sizeof(struct sockaddr_in), 0);
1530 if (rc >= 0)
1531 connected = 1;
1532 }
1533
1534
1535
1536 if (!connected) {
1537 if (orig_port)
1538 psin_server->sin_port = orig_port;
1539 cFYI(1, ("Error %d connecting to server via ipv4", rc));
1540 sock_release(*csocket);
1541 *csocket = NULL;
1542 return rc;
1543 }
1544
1545
1546
1547 cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx",
1548 (*csocket)->sk->sk_sndbuf,
1549 (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo));
1550 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1551
1552 if ((*csocket)->sk->sk_sndbuf < (200 * 1024))
1553 (*csocket)->sk->sk_sndbuf = 200 * 1024;
1554 if ((*csocket)->sk->sk_rcvbuf < (140 * 1024))
1555 (*csocket)->sk->sk_rcvbuf = 140 * 1024;
1556
1557
1558 if (psin_server->sin_port == htons(RFC1001_PORT)) {
1559
1560
1561
1562 struct rfc1002_session_packet *ses_init_buf;
1563 struct smb_hdr *smb_buf;
1564 ses_init_buf = kzalloc(sizeof(struct rfc1002_session_packet),
1565 GFP_KERNEL);
1566 if (ses_init_buf) {
1567 ses_init_buf->trailer.session_req.called_len = 32;
1568 if (target_name && (target_name[0] != 0)) {
1569 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1570 target_name, 16);
1571 } else {
1572 rfc1002mangle(ses_init_buf->trailer.session_req.called_name,
1573 DEFAULT_CIFS_CALLED_NAME, 16);
1574 }
1575
1576 ses_init_buf->trailer.session_req.calling_len = 32;
1577
1578
1579 if (netbios_name && (netbios_name[0] != 0)) {
1580 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1581 netbios_name, 16);
1582 } else {
1583 rfc1002mangle(ses_init_buf->trailer.session_req.calling_name,
1584 "LINUX_CIFS_CLNT", 16);
1585 }
1586 ses_init_buf->trailer.session_req.scope1 = 0;
1587 ses_init_buf->trailer.session_req.scope2 = 0;
1588 smb_buf = (struct smb_hdr *)ses_init_buf;
1589
1590 smb_buf->smb_buf_length = 0x81000044;
1591 rc = smb_send(*csocket, smb_buf, 0x44,
1592 (struct sockaddr *)psin_server);
1593 kfree(ses_init_buf);
1594 msleep(1);
1595
1596
1597
1598
1599
1600
1601
1602 }
1603
1604
1605
1606 }
1607
1608 return rc;
1609}
1610
1611static int
1612ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
1613{
1614 int rc = 0;
1615 int connected = 0;
1616 __be16 orig_port = 0;
1617
1618 if (*csocket == NULL) {
1619 rc = sock_create_kern(PF_INET6, SOCK_STREAM,
1620 IPPROTO_TCP, csocket);
1621 if (rc < 0) {
1622 cERROR(1, ("Error %d creating ipv6 socket", rc));
1623 *csocket = NULL;
1624 return rc;
1625 } else {
1626
1627 cFYI(1, ("ipv6 Socket created"));
1628 (*csocket)->sk->sk_allocation = GFP_NOFS;
1629 }
1630 }
1631
1632 psin_server->sin6_family = AF_INET6;
1633
1634 if (psin_server->sin6_port) {
1635 rc = (*csocket)->ops->connect(*csocket,
1636 (struct sockaddr *) psin_server,
1637 sizeof(struct sockaddr_in6), 0);
1638 if (rc >= 0)
1639 connected = 1;
1640 }
1641
1642 if (!connected) {
1643
1644
1645
1646 orig_port = psin_server->sin6_port;
1647
1648 if (psin_server->sin6_port != htons(CIFS_PORT)) {
1649 psin_server->sin6_port = htons(CIFS_PORT);
1650
1651 rc = (*csocket)->ops->connect(*csocket,
1652 (struct sockaddr *) psin_server,
1653 sizeof(struct sockaddr_in6), 0);
1654 if (rc >= 0)
1655 connected = 1;
1656 }
1657 }
1658 if (!connected) {
1659 psin_server->sin6_port = htons(RFC1001_PORT);
1660 rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *)
1661 psin_server, sizeof(struct sockaddr_in6), 0);
1662 if (rc >= 0)
1663 connected = 1;
1664 }
1665
1666
1667
1668 if (!connected) {
1669 if (orig_port)
1670 psin_server->sin6_port = orig_port;
1671 cFYI(1, ("Error %d connecting to server via ipv6", rc));
1672 sock_release(*csocket);
1673 *csocket = NULL;
1674 return rc;
1675 }
1676
1677
1678
1679 (*csocket)->sk->sk_rcvtimeo = 7 * HZ;
1680
1681 return rc;
1682}
1683
1684void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
1685 struct super_block *sb, struct smb_vol *vol_info)
1686{
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696 __u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1697
1698 if (vol_info && vol_info->no_linux_ext) {
1699 tcon->fsUnixInfo.Capability = 0;
1700 tcon->unix_ext = 0;
1701 cFYI(1, ("Linux protocol extensions disabled"));
1702 return;
1703 } else if (vol_info)
1704 tcon->unix_ext = 1;
1705
1706 if (tcon->unix_ext == 0) {
1707 cFYI(1, ("Unix extensions disabled so not set on reconnect"));
1708 return;
1709 }
1710
1711 if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
1712 __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
1713
1714
1715
1716 if (vol_info == NULL) {
1717
1718
1719 if ((saved_cap & CIFS_UNIX_POSIX_ACL_CAP) == 0)
1720 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1721 if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
1722 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1723 }
1724
1725 cap &= CIFS_UNIX_CAP_MASK;
1726 if (vol_info && vol_info->no_psx_acl)
1727 cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
1728 else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
1729 cFYI(1, ("negotiated posix acl support"));
1730 if (sb)
1731 sb->s_flags |= MS_POSIXACL;
1732 }
1733
1734 if (vol_info && vol_info->posix_paths == 0)
1735 cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
1736 else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
1737 cFYI(1, ("negotiate posix pathnames"));
1738 if (sb)
1739 CIFS_SB(sb)->mnt_cifs_flags |=
1740 CIFS_MOUNT_POSIX_PATHS;
1741 }
1742
1743
1744
1745
1746 if (sb && (CIFS_SB(sb)->prepathlen > 0))
1747 CIFS_SB(sb)->prepath[0] = CIFS_DIR_SEP(CIFS_SB(sb));
1748
1749 if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {
1750 if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
1751 CIFS_SB(sb)->rsize = 127 * 1024;
1752#ifdef CONFIG_CIFS_DEBUG2
1753 cFYI(1, ("larger reads not supported by srv"));
1754#endif
1755 }
1756 }
1757
1758
1759 cFYI(1, ("Negotiate caps 0x%x", (int)cap));
1760#ifdef CONFIG_CIFS_DEBUG2
1761 if (cap & CIFS_UNIX_FCNTL_CAP)
1762 cFYI(1, ("FCNTL cap"));
1763 if (cap & CIFS_UNIX_EXTATTR_CAP)
1764 cFYI(1, ("EXTATTR cap"));
1765 if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
1766 cFYI(1, ("POSIX path cap"));
1767 if (cap & CIFS_UNIX_XATTR_CAP)
1768 cFYI(1, ("XATTR cap"));
1769 if (cap & CIFS_UNIX_POSIX_ACL_CAP)
1770 cFYI(1, ("POSIX ACL cap"));
1771 if (cap & CIFS_UNIX_LARGE_READ_CAP)
1772 cFYI(1, ("very large read cap"));
1773 if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
1774 cFYI(1, ("very large write cap"));
1775#endif
1776 if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
1777 if (vol_info == NULL) {
1778 cFYI(1, ("resetting capabilities failed"));
1779 } else
1780 cERROR(1, ("Negotiating Unix capabilities "
1781 "with the server failed. Consider "
1782 "mounting with the Unix Extensions\n"
1783 "disabled, if problems are found, "
1784 "by specifying the nounix mount "
1785 "option."));
1786
1787 }
1788 }
1789}
1790
1791int
1792cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
1793 char *mount_data, const char *devname)
1794{
1795 int rc = 0;
1796 int xid;
1797 int address_type = AF_INET;
1798 struct socket *csocket = NULL;
1799 struct sockaddr_in sin_server;
1800 struct sockaddr_in6 sin_server6;
1801 struct smb_vol volume_info;
1802 struct cifsSesInfo *pSesInfo = NULL;
1803 struct cifsSesInfo *existingCifsSes = NULL;
1804 struct cifsTconInfo *tcon = NULL;
1805 struct TCP_Server_Info *srvTcp = NULL;
1806
1807 xid = GetXid();
1808
1809
1810
1811 memset(&volume_info, 0, sizeof(struct smb_vol));
1812 if (cifs_parse_mount_options(mount_data, devname, &volume_info)) {
1813 rc = -EINVAL;
1814 goto out;
1815 }
1816
1817 if (volume_info.nullauth) {
1818 cFYI(1, ("null user"));
1819 volume_info.username = "";
1820 } else if (volume_info.username) {
1821
1822 cFYI(1, ("Username: %s", volume_info.username));
1823 } else {
1824 cifserror("No username specified");
1825
1826
1827 rc = -EINVAL;
1828 goto out;
1829 }
1830
1831 if (volume_info.UNCip && volume_info.UNC) {
1832 rc = cifs_inet_pton(AF_INET, volume_info.UNCip,
1833 &sin_server.sin_addr.s_addr);
1834
1835 if (rc <= 0) {
1836
1837 rc = cifs_inet_pton(AF_INET6, volume_info.UNCip,
1838 &sin_server6.sin6_addr.in6_u);
1839 if (rc > 0)
1840 address_type = AF_INET6;
1841 } else {
1842 address_type = AF_INET;
1843 }
1844
1845 if (rc <= 0) {
1846
1847 rc = -EINVAL;
1848 goto out;
1849 }
1850
1851 cFYI(1, ("UNC: %s ip: %s", volume_info.UNC, volume_info.UNCip));
1852
1853 rc = 0;
1854 } else if (volume_info.UNCip) {
1855
1856
1857 cERROR(1, ("Connecting to DFS root not implemented yet"));
1858 rc = -EINVAL;
1859 goto out;
1860 } else {
1861 cERROR(1,
1862 ("CIFS mount error: No UNC path (e.g. -o "
1863 "unc=//192.168.1.100/public) specified"));
1864 rc = -EINVAL;
1865 goto out;
1866 }
1867
1868
1869 if (volume_info.iocharset == NULL) {
1870 cifs_sb->local_nls = load_nls_default();
1871
1872 } else {
1873 cifs_sb->local_nls = load_nls(volume_info.iocharset);
1874 if (cifs_sb->local_nls == NULL) {
1875 cERROR(1, ("CIFS mount error: iocharset %s not found",
1876 volume_info.iocharset));
1877 rc = -ELIBACC;
1878 goto out;
1879 }
1880 }
1881
1882 if (address_type == AF_INET)
1883 existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr,
1884 NULL ,
1885 volume_info.username, &srvTcp);
1886 else if (address_type == AF_INET6) {
1887 cFYI(1, ("looking for ipv6 address"));
1888 existingCifsSes = cifs_find_tcp_session(NULL ,
1889 &sin_server6.sin6_addr,
1890 volume_info.username, &srvTcp);
1891 } else {
1892 rc = -EINVAL;
1893 goto out;
1894 }
1895
1896 if (srvTcp) {
1897 cFYI(1, ("Existing tcp session with server found"));
1898 } else {
1899 if (volume_info.port)
1900 sin_server.sin_port = htons(volume_info.port);
1901 else
1902 sin_server.sin_port = 0;
1903 if (address_type == AF_INET6) {
1904 cFYI(1, ("attempting ipv6 connect"));
1905
1906
1907 rc = ipv6_connect(&sin_server6, &csocket);
1908 } else
1909 rc = ipv4_connect(&sin_server, &csocket,
1910 volume_info.source_rfc1001_name,
1911 volume_info.target_rfc1001_name);
1912 if (rc < 0) {
1913 cERROR(1, ("Error connecting to IPv4 socket. "
1914 "Aborting operation"));
1915 if (csocket != NULL)
1916 sock_release(csocket);
1917 goto out;
1918 }
1919
1920 srvTcp = kzalloc(sizeof(struct TCP_Server_Info), GFP_KERNEL);
1921 if (!srvTcp) {
1922 rc = -ENOMEM;
1923 sock_release(csocket);
1924 goto out;
1925 } else {
1926 memcpy(&srvTcp->addr.sockAddr, &sin_server,
1927 sizeof(struct sockaddr_in));
1928 atomic_set(&srvTcp->inFlight, 0);
1929
1930 srvTcp->ssocket = csocket;
1931 srvTcp->protocolType = IPV4;
1932 srvTcp->hostname = extract_hostname(volume_info.UNC);
1933 if (IS_ERR(srvTcp->hostname)) {
1934 rc = PTR_ERR(srvTcp->hostname);
1935 sock_release(csocket);
1936 goto out;
1937 }
1938 init_waitqueue_head(&srvTcp->response_q);
1939 init_waitqueue_head(&srvTcp->request_q);
1940 INIT_LIST_HEAD(&srvTcp->pending_mid_q);
1941
1942
1943
1944 srvTcp->tcpStatus = CifsNew;
1945 init_MUTEX(&srvTcp->tcpSem);
1946 srvTcp->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, srvTcp, "cifsd");
1947 if (IS_ERR(srvTcp->tsk)) {
1948 rc = PTR_ERR(srvTcp->tsk);
1949 cERROR(1, ("error %d create cifsd thread", rc));
1950 srvTcp->tsk = NULL;
1951 sock_release(csocket);
1952 kfree(srvTcp->hostname);
1953 goto out;
1954 }
1955 wait_for_completion(&cifsd_complete);
1956 rc = 0;
1957 memcpy(srvTcp->workstation_RFC1001_name,
1958 volume_info.source_rfc1001_name, 16);
1959 memcpy(srvTcp->server_RFC1001_name,
1960 volume_info.target_rfc1001_name, 16);
1961 srvTcp->sequence_number = 0;
1962 }
1963 }
1964
1965 if (existingCifsSes) {
1966 pSesInfo = existingCifsSes;
1967 cFYI(1, ("Existing smb sess found"));
1968 } else if (!rc) {
1969 cFYI(1, ("Existing smb sess not found"));
1970 pSesInfo = sesInfoAlloc();
1971 if (pSesInfo == NULL)
1972 rc = -ENOMEM;
1973 else {
1974 pSesInfo->server = srvTcp;
1975 sprintf(pSesInfo->serverName, "%u.%u.%u.%u",
1976 NIPQUAD(sin_server.sin_addr.s_addr));
1977 }
1978
1979 if (!rc) {
1980
1981 if (volume_info.password) {
1982 pSesInfo->password = volume_info.password;
1983
1984 volume_info.password = NULL;
1985 }
1986 if (volume_info.username)
1987 strncpy(pSesInfo->userName,
1988 volume_info.username,
1989 MAX_USERNAME_SIZE);
1990 if (volume_info.domainname) {
1991 int len = strlen(volume_info.domainname);
1992 pSesInfo->domainName =
1993 kmalloc(len + 1, GFP_KERNEL);
1994 if (pSesInfo->domainName)
1995 strcpy(pSesInfo->domainName,
1996 volume_info.domainname);
1997 }
1998 pSesInfo->linux_uid = volume_info.linux_uid;
1999 pSesInfo->overrideSecFlg = volume_info.secFlg;
2000 down(&pSesInfo->sesSem);
2001
2002 rc = cifs_setup_session(xid, pSesInfo,
2003 cifs_sb->local_nls);
2004 up(&pSesInfo->sesSem);
2005 if (!rc)
2006 atomic_inc(&srvTcp->socketUseCount);
2007 }
2008 }
2009
2010
2011 if (!rc) {
2012 if (volume_info.rsize > CIFSMaxBufSize) {
2013 cERROR(1, ("rsize %d too large, using MaxBufSize",
2014 volume_info.rsize));
2015 cifs_sb->rsize = CIFSMaxBufSize;
2016 } else if ((volume_info.rsize) &&
2017 (volume_info.rsize <= CIFSMaxBufSize))
2018 cifs_sb->rsize = volume_info.rsize;
2019 else
2020 cifs_sb->rsize = CIFSMaxBufSize;
2021
2022 if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
2023 cERROR(1, ("wsize %d too large, using 4096 instead",
2024 volume_info.wsize));
2025 cifs_sb->wsize = 4096;
2026 } else if (volume_info.wsize)
2027 cifs_sb->wsize = volume_info.wsize;
2028 else
2029 cifs_sb->wsize =
2030 min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE,
2031 127*1024);
2032
2033
2034
2035
2036
2037
2038
2039 if (cifs_sb->rsize < 2048) {
2040 cifs_sb->rsize = 2048;
2041
2042 cFYI(1, ("readsize set to minimum: 2048"));
2043 }
2044
2045 cifs_sb->prepath = volume_info.prepath;
2046 if (cifs_sb->prepath) {
2047 cifs_sb->prepathlen = strlen(cifs_sb->prepath);
2048 cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb);
2049 volume_info.prepath = NULL;
2050 } else
2051 cifs_sb->prepathlen = 0;
2052 cifs_sb->mnt_uid = volume_info.linux_uid;
2053 cifs_sb->mnt_gid = volume_info.linux_gid;
2054 cifs_sb->mnt_file_mode = volume_info.file_mode;
2055 cifs_sb->mnt_dir_mode = volume_info.dir_mode;
2056 cFYI(1, ("file mode: 0x%x dir mode: 0x%x",
2057 cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode));
2058
2059 if (volume_info.noperm)
2060 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM;
2061 if (volume_info.setuids)
2062 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID;
2063 if (volume_info.server_ino)
2064 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM;
2065 if (volume_info.remap)
2066 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR;
2067 if (volume_info.no_xattr)
2068 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR;
2069 if (volume_info.sfu_emul)
2070 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL;
2071 if (volume_info.nobrl)
2072 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL;
2073 if (volume_info.cifs_acl)
2074 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
2075 if (volume_info.override_uid)
2076 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
2077 if (volume_info.override_gid)
2078 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
2079 if (volume_info.direct_io) {
2080 cFYI(1, ("mounting share using direct i/o"));
2081 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
2082 }
2083
2084 tcon =
2085 find_unc(sin_server.sin_addr.s_addr, volume_info.UNC,
2086 volume_info.username);
2087 if (tcon) {
2088 cFYI(1, ("Found match on UNC path"));
2089
2090
2091
2092
2093 tcon->retry = volume_info.retry;
2094 tcon->nocase = volume_info.nocase;
2095 } else {
2096 tcon = tconInfoAlloc();
2097 if (tcon == NULL)
2098 rc = -ENOMEM;
2099 else {
2100
2101
2102
2103
2104
2105 if ((strchr(volume_info.UNC + 3, '\\') == NULL)
2106 && (strchr(volume_info.UNC + 3, '/') ==
2107 NULL)) {
2108 rc = connect_to_dfs_path(xid, pSesInfo,
2109 "", cifs_sb->local_nls,
2110 cifs_sb->mnt_cifs_flags &
2111 CIFS_MOUNT_MAP_SPECIAL_CHR);
2112 rc = -ENODEV;
2113 goto out;
2114 } else {
2115
2116
2117
2118 rc = CIFSTCon(xid, pSesInfo,
2119 volume_info.UNC,
2120 tcon, cifs_sb->local_nls);
2121 cFYI(1, ("CIFS Tcon rc = %d", rc));
2122 }
2123 if (!rc) {
2124 atomic_inc(&pSesInfo->inUse);
2125 tcon->retry = volume_info.retry;
2126 tcon->nocase = volume_info.nocase;
2127 }
2128 }
2129 }
2130 }
2131 if (pSesInfo) {
2132 if (pSesInfo->capabilities & CAP_LARGE_FILES) {
2133 sb->s_maxbytes = (u64) 1 << 63;
2134 } else
2135 sb->s_maxbytes = (u64) 1 << 31;
2136 }
2137
2138
2139 sb->s_time_gran = 100;
2140
2141
2142 if (rc) {
2143
2144
2145 if (atomic_read(&srvTcp->socketUseCount) == 0) {
2146 spin_lock(&GlobalMid_Lock);
2147 srvTcp->tcpStatus = CifsExiting;
2148 spin_unlock(&GlobalMid_Lock);
2149 if (srvTcp->tsk) {
2150 struct task_struct *tsk;
2151
2152
2153
2154
2155 force_sig(SIGKILL, srvTcp->tsk);
2156 tsk = srvTcp->tsk;
2157 if (tsk)
2158 kthread_stop(tsk);
2159 }
2160 }
2161
2162 if (tcon)
2163 tconInfoFree(tcon);
2164 if (existingCifsSes == NULL) {
2165 if (pSesInfo) {
2166 if ((pSesInfo->server) &&
2167 (pSesInfo->status == CifsGood)) {
2168 int temp_rc;
2169 temp_rc = CIFSSMBLogoff(xid, pSesInfo);
2170
2171 if ((temp_rc == -ESHUTDOWN) &&
2172 (pSesInfo->server) &&
2173 (pSesInfo->server->tsk)) {
2174 struct task_struct *tsk;
2175 force_sig(SIGKILL,
2176 pSesInfo->server->tsk);
2177 tsk = pSesInfo->server->tsk;
2178 if (tsk)
2179 kthread_stop(tsk);
2180 }
2181 } else {
2182 cFYI(1, ("No session or bad tcon"));
2183 if ((pSesInfo->server) &&
2184 (pSesInfo->server->tsk)) {
2185 struct task_struct *tsk;
2186 force_sig(SIGKILL,
2187 pSesInfo->server->tsk);
2188 tsk = pSesInfo->server->tsk;
2189 if (tsk)
2190 kthread_stop(tsk);
2191 }
2192 }
2193 sesInfoFree(pSesInfo);
2194
2195 }
2196 }
2197 } else {
2198 atomic_inc(&tcon->useCount);
2199 cifs_sb->tcon = tcon;
2200 tcon->ses = pSesInfo;
2201
2202
2203 if (!tcon->ipc) {
2204 CIFSSMBQFSDeviceInfo(xid, tcon);
2205 CIFSSMBQFSAttributeInfo(xid, tcon);
2206 }
2207
2208
2209 if (tcon->ses->capabilities & CAP_UNIX)
2210
2211
2212 reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
2213 else
2214 tcon->unix_ext = 0;
2215
2216 if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
2217 cifs_sb->rsize = 1024 * 127;
2218#ifdef CONFIG_CIFS_DEBUG2
2219 cFYI(1, ("no very large read support, rsize now 127K"));
2220#endif
2221 }
2222 if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
2223 cifs_sb->wsize = min(cifs_sb->wsize,
2224 (tcon->ses->server->maxBuf -
2225 MAX_CIFS_HDR_SIZE));
2226 if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
2227 cifs_sb->rsize = min(cifs_sb->rsize,
2228 (tcon->ses->server->maxBuf -
2229 MAX_CIFS_HDR_SIZE));
2230 }
2231
2232
2233
2234
2235
2236out:
2237
2238 if (volume_info.password != NULL) {
2239 memset(volume_info.password, 0, strlen(volume_info.password));
2240 kfree(volume_info.password);
2241 }
2242 kfree(volume_info.UNC);
2243 kfree(volume_info.prepath);
2244 FreeXid(xid);
2245 return rc;
2246}
2247
2248static int
2249CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2250 char session_key[CIFS_SESS_KEY_SIZE],
2251 const struct nls_table *nls_codepage)
2252{
2253 struct smb_hdr *smb_buffer;
2254 struct smb_hdr *smb_buffer_response;
2255 SESSION_SETUP_ANDX *pSMB;
2256 SESSION_SETUP_ANDX *pSMBr;
2257 char *bcc_ptr;
2258 char *user;
2259 char *domain;
2260 int rc = 0;
2261 int remaining_words = 0;
2262 int bytes_returned = 0;
2263 int len;
2264 __u32 capabilities;
2265 __u16 count;
2266
2267 cFYI(1, ("In sesssetup"));
2268 if (ses == NULL)
2269 return -EINVAL;
2270 user = ses->userName;
2271 domain = ses->domainName;
2272 smb_buffer = cifs_buf_get();
2273 if (smb_buffer == NULL) {
2274 return -ENOMEM;
2275 }
2276 smb_buffer_response = smb_buffer;
2277 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2278
2279
2280 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2281 NULL , 13 );
2282
2283 smb_buffer->Mid = GetNextMid(ses->server);
2284 pSMB->req_no_secext.AndXCommand = 0xFF;
2285 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2286 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2287
2288 if (ses->server->secMode &
2289 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2290 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2291
2292 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2293 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
2294 if (ses->capabilities & CAP_UNICODE) {
2295 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2296 capabilities |= CAP_UNICODE;
2297 }
2298 if (ses->capabilities & CAP_STATUS32) {
2299 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2300 capabilities |= CAP_STATUS32;
2301 }
2302 if (ses->capabilities & CAP_DFS) {
2303 smb_buffer->Flags2 |= SMBFLG2_DFS;
2304 capabilities |= CAP_DFS;
2305 }
2306 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2307
2308 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2309 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2310
2311 pSMB->req_no_secext.CaseSensitivePasswordLength =
2312 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2313 bcc_ptr = pByteArea(smb_buffer);
2314 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2315 bcc_ptr += CIFS_SESS_KEY_SIZE;
2316 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2317 bcc_ptr += CIFS_SESS_KEY_SIZE;
2318
2319 if (ses->capabilities & CAP_UNICODE) {
2320 if ((long) bcc_ptr % 2) {
2321 *bcc_ptr = 0;
2322 bcc_ptr++;
2323 }
2324 if (user == NULL)
2325 bytes_returned = 0;
2326 else
2327 bytes_returned =
2328 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
2329 nls_codepage);
2330
2331 bcc_ptr += 2 * bytes_returned;
2332 bcc_ptr += 2;
2333 if (domain == NULL)
2334 bytes_returned =
2335 cifs_strtoUCS((__le16 *) bcc_ptr,
2336 "CIFS_LINUX_DOM", 32, nls_codepage);
2337 else
2338 bytes_returned =
2339 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2340 nls_codepage);
2341 bcc_ptr += 2 * bytes_returned;
2342 bcc_ptr += 2;
2343 bytes_returned =
2344 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2345 32, nls_codepage);
2346 bcc_ptr += 2 * bytes_returned;
2347 bytes_returned =
2348 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release,
2349 32, nls_codepage);
2350 bcc_ptr += 2 * bytes_returned;
2351 bcc_ptr += 2;
2352 bytes_returned =
2353 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2354 64, nls_codepage);
2355 bcc_ptr += 2 * bytes_returned;
2356 bcc_ptr += 2;
2357 } else {
2358 if (user != NULL) {
2359 strncpy(bcc_ptr, user, 200);
2360 bcc_ptr += strnlen(user, 200);
2361 }
2362 *bcc_ptr = 0;
2363 bcc_ptr++;
2364 if (domain == NULL) {
2365 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2366 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2367 } else {
2368 strncpy(bcc_ptr, domain, 64);
2369 bcc_ptr += strnlen(domain, 64);
2370 *bcc_ptr = 0;
2371 bcc_ptr++;
2372 }
2373 strcpy(bcc_ptr, "Linux version ");
2374 bcc_ptr += strlen("Linux version ");
2375 strcpy(bcc_ptr, utsname()->release);
2376 bcc_ptr += strlen(utsname()->release) + 1;
2377 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2378 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2379 }
2380 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2381 smb_buffer->smb_buf_length += count;
2382 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2383
2384 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2385 &bytes_returned, CIFS_LONG_OP);
2386 if (rc) {
2387
2388 } else if ((smb_buffer_response->WordCount == 3)
2389 || (smb_buffer_response->WordCount == 4)) {
2390 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2391 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2392 if (action & GUEST_LOGIN)
2393 cFYI(1, (" Guest login"));
2394 ses->Suid = smb_buffer_response->Uid;
2395
2396 cFYI(1, ("UID = %d ", ses->Suid));
2397
2398 bcc_ptr = pByteArea(smb_buffer_response);
2399 if ((pSMBr->resp.hdr.WordCount == 3)
2400 || ((pSMBr->resp.hdr.WordCount == 4)
2401 && (blob_len < pSMBr->resp.ByteCount))) {
2402 if (pSMBr->resp.hdr.WordCount == 4)
2403 bcc_ptr += blob_len;
2404
2405 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2406 if ((long) (bcc_ptr) % 2) {
2407 remaining_words =
2408 (BCC(smb_buffer_response) - 1) / 2;
2409
2410
2411 bcc_ptr++;
2412 } else {
2413 remaining_words =
2414 BCC(smb_buffer_response) / 2;
2415 }
2416 len =
2417 UniStrnlen((wchar_t *) bcc_ptr,
2418 remaining_words - 1);
2419
2420
2421
2422 if (ses->serverOS)
2423 kfree(ses->serverOS);
2424 ses->serverOS = kzalloc(2 * (len + 1),
2425 GFP_KERNEL);
2426 if (ses->serverOS == NULL)
2427 goto sesssetup_nomem;
2428 cifs_strfromUCS_le(ses->serverOS,
2429 (__le16 *)bcc_ptr,
2430 len, nls_codepage);
2431 bcc_ptr += 2 * (len + 1);
2432 remaining_words -= len + 1;
2433 ses->serverOS[2 * len] = 0;
2434 ses->serverOS[1 + (2 * len)] = 0;
2435 if (remaining_words > 0) {
2436 len = UniStrnlen((wchar_t *)bcc_ptr,
2437 remaining_words-1);
2438 kfree(ses->serverNOS);
2439 ses->serverNOS = kzalloc(2 * (len + 1),
2440 GFP_KERNEL);
2441 if (ses->serverNOS == NULL)
2442 goto sesssetup_nomem;
2443 cifs_strfromUCS_le(ses->serverNOS,
2444 (__le16 *)bcc_ptr,
2445 len, nls_codepage);
2446 bcc_ptr += 2 * (len + 1);
2447 ses->serverNOS[2 * len] = 0;
2448 ses->serverNOS[1 + (2 * len)] = 0;
2449 if (strncmp(ses->serverNOS,
2450 "NT LAN Manager 4", 16) == 0) {
2451 cFYI(1, ("NT4 server"));
2452 ses->flags |= CIFS_SES_NT4;
2453 }
2454 remaining_words -= len + 1;
2455 if (remaining_words > 0) {
2456 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2457
2458
2459 if (ses->serverDomain)
2460 kfree(ses->serverDomain);
2461 ses->serverDomain =
2462 kzalloc(2*(len+1),
2463 GFP_KERNEL);
2464 if (ses->serverDomain == NULL)
2465 goto sesssetup_nomem;
2466 cifs_strfromUCS_le(ses->serverDomain,
2467 (__le16 *)bcc_ptr,
2468 len, nls_codepage);
2469 bcc_ptr += 2 * (len + 1);
2470 ses->serverDomain[2*len] = 0;
2471 ses->serverDomain[1+(2*len)] = 0;
2472 } else {
2473
2474 if (ses->serverDomain)
2475 kfree(ses->serverDomain);
2476 ses->serverDomain =
2477 kzalloc(2, GFP_KERNEL);
2478 }
2479 } else {
2480
2481
2482
2483
2484
2485 kfree(ses->serverDomain);
2486 ses->serverDomain =
2487 kzalloc(2, GFP_KERNEL);
2488 kfree(ses->serverNOS);
2489 ses->serverNOS =
2490 kzalloc(2, GFP_KERNEL);
2491 }
2492 } else {
2493 len = strnlen(bcc_ptr, 1024);
2494 if (((long) bcc_ptr + len) - (long)
2495 pByteArea(smb_buffer_response)
2496 <= BCC(smb_buffer_response)) {
2497 kfree(ses->serverOS);
2498 ses->serverOS = kzalloc(len + 1,
2499 GFP_KERNEL);
2500 if (ses->serverOS == NULL)
2501 goto sesssetup_nomem;
2502 strncpy(ses->serverOS, bcc_ptr, len);
2503
2504 bcc_ptr += len;
2505
2506 bcc_ptr[0] = 0;
2507 bcc_ptr++;
2508
2509 len = strnlen(bcc_ptr, 1024);
2510 kfree(ses->serverNOS);
2511 ses->serverNOS = kzalloc(len + 1,
2512 GFP_KERNEL);
2513 if (ses->serverNOS == NULL)
2514 goto sesssetup_nomem;
2515 strncpy(ses->serverNOS, bcc_ptr, len);
2516 bcc_ptr += len;
2517 bcc_ptr[0] = 0;
2518 bcc_ptr++;
2519
2520 len = strnlen(bcc_ptr, 1024);
2521 if (ses->serverDomain)
2522 kfree(ses->serverDomain);
2523 ses->serverDomain = kzalloc(len + 1,
2524 GFP_KERNEL);
2525 if (ses->serverDomain == NULL)
2526 goto sesssetup_nomem;
2527 strncpy(ses->serverDomain, bcc_ptr,
2528 len);
2529 bcc_ptr += len;
2530 bcc_ptr[0] = 0;
2531 bcc_ptr++;
2532 } else
2533 cFYI(1,
2534 ("Variable field of length %d "
2535 "extends beyond end of smb ",
2536 len));
2537 }
2538 } else {
2539 cERROR(1,
2540 (" Security Blob Length extends beyond "
2541 "end of SMB"));
2542 }
2543 } else {
2544 cERROR(1,
2545 (" Invalid Word count %d: ",
2546 smb_buffer_response->WordCount));
2547 rc = -EIO;
2548 }
2549sesssetup_nomem:
2550
2551
2552 cifs_buf_release(smb_buffer);
2553
2554 return rc;
2555}
2556
2557static int
2558CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2559 struct cifsSesInfo *ses, int *pNTLMv2_flag,
2560 const struct nls_table *nls_codepage)
2561{
2562 struct smb_hdr *smb_buffer;
2563 struct smb_hdr *smb_buffer_response;
2564 SESSION_SETUP_ANDX *pSMB;
2565 SESSION_SETUP_ANDX *pSMBr;
2566 char *bcc_ptr;
2567 char *domain;
2568 int rc = 0;
2569 int remaining_words = 0;
2570 int bytes_returned = 0;
2571 int len;
2572 int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
2573 PNEGOTIATE_MESSAGE SecurityBlob;
2574 PCHALLENGE_MESSAGE SecurityBlob2;
2575 __u32 negotiate_flags, capabilities;
2576 __u16 count;
2577
2578 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
2579 if (ses == NULL)
2580 return -EINVAL;
2581 domain = ses->domainName;
2582 *pNTLMv2_flag = FALSE;
2583 smb_buffer = cifs_buf_get();
2584 if (smb_buffer == NULL) {
2585 return -ENOMEM;
2586 }
2587 smb_buffer_response = smb_buffer;
2588 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2589 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2590
2591
2592 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2593 NULL , 12 );
2594
2595 smb_buffer->Mid = GetNextMid(ses->server);
2596 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2597 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2598
2599 pSMB->req.AndXCommand = 0xFF;
2600 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2601 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2602
2603 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2604 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2605
2606 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2607 CAP_EXTENDED_SECURITY;
2608 if (ses->capabilities & CAP_UNICODE) {
2609 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2610 capabilities |= CAP_UNICODE;
2611 }
2612 if (ses->capabilities & CAP_STATUS32) {
2613 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2614 capabilities |= CAP_STATUS32;
2615 }
2616 if (ses->capabilities & CAP_DFS) {
2617 smb_buffer->Flags2 |= SMBFLG2_DFS;
2618 capabilities |= CAP_DFS;
2619 }
2620 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2621
2622 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2623 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2624 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2625 SecurityBlob->MessageType = NtLmNegotiate;
2626 negotiate_flags =
2627 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2628 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2629 NTLMSSP_NEGOTIATE_56 |
2630 NTLMSSP_NEGOTIATE_128;
2631 if (sign_CIFS_PDUs)
2632 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2633
2634
2635
2636 bcc_ptr += SecurityBlobLength;
2637
2638 SecurityBlob->WorkstationName.Buffer = 0;
2639 SecurityBlob->WorkstationName.Length = 0;
2640 SecurityBlob->WorkstationName.MaximumLength = 0;
2641
2642
2643
2644 SecurityBlob->DomainName.Buffer = 0;
2645 SecurityBlob->DomainName.Length = 0;
2646 SecurityBlob->DomainName.MaximumLength = 0;
2647 if (ses->capabilities & CAP_UNICODE) {
2648 if ((long) bcc_ptr % 2) {
2649 *bcc_ptr = 0;
2650 bcc_ptr++;
2651 }
2652
2653 bytes_returned =
2654 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2655 32, nls_codepage);
2656 bcc_ptr += 2 * bytes_returned;
2657 bytes_returned =
2658 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
2659 nls_codepage);
2660 bcc_ptr += 2 * bytes_returned;
2661 bcc_ptr += 2;
2662 bytes_returned =
2663 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2664 64, nls_codepage);
2665 bcc_ptr += 2 * bytes_returned;
2666 *(bcc_ptr + 1) = 0;
2667 *(bcc_ptr + 2) = 0;
2668 bcc_ptr += 2;
2669 *(bcc_ptr + 1) = 0;
2670 *(bcc_ptr + 2) = 0;
2671 bcc_ptr += 2;
2672 } else {
2673 strcpy(bcc_ptr, "Linux version ");
2674 bcc_ptr += strlen("Linux version ");
2675 strcpy(bcc_ptr, utsname()->release);
2676 bcc_ptr += strlen(utsname()->release) + 1;
2677 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2678 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2679 bcc_ptr++;
2680 *bcc_ptr = 0;
2681 }
2682 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2683 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2684 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2685 smb_buffer->smb_buf_length += count;
2686 pSMB->req.ByteCount = cpu_to_le16(count);
2687
2688 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2689 &bytes_returned, CIFS_LONG_OP);
2690
2691 if (smb_buffer_response->Status.CifsError ==
2692 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2693 rc = 0;
2694
2695 if (rc) {
2696
2697 } else if ((smb_buffer_response->WordCount == 3)
2698 || (smb_buffer_response->WordCount == 4)) {
2699 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2700 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2701
2702 if (action & GUEST_LOGIN)
2703 cFYI(1, (" Guest login"));
2704
2705
2706 bcc_ptr = pByteArea(smb_buffer_response);
2707
2708
2709 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2710 if (SecurityBlob2->MessageType != NtLmChallenge) {
2711 cFYI(1,
2712 ("Unexpected NTLMSSP message type received %d",
2713 SecurityBlob2->MessageType));
2714 } else if (ses) {
2715 ses->Suid = smb_buffer_response->Uid;
2716 cFYI(1, ("UID = %d", ses->Suid));
2717 if ((pSMBr->resp.hdr.WordCount == 3)
2718 || ((pSMBr->resp.hdr.WordCount == 4)
2719 && (blob_len <
2720 pSMBr->resp.ByteCount))) {
2721
2722 if (pSMBr->resp.hdr.WordCount == 4) {
2723 bcc_ptr += blob_len;
2724 cFYI(1, ("Security Blob Length %d",
2725 blob_len));
2726 }
2727
2728 cFYI(1, ("NTLMSSP Challenge rcvd"));
2729
2730 memcpy(ses->server->cryptKey,
2731 SecurityBlob2->Challenge,
2732 CIFS_CRYPTO_KEY_SIZE);
2733 if (SecurityBlob2->NegotiateFlags &
2734 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2735 *pNTLMv2_flag = TRUE;
2736
2737 if ((SecurityBlob2->NegotiateFlags &
2738 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2739 || (sign_CIFS_PDUs > 1))
2740 ses->server->secMode |=
2741 SECMODE_SIGN_REQUIRED;
2742 if ((SecurityBlob2->NegotiateFlags &
2743 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2744 ses->server->secMode |=
2745 SECMODE_SIGN_ENABLED;
2746
2747 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2748 if ((long) (bcc_ptr) % 2) {
2749 remaining_words =
2750 (BCC(smb_buffer_response)
2751 - 1) / 2;
2752
2753 bcc_ptr++;
2754 } else {
2755 remaining_words =
2756 BCC
2757 (smb_buffer_response) / 2;
2758 }
2759 len =
2760 UniStrnlen((wchar_t *) bcc_ptr,
2761 remaining_words - 1);
2762
2763
2764
2765 if (ses->serverOS)
2766 kfree(ses->serverOS);
2767 ses->serverOS =
2768 kzalloc(2 * (len + 1), GFP_KERNEL);
2769 cifs_strfromUCS_le(ses->serverOS,
2770 (__le16 *)
2771 bcc_ptr, len,
2772 nls_codepage);
2773 bcc_ptr += 2 * (len + 1);
2774 remaining_words -= len + 1;
2775 ses->serverOS[2 * len] = 0;
2776 ses->serverOS[1 + (2 * len)] = 0;
2777 if (remaining_words > 0) {
2778 len = UniStrnlen((wchar_t *)
2779 bcc_ptr,
2780 remaining_words
2781 - 1);
2782 kfree(ses->serverNOS);
2783 ses->serverNOS =
2784 kzalloc(2 * (len + 1),
2785 GFP_KERNEL);
2786 cifs_strfromUCS_le(ses->
2787 serverNOS,
2788 (__le16 *)
2789 bcc_ptr,
2790 len,
2791 nls_codepage);
2792 bcc_ptr += 2 * (len + 1);
2793 ses->serverNOS[2 * len] = 0;
2794 ses->serverNOS[1 +
2795 (2 * len)] = 0;
2796 remaining_words -= len + 1;
2797 if (remaining_words > 0) {
2798 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2799
2800
2801 kfree(ses->serverDomain);
2802 ses->serverDomain =
2803 kzalloc(2 *
2804 (len +
2805 1),
2806 GFP_KERNEL);
2807 cifs_strfromUCS_le
2808 (ses->serverDomain,
2809 (__le16 *)bcc_ptr,
2810 len, nls_codepage);
2811 bcc_ptr +=
2812 2 * (len + 1);
2813 ses->serverDomain[2*len]
2814 = 0;
2815 ses->serverDomain
2816 [1 + (2 * len)]
2817 = 0;
2818 }
2819 else {
2820 kfree(ses->serverDomain);
2821 ses->serverDomain =
2822 kzalloc(2,
2823 GFP_KERNEL);
2824 }
2825 } else {
2826 kfree(ses->serverDomain);
2827 ses->serverDomain =
2828 kzalloc(2, GFP_KERNEL);
2829 kfree(ses->serverNOS);
2830 ses->serverNOS =
2831 kzalloc(2, GFP_KERNEL);
2832 }
2833 } else {
2834 len = strnlen(bcc_ptr, 1024);
2835 if (((long) bcc_ptr + len) - (long)
2836 pByteArea(smb_buffer_response)
2837 <= BCC(smb_buffer_response)) {
2838 if (ses->serverOS)
2839 kfree(ses->serverOS);
2840 ses->serverOS =
2841 kzalloc(len + 1,
2842 GFP_KERNEL);
2843 strncpy(ses->serverOS,
2844 bcc_ptr, len);
2845
2846 bcc_ptr += len;
2847 bcc_ptr[0] = 0;
2848 bcc_ptr++;
2849
2850 len = strnlen(bcc_ptr, 1024);
2851 kfree(ses->serverNOS);
2852 ses->serverNOS =
2853 kzalloc(len + 1,
2854 GFP_KERNEL);
2855 strncpy(ses->serverNOS, bcc_ptr, len);
2856 bcc_ptr += len;
2857 bcc_ptr[0] = 0;
2858 bcc_ptr++;
2859
2860 len = strnlen(bcc_ptr, 1024);
2861 kfree(ses->serverDomain);
2862 ses->serverDomain =
2863 kzalloc(len + 1,
2864 GFP_KERNEL);
2865 strncpy(ses->serverDomain,
2866 bcc_ptr, len);
2867 bcc_ptr += len;
2868 bcc_ptr[0] = 0;
2869 bcc_ptr++;
2870 } else
2871 cFYI(1,
2872 ("field of length %d "
2873 "extends beyond end of smb",
2874 len));
2875 }
2876 } else {
2877 cERROR(1, ("Security Blob Length extends beyond"
2878 " end of SMB"));
2879 }
2880 } else {
2881 cERROR(1, ("No session structure passed in."));
2882 }
2883 } else {
2884 cERROR(1,
2885 (" Invalid Word count %d:",
2886 smb_buffer_response->WordCount));
2887 rc = -EIO;
2888 }
2889
2890 cifs_buf_release(smb_buffer);
2891
2892 return rc;
2893}
2894static int
2895CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2896 char *ntlm_session_key, int ntlmv2_flag,
2897 const struct nls_table *nls_codepage)
2898{
2899 struct smb_hdr *smb_buffer;
2900 struct smb_hdr *smb_buffer_response;
2901 SESSION_SETUP_ANDX *pSMB;
2902 SESSION_SETUP_ANDX *pSMBr;
2903 char *bcc_ptr;
2904 char *user;
2905 char *domain;
2906 int rc = 0;
2907 int remaining_words = 0;
2908 int bytes_returned = 0;
2909 int len;
2910 int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
2911 PAUTHENTICATE_MESSAGE SecurityBlob;
2912 __u32 negotiate_flags, capabilities;
2913 __u16 count;
2914
2915 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2916 if (ses == NULL)
2917 return -EINVAL;
2918 user = ses->userName;
2919 domain = ses->domainName;
2920 smb_buffer = cifs_buf_get();
2921 if (smb_buffer == NULL) {
2922 return -ENOMEM;
2923 }
2924 smb_buffer_response = smb_buffer;
2925 pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
2926 pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
2927
2928
2929 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2930 NULL , 12 );
2931
2932 smb_buffer->Mid = GetNextMid(ses->server);
2933 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2934 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2935 pSMB->req.AndXCommand = 0xFF;
2936 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2937 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2938
2939 pSMB->req.hdr.Uid = ses->Suid;
2940
2941 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2942 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2943
2944 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2945 CAP_EXTENDED_SECURITY;
2946 if (ses->capabilities & CAP_UNICODE) {
2947 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2948 capabilities |= CAP_UNICODE;
2949 }
2950 if (ses->capabilities & CAP_STATUS32) {
2951 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2952 capabilities |= CAP_STATUS32;
2953 }
2954 if (ses->capabilities & CAP_DFS) {
2955 smb_buffer->Flags2 |= SMBFLG2_DFS;
2956 capabilities |= CAP_DFS;
2957 }
2958 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2959
2960 bcc_ptr = (char *)&pSMB->req.SecurityBlob;
2961 SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
2962 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2963 SecurityBlob->MessageType = NtLmAuthenticate;
2964 bcc_ptr += SecurityBlobLength;
2965 negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
2966 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
2967 0x80000000 | NTLMSSP_NEGOTIATE_128;
2968 if (sign_CIFS_PDUs)
2969 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2970 if (ntlmv2_flag)
2971 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
2972
2973
2974
2975 SecurityBlob->WorkstationName.Buffer = 0;
2976 SecurityBlob->WorkstationName.Length = 0;
2977 SecurityBlob->WorkstationName.MaximumLength = 0;
2978 SecurityBlob->SessionKey.Length = 0;
2979 SecurityBlob->SessionKey.MaximumLength = 0;
2980 SecurityBlob->SessionKey.Buffer = 0;
2981
2982 SecurityBlob->LmChallengeResponse.Length = 0;
2983 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
2984 SecurityBlob->LmChallengeResponse.Buffer = 0;
2985
2986 SecurityBlob->NtChallengeResponse.Length =
2987 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2988 SecurityBlob->NtChallengeResponse.MaximumLength =
2989 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2990 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
2991 SecurityBlob->NtChallengeResponse.Buffer =
2992 cpu_to_le32(SecurityBlobLength);
2993 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
2994 bcc_ptr += CIFS_SESS_KEY_SIZE;
2995
2996 if (ses->capabilities & CAP_UNICODE) {
2997 if (domain == NULL) {
2998 SecurityBlob->DomainName.Buffer = 0;
2999 SecurityBlob->DomainName.Length = 0;
3000 SecurityBlob->DomainName.MaximumLength = 0;
3001 } else {
3002 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
3003 nls_codepage);
3004 ln *= 2;
3005 SecurityBlob->DomainName.MaximumLength =
3006 cpu_to_le16(ln);
3007 SecurityBlob->DomainName.Buffer =
3008 cpu_to_le32(SecurityBlobLength);
3009 bcc_ptr += ln;
3010 SecurityBlobLength += ln;
3011 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3012 }
3013 if (user == NULL) {
3014 SecurityBlob->UserName.Buffer = 0;
3015 SecurityBlob->UserName.Length = 0;
3016 SecurityBlob->UserName.MaximumLength = 0;
3017 } else {
3018 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
3019 nls_codepage);
3020 ln *= 2;
3021 SecurityBlob->UserName.MaximumLength =
3022 cpu_to_le16(ln);
3023 SecurityBlob->UserName.Buffer =
3024 cpu_to_le32(SecurityBlobLength);
3025 bcc_ptr += ln;
3026 SecurityBlobLength += ln;
3027 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3028 }
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042 if ((long) bcc_ptr % 2) {
3043 *bcc_ptr = 0;
3044 bcc_ptr++;
3045 }
3046 bytes_returned =
3047 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
3048 32, nls_codepage);
3049 bcc_ptr += 2 * bytes_returned;
3050 bytes_returned =
3051 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
3052 nls_codepage);
3053 bcc_ptr += 2 * bytes_returned;
3054 bcc_ptr += 2;
3055 bytes_returned =
3056 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
3057 64, nls_codepage);
3058 bcc_ptr += 2 * bytes_returned;
3059 *(bcc_ptr + 1) = 0;
3060 *(bcc_ptr + 2) = 0;
3061 bcc_ptr += 2;
3062 *(bcc_ptr + 1) = 0;
3063 *(bcc_ptr + 2) = 0;
3064 bcc_ptr += 2;
3065 } else {
3066 if (domain == NULL) {
3067 SecurityBlob->DomainName.Buffer = 0;
3068 SecurityBlob->DomainName.Length = 0;
3069 SecurityBlob->DomainName.MaximumLength = 0;
3070 } else {
3071 __u16 ln;
3072 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3073 strncpy(bcc_ptr, domain, 63);
3074 ln = strnlen(domain, 64);
3075 SecurityBlob->DomainName.MaximumLength =
3076 cpu_to_le16(ln);
3077 SecurityBlob->DomainName.Buffer =
3078 cpu_to_le32(SecurityBlobLength);
3079 bcc_ptr += ln;
3080 SecurityBlobLength += ln;
3081 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3082 }
3083 if (user == NULL) {
3084 SecurityBlob->UserName.Buffer = 0;
3085 SecurityBlob->UserName.Length = 0;
3086 SecurityBlob->UserName.MaximumLength = 0;
3087 } else {
3088 __u16 ln;
3089 strncpy(bcc_ptr, user, 63);
3090 ln = strnlen(user, 64);
3091 SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
3092 SecurityBlob->UserName.Buffer =
3093 cpu_to_le32(SecurityBlobLength);
3094 bcc_ptr += ln;
3095 SecurityBlobLength += ln;
3096 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3097 }
3098
3099
3100 strcpy(bcc_ptr, "Linux version ");
3101 bcc_ptr += strlen("Linux version ");
3102 strcpy(bcc_ptr, utsname()->release);
3103 bcc_ptr += strlen(utsname()->release) + 1;
3104 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3105 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3106 bcc_ptr++;
3107 *bcc_ptr = 0;
3108 }
3109 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3110 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3111 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3112 smb_buffer->smb_buf_length += count;
3113 pSMB->req.ByteCount = cpu_to_le16(count);
3114
3115 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3116 &bytes_returned, CIFS_LONG_OP);
3117 if (rc) {
3118
3119 } else if ((smb_buffer_response->WordCount == 3) ||
3120 (smb_buffer_response->WordCount == 4)) {
3121 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3122 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3123 if (action & GUEST_LOGIN)
3124 cFYI(1, (" Guest login"));
3125
3126
3127
3128
3129
3130 if (ses) {
3131 cFYI(1,
3132 ("Check challenge UID %d vs auth response UID %d",
3133 ses->Suid, smb_buffer_response->Uid));
3134
3135 ses->Suid = smb_buffer_response->Uid;
3136 bcc_ptr = pByteArea(smb_buffer_response);
3137
3138 if ((pSMBr->resp.hdr.WordCount == 3)
3139 || ((pSMBr->resp.hdr.WordCount == 4)
3140 && (blob_len <
3141 pSMBr->resp.ByteCount))) {
3142 if (pSMBr->resp.hdr.WordCount == 4) {
3143 bcc_ptr +=
3144 blob_len;
3145 cFYI(1,
3146 ("Security Blob Length %d ",
3147 blob_len));
3148 }
3149
3150 cFYI(1,
3151 ("NTLMSSP response to Authenticate "));
3152
3153 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3154 if ((long) (bcc_ptr) % 2) {
3155 remaining_words =
3156 (BCC(smb_buffer_response)
3157 - 1) / 2;
3158 bcc_ptr++;
3159 } else {
3160 remaining_words = BCC(smb_buffer_response) / 2;
3161 }
3162 len = UniStrnlen((wchar_t *) bcc_ptr,
3163 remaining_words - 1);
3164
3165
3166
3167 if (ses->serverOS)
3168 kfree(ses->serverOS);
3169 ses->serverOS =
3170 kzalloc(2 * (len + 1), GFP_KERNEL);
3171 cifs_strfromUCS_le(ses->serverOS,
3172 (__le16 *)
3173 bcc_ptr, len,
3174 nls_codepage);
3175 bcc_ptr += 2 * (len + 1);
3176 remaining_words -= len + 1;
3177 ses->serverOS[2 * len] = 0;
3178 ses->serverOS[1 + (2 * len)] = 0;
3179 if (remaining_words > 0) {
3180 len = UniStrnlen((wchar_t *)
3181 bcc_ptr,
3182 remaining_words
3183 - 1);
3184 kfree(ses->serverNOS);
3185 ses->serverNOS =
3186 kzalloc(2 * (len + 1),
3187 GFP_KERNEL);
3188 cifs_strfromUCS_le(ses->
3189 serverNOS,
3190 (__le16 *)
3191 bcc_ptr,
3192 len,
3193 nls_codepage);
3194 bcc_ptr += 2 * (len + 1);
3195 ses->serverNOS[2 * len] = 0;
3196 ses->serverNOS[1+(2*len)] = 0;
3197 remaining_words -= len + 1;
3198 if (remaining_words > 0) {
3199 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3200
3201 if (ses->serverDomain)
3202 kfree(ses->serverDomain);
3203 ses->serverDomain =
3204 kzalloc(2 *
3205 (len +
3206 1),
3207 GFP_KERNEL);
3208 cifs_strfromUCS_le
3209 (ses->
3210 serverDomain,
3211 (__le16 *)
3212 bcc_ptr, len,
3213 nls_codepage);
3214 bcc_ptr +=
3215 2 * (len + 1);
3216 ses->
3217 serverDomain[2
3218 * len]
3219 = 0;
3220 ses->
3221 serverDomain[1
3222 +
3223 (2
3224 *
3225 len)]
3226 = 0;
3227 }
3228 else {
3229 if (ses->serverDomain)
3230 kfree(ses->serverDomain);
3231 ses->serverDomain = kzalloc(2,GFP_KERNEL);
3232 }
3233 } else {
3234 if (ses->serverDomain)
3235 kfree(ses->serverDomain);
3236 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3237 kfree(ses->serverNOS);
3238 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3239 }
3240 } else {
3241 len = strnlen(bcc_ptr, 1024);
3242 if (((long) bcc_ptr + len) -
3243 (long) pByteArea(smb_buffer_response)
3244 <= BCC(smb_buffer_response)) {
3245 if (ses->serverOS)
3246 kfree(ses->serverOS);
3247 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
3248 strncpy(ses->serverOS,bcc_ptr, len);
3249
3250 bcc_ptr += len;
3251 bcc_ptr[0] = 0;
3252 bcc_ptr++;
3253
3254 len = strnlen(bcc_ptr, 1024);
3255 kfree(ses->serverNOS);
3256 ses->serverNOS = kzalloc(len+1,
3257 GFP_KERNEL);
3258 strncpy(ses->serverNOS,
3259 bcc_ptr, len);
3260 bcc_ptr += len;
3261 bcc_ptr[0] = 0;
3262 bcc_ptr++;
3263
3264 len = strnlen(bcc_ptr, 1024);
3265 if (ses->serverDomain)
3266 kfree(ses->serverDomain);
3267 ses->serverDomain =
3268 kzalloc(len+1,
3269 GFP_KERNEL);
3270 strncpy(ses->serverDomain,
3271 bcc_ptr, len);
3272 bcc_ptr += len;
3273 bcc_ptr[0] = 0;
3274 bcc_ptr++;
3275 } else
3276 cFYI(1, ("field of length %d "
3277 "extends beyond end of smb ",
3278 len));
3279 }
3280 } else {
3281 cERROR(1, ("Security Blob extends beyond end "
3282 "of SMB"));
3283 }
3284 } else {
3285 cERROR(1, ("No session structure passed in."));
3286 }
3287 } else {
3288 cERROR(1, ("Invalid Word count %d: ",
3289 smb_buffer_response->WordCount));
3290 rc = -EIO;
3291 }
3292
3293 cifs_buf_release(smb_buffer);
3294
3295 return rc;
3296}
3297
3298int
3299CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3300 const char *tree, struct cifsTconInfo *tcon,
3301 const struct nls_table *nls_codepage)
3302{
3303 struct smb_hdr *smb_buffer;
3304 struct smb_hdr *smb_buffer_response;
3305 TCONX_REQ *pSMB;
3306 TCONX_RSP *pSMBr;
3307 unsigned char *bcc_ptr;
3308 int rc = 0;
3309 int length;
3310 __u16 count;
3311
3312 if (ses == NULL)
3313 return -EIO;
3314
3315 smb_buffer = cifs_buf_get();
3316 if (smb_buffer == NULL) {
3317 return -ENOMEM;
3318 }
3319 smb_buffer_response = smb_buffer;
3320
3321 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
3322 NULL , 4 );
3323
3324 smb_buffer->Mid = GetNextMid(ses->server);
3325 smb_buffer->Uid = ses->Suid;
3326 pSMB = (TCONX_REQ *) smb_buffer;
3327 pSMBr = (TCONX_RSP *) smb_buffer_response;
3328
3329 pSMB->AndXCommand = 0xFF;
3330 pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
3331 bcc_ptr = &pSMB->Password[0];
3332 if ((ses->server->secMode) & SECMODE_USER) {
3333 pSMB->PasswordLength = cpu_to_le16(1);
3334 *bcc_ptr = 0;
3335 bcc_ptr++;
3336
3337 } else {
3338 pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
3339
3340
3341
3342
3343
3344
3345#ifdef CONFIG_CIFS_WEAK_PW_HASH
3346 if ((extended_security & CIFSSEC_MAY_LANMAN) &&
3347 (ses->server->secType == LANMAN))
3348 calc_lanman_hash(ses, bcc_ptr);
3349 else
3350#endif
3351 SMBNTencrypt(ses->password,
3352 ses->server->cryptKey,
3353 bcc_ptr);
3354
3355 bcc_ptr += CIFS_SESS_KEY_SIZE;
3356 if (ses->capabilities & CAP_UNICODE) {
3357
3358 *bcc_ptr = 0;
3359 bcc_ptr++;
3360 }
3361 }
3362
3363 if (ses->server->secMode &
3364 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3365 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3366
3367 if (ses->capabilities & CAP_STATUS32) {
3368 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3369 }
3370 if (ses->capabilities & CAP_DFS) {
3371 smb_buffer->Flags2 |= SMBFLG2_DFS;
3372 }
3373 if (ses->capabilities & CAP_UNICODE) {
3374 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3375 length =
3376 cifs_strtoUCS((__le16 *) bcc_ptr, tree,
3377 6 *
3378 ( + 256 ), nls_codepage);
3379 bcc_ptr += 2 * length;
3380 bcc_ptr += 2;
3381 } else {
3382 strcpy(bcc_ptr, tree);
3383 bcc_ptr += strlen(tree) + 1;
3384 }
3385 strcpy(bcc_ptr, "?????");
3386 bcc_ptr += strlen("?????");
3387 bcc_ptr += 1;
3388 count = bcc_ptr - &pSMB->Password[0];
3389 pSMB->hdr.smb_buf_length += count;
3390 pSMB->ByteCount = cpu_to_le16(count);
3391
3392 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
3393 CIFS_STD_OP);
3394
3395
3396
3397 if ((rc == 0) && (tcon != NULL)) {
3398 tcon->tidStatus = CifsGood;
3399 tcon->tid = smb_buffer_response->Tid;
3400 bcc_ptr = pByteArea(smb_buffer_response);
3401 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
3402
3403 if (length == 3) {
3404 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
3405 (bcc_ptr[2] == 'C')) {
3406 cFYI(1, ("IPC connection"));
3407 tcon->ipc = 1;
3408 }
3409 } else if (length == 2) {
3410 if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) {
3411
3412 cFYI(1, ("disk share connection"));
3413 }
3414 }
3415 bcc_ptr += length + 1;
3416 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3417 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3418 length = UniStrnlen((wchar_t *) bcc_ptr, 512);
3419 if ((bcc_ptr + (2 * length)) -
3420 pByteArea(smb_buffer_response) <=
3421 BCC(smb_buffer_response)) {
3422 kfree(tcon->nativeFileSystem);
3423 tcon->nativeFileSystem =
3424 kzalloc(length + 2, GFP_KERNEL);
3425 if (tcon->nativeFileSystem)
3426 cifs_strfromUCS_le(
3427 tcon->nativeFileSystem,
3428 (__le16 *) bcc_ptr,
3429 length, nls_codepage);
3430 bcc_ptr += 2 * length;
3431 bcc_ptr[0] = 0;
3432 bcc_ptr[1] = 0;
3433 bcc_ptr += 2;
3434 }
3435
3436 } else {
3437 length = strnlen(bcc_ptr, 1024);
3438 if ((bcc_ptr + length) -
3439 pByteArea(smb_buffer_response) <=
3440 BCC(smb_buffer_response)) {
3441 kfree(tcon->nativeFileSystem);
3442 tcon->nativeFileSystem =
3443 kzalloc(length + 1, GFP_KERNEL);
3444 if (tcon->nativeFileSystem)
3445 strncpy(tcon->nativeFileSystem, bcc_ptr,
3446 length);
3447 }
3448
3449 }
3450 if ((smb_buffer_response->WordCount == 3) ||
3451 (smb_buffer_response->WordCount == 7))
3452
3453 tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
3454 else
3455 tcon->Flags = 0;
3456 cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
3457 } else if ((rc == 0) && tcon == NULL) {
3458
3459 ses->ipc_tid = smb_buffer_response->Tid;
3460 }
3461
3462 cifs_buf_release(smb_buffer);
3463 return rc;
3464}
3465
3466int
3467cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
3468{
3469 int rc = 0;
3470 int xid;
3471 struct cifsSesInfo *ses = NULL;
3472 struct task_struct *cifsd_task;
3473 char *tmp;
3474
3475 xid = GetXid();
3476
3477 if (cifs_sb->tcon) {
3478 ses = cifs_sb->tcon->ses;
3479 rc = CIFSSMBTDis(xid, cifs_sb->tcon);
3480 if (rc == -EBUSY) {
3481 FreeXid(xid);
3482 return 0;
3483 }
3484 tconInfoFree(cifs_sb->tcon);
3485 if ((ses) && (ses->server)) {
3486
3487 cifsd_task = ses->server->tsk;
3488 cFYI(1, ("About to do SMBLogoff "));
3489 rc = CIFSSMBLogoff(xid, ses);
3490 if (rc == -EBUSY) {
3491 FreeXid(xid);
3492 return 0;
3493 } else if (rc == -ESHUTDOWN) {
3494 cFYI(1, ("Waking up socket by sending signal"));
3495 if (cifsd_task) {
3496 force_sig(SIGKILL, cifsd_task);
3497 kthread_stop(cifsd_task);
3498 }
3499 rc = 0;
3500 }
3501
3502 } else
3503 cFYI(1, ("No session or bad tcon"));
3504 }
3505
3506 cifs_sb->tcon = NULL;
3507 tmp = cifs_sb->prepath;
3508 cifs_sb->prepathlen = 0;
3509 cifs_sb->prepath = NULL;
3510 kfree(tmp);
3511 if (ses)
3512 schedule_timeout_interruptible(msecs_to_jiffies(500));
3513 if (ses)
3514 sesInfoFree(ses);
3515
3516 FreeXid(xid);
3517 return rc;
3518}
3519
3520int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3521 struct nls_table *nls_info)
3522{
3523 int rc = 0;
3524 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3525 int ntlmv2_flag = FALSE;
3526 int first_time = 0;
3527
3528
3529 if (pSesInfo->server->maxBuf == 0) {
3530 rc = CIFSSMBNegotiate(xid, pSesInfo);
3531 if (rc == -EAGAIN) {
3532 rc = CIFSSMBNegotiate(xid, pSesInfo);
3533 if (rc == -EAGAIN)
3534 rc = -EHOSTDOWN;
3535 }
3536 if (rc == 0) {
3537 spin_lock(&GlobalMid_Lock);
3538 if (pSesInfo->server->tcpStatus != CifsExiting)
3539 pSesInfo->server->tcpStatus = CifsGood;
3540 else
3541 rc = -EHOSTDOWN;
3542 spin_unlock(&GlobalMid_Lock);
3543
3544 }
3545 first_time = 1;
3546 }
3547 if (!rc) {
3548 pSesInfo->flags = 0;
3549 pSesInfo->capabilities = pSesInfo->server->capabilities;
3550 if (linuxExtEnabled == 0)
3551 pSesInfo->capabilities &= (~CAP_UNIX);
3552
3553 cFYI(1,
3554 ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
3555 pSesInfo->server->secMode,
3556 pSesInfo->server->capabilities,
3557 pSesInfo->server->timeAdj));
3558 if (experimEnabled < 2)
3559 rc = CIFS_SessSetup(xid, pSesInfo,
3560 first_time, nls_info);
3561 else if (extended_security
3562 && (pSesInfo->capabilities
3563 & CAP_EXTENDED_SECURITY)
3564 && (pSesInfo->server->secType == NTLMSSP)) {
3565 rc = -EOPNOTSUPP;
3566 } else if (extended_security
3567 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3568 && (pSesInfo->server->secType == RawNTLMSSP)) {
3569 cFYI(1, ("NTLMSSP sesssetup"));
3570 rc = CIFSNTLMSSPNegotiateSessSetup(xid,
3571 pSesInfo,
3572 &ntlmv2_flag,
3573 nls_info);
3574 if (!rc) {
3575 if (ntlmv2_flag) {
3576 char *v2_response;
3577 cFYI(1, ("more secure NTLM ver2 hash"));
3578 if (CalcNTLMv2_partial_mac_key(pSesInfo,
3579 nls_info)) {
3580 rc = -ENOMEM;
3581 goto ss_err_exit;
3582 } else
3583 v2_response = kmalloc(16 + 64 , GFP_KERNEL);
3584 if (v2_response) {
3585 CalcNTLMv2_response(pSesInfo,
3586 v2_response);
3587
3588
3589
3590
3591 kfree(v2_response);
3592
3593 } else {
3594 rc = -ENOMEM;
3595 goto ss_err_exit;
3596 }
3597
3598 } else {
3599 SMBNTencrypt(pSesInfo->password,
3600 pSesInfo->server->cryptKey,
3601 ntlm_session_key);
3602
3603 if (first_time)
3604 cifs_calculate_mac_key(
3605 &pSesInfo->server->mac_signing_key,
3606 ntlm_session_key,
3607 pSesInfo->password);
3608 }
3609
3610
3611
3612 rc = CIFSNTLMSSPAuthSessSetup(xid,
3613 pSesInfo,
3614 ntlm_session_key,
3615 ntlmv2_flag,
3616 nls_info);
3617 }
3618 } else {
3619 SMBNTencrypt(pSesInfo->password,
3620 pSesInfo->server->cryptKey,
3621 ntlm_session_key);
3622
3623 if (first_time)
3624 cifs_calculate_mac_key(
3625 &pSesInfo->server->mac_signing_key,
3626 ntlm_session_key, pSesInfo->password);
3627
3628 rc = CIFSSessSetup(xid, pSesInfo,
3629 ntlm_session_key, nls_info);
3630 }
3631 if (rc) {
3632 cERROR(1, ("Send error in SessSetup = %d", rc));
3633 } else {
3634 cFYI(1, ("CIFS Session Established successfully"));
3635 pSesInfo->status = CifsGood;
3636 }
3637 }
3638ss_err_exit:
3639 return rc;
3640}
3641
3642