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