aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/connect.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r--fs/cifs/connect.c1357
1 files changed, 171 insertions, 1186 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 0de3b5615a22..4aa81a507b74 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * fs/cifs/connect.c 2 * fs/cifs/connect.c
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2008 4 * Copyright (C) International Business Machines Corp., 2002,2009
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 *
7 * This library is free software; you can redistribute it and/or modify 7 * This library is free software; you can redistribute it and/or modify
@@ -32,6 +32,7 @@
32#include <linux/kthread.h> 32#include <linux/kthread.h>
33#include <linux/pagevec.h> 33#include <linux/pagevec.h>
34#include <linux/freezer.h> 34#include <linux/freezer.h>
35#include <linux/namei.h>
35#include <asm/uaccess.h> 36#include <asm/uaccess.h>
36#include <asm/processor.h> 37#include <asm/processor.h>
37#include <net/ipv6.h> 38#include <net/ipv6.h>
@@ -978,6 +979,13 @@ cifs_parse_mount_options(char *options, const char *devname,
978 return 1; 979 return 1;
979 } else if (strnicmp(value, "krb5", 4) == 0) { 980 } else if (strnicmp(value, "krb5", 4) == 0) {
980 vol->secFlg |= CIFSSEC_MAY_KRB5; 981 vol->secFlg |= CIFSSEC_MAY_KRB5;
982#ifdef CONFIG_CIFS_EXPERIMENTAL
983 } else if (strnicmp(value, "ntlmsspi", 8) == 0) {
984 vol->secFlg |= CIFSSEC_MAY_NTLMSSP |
985 CIFSSEC_MUST_SIGN;
986 } else if (strnicmp(value, "ntlmssp", 7) == 0) {
987 vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
988#endif
981 } else if (strnicmp(value, "ntlmv2i", 7) == 0) { 989 } else if (strnicmp(value, "ntlmv2i", 7) == 0) {
982 vol->secFlg |= CIFSSEC_MAY_NTLMV2 | 990 vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
983 CIFSSEC_MUST_SIGN; 991 CIFSSEC_MUST_SIGN;
@@ -2214,9 +2222,58 @@ is_path_accessible(int xid, struct cifsTconInfo *tcon,
2214 return rc; 2222 return rc;
2215} 2223}
2216 2224
2225static void
2226cleanup_volume_info(struct smb_vol **pvolume_info)
2227{
2228 struct smb_vol *volume_info;
2229
2230 if (!pvolume_info && !*pvolume_info)
2231 return;
2232
2233 volume_info = *pvolume_info;
2234 kzfree(volume_info->password);
2235 kfree(volume_info->UNC);
2236 kfree(volume_info->prepath);
2237 kfree(volume_info);
2238 *pvolume_info = NULL;
2239 return;
2240}
2241
2242#ifdef CONFIG_CIFS_DFS_UPCALL
2243/* build_path_to_root returns full path to root when
2244 * we do not have an exiting connection (tcon) */
2245static char *
2246build_unc_path_to_root(const struct smb_vol *volume_info,
2247 const struct cifs_sb_info *cifs_sb)
2248{
2249 char *full_path;
2250
2251 int unc_len = strnlen(volume_info->UNC, MAX_TREE_SIZE + 1);
2252 full_path = kmalloc(unc_len + cifs_sb->prepathlen + 1, GFP_KERNEL);
2253 if (full_path == NULL)
2254 return ERR_PTR(-ENOMEM);
2255
2256 strncpy(full_path, volume_info->UNC, unc_len);
2257 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
2258 int i;
2259 for (i = 0; i < unc_len; i++) {
2260 if (full_path[i] == '\\')
2261 full_path[i] = '/';
2262 }
2263 }
2264
2265 if (cifs_sb->prepathlen)
2266 strncpy(full_path + unc_len, cifs_sb->prepath,
2267 cifs_sb->prepathlen);
2268
2269 full_path[unc_len + cifs_sb->prepathlen] = 0; /* add trailing null */
2270 return full_path;
2271}
2272#endif
2273
2217int 2274int
2218cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, 2275cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2219 char *mount_data, const char *devname) 2276 char *mount_data_global, const char *devname)
2220{ 2277{
2221 int rc = 0; 2278 int rc = 0;
2222 int xid; 2279 int xid;
@@ -2225,6 +2282,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2225 struct cifsTconInfo *tcon = NULL; 2282 struct cifsTconInfo *tcon = NULL;
2226 struct TCP_Server_Info *srvTcp = NULL; 2283 struct TCP_Server_Info *srvTcp = NULL;
2227 char *full_path; 2284 char *full_path;
2285 char *mount_data = mount_data_global;
2286#ifdef CONFIG_CIFS_DFS_UPCALL
2287 struct dfs_info3_param *referrals = NULL;
2288 unsigned int num_referrals = 0;
2289 int referral_walks_count = 0;
2290try_mount_again:
2291#endif
2292 full_path = NULL;
2228 2293
2229 xid = GetXid(); 2294 xid = GetXid();
2230 2295
@@ -2371,11 +2436,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2371 } 2436 }
2372 } 2437 }
2373 2438
2374 /* check for null share name ie connect to dfs root */
2375 if ((strchr(volume_info->UNC + 3, '\\') == NULL) 2439 if ((strchr(volume_info->UNC + 3, '\\') == NULL)
2376 && (strchr(volume_info->UNC + 3, '/') == NULL)) { 2440 && (strchr(volume_info->UNC + 3, '/') == NULL)) {
2377 /* rc = connect_to_dfs_path(...) */ 2441 cERROR(1, ("Missing share name"));
2378 cFYI(1, ("DFS root not supported"));
2379 rc = -ENODEV; 2442 rc = -ENODEV;
2380 goto mount_fail_check; 2443 goto mount_fail_check;
2381 } else { 2444 } else {
@@ -2392,7 +2455,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2392 } 2455 }
2393 } 2456 }
2394 if (rc) 2457 if (rc)
2395 goto mount_fail_check; 2458 goto remote_path_check;
2396 tcon->seal = volume_info->seal; 2459 tcon->seal = volume_info->seal;
2397 write_lock(&cifs_tcp_ses_lock); 2460 write_lock(&cifs_tcp_ses_lock);
2398 list_add(&tcon->tcon_list, &pSesInfo->tcon_list); 2461 list_add(&tcon->tcon_list, &pSesInfo->tcon_list);
@@ -2417,19 +2480,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
2417 /* BB FIXME fix time_gran to be larger for LANMAN sessions */ 2480 /* BB FIXME fix time_gran to be larger for LANMAN sessions */
2418 sb->s_time_gran = 100; 2481 sb->s_time_gran = 100;
2419 2482
2420mount_fail_check: 2483 if (rc)
2421 /* on error free sesinfo and tcon struct if needed */ 2484 goto remote_path_check;
2422 if (rc) { 2485
2423 /* If find_unc succeeded then rc == 0 so we can not end */
2424 /* up accidently freeing someone elses tcon struct */
2425 if (tcon)
2426 cifs_put_tcon(tcon);
2427 else if (pSesInfo)
2428 cifs_put_smb_ses(pSesInfo);
2429 else
2430 cifs_put_tcp_session(srvTcp);
2431 goto out;
2432 }
2433 cifs_sb->tcon = tcon; 2486 cifs_sb->tcon = tcon;
2434 2487
2435 /* do not care if following two calls succeed - informational */ 2488 /* do not care if following two calls succeed - informational */
@@ -2461,7 +2514,9 @@ mount_fail_check:
2461 cifs_sb->rsize = min(cifs_sb->rsize, 2514 cifs_sb->rsize = min(cifs_sb->rsize,
2462 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); 2515 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
2463 2516
2464 if (!rc && cifs_sb->prepathlen) { 2517remote_path_check:
2518 /* check if a whole path (including prepath) is not remote */
2519 if (!rc && cifs_sb->prepathlen && tcon) {
2465 /* build_path_to_root works only when we have a valid tcon */ 2520 /* build_path_to_root works only when we have a valid tcon */
2466 full_path = cifs_build_path_to_root(cifs_sb); 2521 full_path = cifs_build_path_to_root(cifs_sb);
2467 if (full_path == NULL) { 2522 if (full_path == NULL) {
@@ -2469,1079 +2524,91 @@ mount_fail_check:
2469 goto mount_fail_check; 2524 goto mount_fail_check;
2470 } 2525 }
2471 rc = is_path_accessible(xid, tcon, cifs_sb, full_path); 2526 rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
2472 if (rc) { 2527 if (rc != -EREMOTE) {
2473 cERROR(1, ("Path %s in not accessible: %d",
2474 full_path, rc));
2475 kfree(full_path); 2528 kfree(full_path);
2476 goto mount_fail_check; 2529 goto mount_fail_check;
2477 } 2530 }
2478 kfree(full_path); 2531 kfree(full_path);
2479 } 2532 }
2480 2533
2481 /* volume_info->password is freed above when existing session found 2534 /* get referral if needed */
2482 (in which case it is not needed anymore) but when new sesion is created 2535 if (rc == -EREMOTE) {
2483 the password ptr is put in the new session structure (in which case the 2536#ifdef CONFIG_CIFS_DFS_UPCALL
2484 password will be freed at unmount time) */ 2537 if (referral_walks_count > MAX_NESTED_LINKS) {
2485out: 2538 /*
2486 /* zero out password before freeing */ 2539 * BB: when we implement proper loop detection,
2487 if (volume_info) { 2540 * we will remove this check. But now we need it
2488 if (volume_info->password != NULL) { 2541 * to prevent an indefinite loop if 'DFS tree' is
2489 memset(volume_info->password, 0, 2542 * misconfigured (i.e. has loops).
2490 strlen(volume_info->password)); 2543 */
2491 kfree(volume_info->password); 2544 rc = -ELOOP;
2492 } 2545 goto mount_fail_check;
2493 kfree(volume_info->UNC);
2494 kfree(volume_info->prepath);
2495 kfree(volume_info);
2496 }
2497 FreeXid(xid);
2498 return rc;
2499}
2500
2501static int
2502CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2503 char session_key[CIFS_SESS_KEY_SIZE],
2504 const struct nls_table *nls_codepage)
2505{
2506 struct smb_hdr *smb_buffer;
2507 struct smb_hdr *smb_buffer_response;
2508 SESSION_SETUP_ANDX *pSMB;
2509 SESSION_SETUP_ANDX *pSMBr;
2510 char *bcc_ptr;
2511 char *user;
2512 char *domain;
2513 int rc = 0;
2514 int remaining_words = 0;
2515 int bytes_returned = 0;
2516 int len;
2517 __u32 capabilities;
2518 __u16 count;
2519
2520 cFYI(1, ("In sesssetup"));
2521 if (ses == NULL)
2522 return -EINVAL;
2523 user = ses->userName;
2524 domain = ses->domainName;
2525 smb_buffer = cifs_buf_get();
2526
2527 if (smb_buffer == NULL)
2528 return -ENOMEM;
2529
2530 smb_buffer_response = smb_buffer;
2531 pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2532
2533 /* send SMBsessionSetup here */
2534 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2535 NULL /* no tCon exists yet */ , 13 /* wct */ );
2536
2537 smb_buffer->Mid = GetNextMid(ses->server);
2538 pSMB->req_no_secext.AndXCommand = 0xFF;
2539 pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2540 pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2541
2542 if (ses->server->secMode &
2543 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2544 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2545
2546 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2547 CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
2548 if (ses->capabilities & CAP_UNICODE) {
2549 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2550 capabilities |= CAP_UNICODE;
2551 }
2552 if (ses->capabilities & CAP_STATUS32) {
2553 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2554 capabilities |= CAP_STATUS32;
2555 }
2556 if (ses->capabilities & CAP_DFS) {
2557 smb_buffer->Flags2 |= SMBFLG2_DFS;
2558 capabilities |= CAP_DFS;
2559 }
2560 pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
2561
2562 pSMB->req_no_secext.CaseInsensitivePasswordLength =
2563 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2564
2565 pSMB->req_no_secext.CaseSensitivePasswordLength =
2566 cpu_to_le16(CIFS_SESS_KEY_SIZE);
2567 bcc_ptr = pByteArea(smb_buffer);
2568 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2569 bcc_ptr += CIFS_SESS_KEY_SIZE;
2570 memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
2571 bcc_ptr += CIFS_SESS_KEY_SIZE;
2572
2573 if (ses->capabilities & CAP_UNICODE) {
2574 if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
2575 *bcc_ptr = 0;
2576 bcc_ptr++;
2577 }
2578 if (user == NULL)
2579 bytes_returned = 0; /* skip null user */
2580 else
2581 bytes_returned =
2582 cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
2583 nls_codepage);
2584 /* convert number of 16 bit words to bytes */
2585 bcc_ptr += 2 * bytes_returned;
2586 bcc_ptr += 2; /* trailing null */
2587 if (domain == NULL)
2588 bytes_returned =
2589 cifs_strtoUCS((__le16 *) bcc_ptr,
2590 "CIFS_LINUX_DOM", 32, nls_codepage);
2591 else
2592 bytes_returned =
2593 cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
2594 nls_codepage);
2595 bcc_ptr += 2 * bytes_returned;
2596 bcc_ptr += 2;
2597 bytes_returned =
2598 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2599 32, nls_codepage);
2600 bcc_ptr += 2 * bytes_returned;
2601 bytes_returned =
2602 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release,
2603 32, nls_codepage);
2604 bcc_ptr += 2 * bytes_returned;
2605 bcc_ptr += 2;
2606 bytes_returned =
2607 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2608 64, nls_codepage);
2609 bcc_ptr += 2 * bytes_returned;
2610 bcc_ptr += 2;
2611 } else {
2612 if (user != NULL) {
2613 strncpy(bcc_ptr, user, 200);
2614 bcc_ptr += strnlen(user, 200);
2615 }
2616 *bcc_ptr = 0;
2617 bcc_ptr++;
2618 if (domain == NULL) {
2619 strcpy(bcc_ptr, "CIFS_LINUX_DOM");
2620 bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
2621 } else {
2622 strncpy(bcc_ptr, domain, 64);
2623 bcc_ptr += strnlen(domain, 64);
2624 *bcc_ptr = 0;
2625 bcc_ptr++;
2626 }
2627 strcpy(bcc_ptr, "Linux version ");
2628 bcc_ptr += strlen("Linux version ");
2629 strcpy(bcc_ptr, utsname()->release);
2630 bcc_ptr += strlen(utsname()->release) + 1;
2631 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2632 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2633 }
2634 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2635 smb_buffer->smb_buf_length += count;
2636 pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
2637
2638 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2639 &bytes_returned, CIFS_LONG_OP);
2640 if (rc) {
2641/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
2642 } else if ((smb_buffer_response->WordCount == 3)
2643 || (smb_buffer_response->WordCount == 4)) {
2644 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2645 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2646 if (action & GUEST_LOGIN)
2647 cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
2648 ses->Suid = smb_buffer_response->Uid; /* UID left in wire format
2649 (little endian) */
2650 cFYI(1, ("UID = %d ", ses->Suid));
2651 /* response can have either 3 or 4 word count - Samba sends 3 */
2652 bcc_ptr = pByteArea(smb_buffer_response);
2653 if ((pSMBr->resp.hdr.WordCount == 3)
2654 || ((pSMBr->resp.hdr.WordCount == 4)
2655 && (blob_len < pSMBr->resp.ByteCount))) {
2656 if (pSMBr->resp.hdr.WordCount == 4)
2657 bcc_ptr += blob_len;
2658
2659 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2660 if ((long) (bcc_ptr) % 2) {
2661 remaining_words =
2662 (BCC(smb_buffer_response) - 1) / 2;
2663 /* Unicode strings must be word
2664 aligned */
2665 bcc_ptr++;
2666 } else {
2667 remaining_words =
2668 BCC(smb_buffer_response) / 2;
2669 }
2670 len =
2671 UniStrnlen((wchar_t *) bcc_ptr,
2672 remaining_words - 1);
2673/* We look for obvious messed up bcc or strings in response so we do not go off
2674 the end since (at least) WIN2K and Windows XP have a major bug in not null
2675 terminating last Unicode string in response */
2676 if (ses->serverOS)
2677 kfree(ses->serverOS);
2678 ses->serverOS = kzalloc(2 * (len + 1),
2679 GFP_KERNEL);
2680 if (ses->serverOS == NULL)
2681 goto sesssetup_nomem;
2682 cifs_strfromUCS_le(ses->serverOS,
2683 (__le16 *)bcc_ptr,
2684 len, nls_codepage);
2685 bcc_ptr += 2 * (len + 1);
2686 remaining_words -= len + 1;
2687 ses->serverOS[2 * len] = 0;
2688 ses->serverOS[1 + (2 * len)] = 0;
2689 if (remaining_words > 0) {
2690 len = UniStrnlen((wchar_t *)bcc_ptr,
2691 remaining_words-1);
2692 kfree(ses->serverNOS);
2693 ses->serverNOS = kzalloc(2 * (len + 1),
2694 GFP_KERNEL);
2695 if (ses->serverNOS == NULL)
2696 goto sesssetup_nomem;
2697 cifs_strfromUCS_le(ses->serverNOS,
2698 (__le16 *)bcc_ptr,
2699 len, nls_codepage);
2700 bcc_ptr += 2 * (len + 1);
2701 ses->serverNOS[2 * len] = 0;
2702 ses->serverNOS[1 + (2 * len)] = 0;
2703 if (strncmp(ses->serverNOS,
2704 "NT LAN Manager 4", 16) == 0) {
2705 cFYI(1, ("NT4 server"));
2706 ses->flags |= CIFS_SES_NT4;
2707 }
2708 remaining_words -= len + 1;
2709 if (remaining_words > 0) {
2710 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2711 /* last string is not always null terminated
2712 (for e.g. for Windows XP & 2000) */
2713 if (ses->serverDomain)
2714 kfree(ses->serverDomain);
2715 ses->serverDomain =
2716 kzalloc(2*(len+1),
2717 GFP_KERNEL);
2718 if (ses->serverDomain == NULL)
2719 goto sesssetup_nomem;
2720 cifs_strfromUCS_le(ses->serverDomain,
2721 (__le16 *)bcc_ptr,
2722 len, nls_codepage);
2723 bcc_ptr += 2 * (len + 1);
2724 ses->serverDomain[2*len] = 0;
2725 ses->serverDomain[1+(2*len)] = 0;
2726 } else { /* else no more room so create
2727 dummy domain string */
2728 if (ses->serverDomain)
2729 kfree(ses->serverDomain);
2730 ses->serverDomain =
2731 kzalloc(2, GFP_KERNEL);
2732 }
2733 } else { /* no room so create dummy domain
2734 and NOS string */
2735
2736 /* if these kcallocs fail not much we
2737 can do, but better to not fail the
2738 sesssetup itself */
2739 kfree(ses->serverDomain);
2740 ses->serverDomain =
2741 kzalloc(2, GFP_KERNEL);
2742 kfree(ses->serverNOS);
2743 ses->serverNOS =
2744 kzalloc(2, GFP_KERNEL);
2745 }
2746 } else { /* ASCII */
2747 len = strnlen(bcc_ptr, 1024);
2748 if (((long) bcc_ptr + len) - (long)
2749 pByteArea(smb_buffer_response)
2750 <= BCC(smb_buffer_response)) {
2751 kfree(ses->serverOS);
2752 ses->serverOS = kzalloc(len + 1,
2753 GFP_KERNEL);
2754 if (ses->serverOS == NULL)
2755 goto sesssetup_nomem;
2756 strncpy(ses->serverOS, bcc_ptr, len);
2757
2758 bcc_ptr += len;
2759 /* null terminate the string */
2760 bcc_ptr[0] = 0;
2761 bcc_ptr++;
2762
2763 len = strnlen(bcc_ptr, 1024);
2764 kfree(ses->serverNOS);
2765 ses->serverNOS = kzalloc(len + 1,
2766 GFP_KERNEL);
2767 if (ses->serverNOS == NULL)
2768 goto sesssetup_nomem;
2769 strncpy(ses->serverNOS, bcc_ptr, len);
2770 bcc_ptr += len;
2771 bcc_ptr[0] = 0;
2772 bcc_ptr++;
2773
2774 len = strnlen(bcc_ptr, 1024);
2775 if (ses->serverDomain)
2776 kfree(ses->serverDomain);
2777 ses->serverDomain = kzalloc(len + 1,
2778 GFP_KERNEL);
2779 if (ses->serverDomain == NULL)
2780 goto sesssetup_nomem;
2781 strncpy(ses->serverDomain, bcc_ptr,
2782 len);
2783 bcc_ptr += len;
2784 bcc_ptr[0] = 0;
2785 bcc_ptr++;
2786 } else
2787 cFYI(1,
2788 ("Variable field of length %d "
2789 "extends beyond end of smb ",
2790 len));
2791 }
2792 } else {
2793 cERROR(1, ("Security Blob Length extends beyond "
2794 "end of SMB"));
2795 } 2546 }
2796 } else { 2547 /* convert forward to back slashes in prepath here if needed */
2797 cERROR(1, ("Invalid Word count %d: ", 2548 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
2798 smb_buffer_response->WordCount)); 2549 convert_delimiter(cifs_sb->prepath,
2799 rc = -EIO; 2550 CIFS_DIR_SEP(cifs_sb));
2800 } 2551 full_path = build_unc_path_to_root(volume_info, cifs_sb);
2801sesssetup_nomem: /* do not return an error on nomem for the info strings, 2552 if (IS_ERR(full_path)) {
2802 since that could make reconnection harder, and 2553 rc = PTR_ERR(full_path);
2803 reconnection might be needed to free memory */ 2554 goto mount_fail_check;
2804 cifs_buf_release(smb_buffer);
2805
2806 return rc;
2807}
2808
2809static int
2810CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2811 struct cifsSesInfo *ses, bool *pNTLMv2_flag,
2812 const struct nls_table *nls_codepage)
2813{
2814 struct smb_hdr *smb_buffer;
2815 struct smb_hdr *smb_buffer_response;
2816 SESSION_SETUP_ANDX *pSMB;
2817 SESSION_SETUP_ANDX *pSMBr;
2818 char *bcc_ptr;
2819 char *domain;
2820 int rc = 0;
2821 int remaining_words = 0;
2822 int bytes_returned = 0;
2823 int len;
2824 int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
2825 PNEGOTIATE_MESSAGE SecurityBlob;
2826 PCHALLENGE_MESSAGE SecurityBlob2;
2827 __u32 negotiate_flags, capabilities;
2828 __u16 count;
2829
2830 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
2831 if (ses == NULL)
2832 return -EINVAL;
2833 domain = ses->domainName;
2834 *pNTLMv2_flag = false;
2835 smb_buffer = cifs_buf_get();
2836 if (smb_buffer == NULL) {
2837 return -ENOMEM;
2838 }
2839 smb_buffer_response = smb_buffer;
2840 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2841 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2842
2843 /* send SMBsessionSetup here */
2844 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2845 NULL /* no tCon exists yet */ , 12 /* wct */ );
2846
2847 smb_buffer->Mid = GetNextMid(ses->server);
2848 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2849 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2850
2851 pSMB->req.AndXCommand = 0xFF;
2852 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2853 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2854
2855 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2856 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2857
2858 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2859 CAP_EXTENDED_SECURITY;
2860 if (ses->capabilities & CAP_UNICODE) {
2861 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2862 capabilities |= CAP_UNICODE;
2863 }
2864 if (ses->capabilities & CAP_STATUS32) {
2865 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2866 capabilities |= CAP_STATUS32;
2867 }
2868 if (ses->capabilities & CAP_DFS) {
2869 smb_buffer->Flags2 |= SMBFLG2_DFS;
2870 capabilities |= CAP_DFS;
2871 }
2872 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2873
2874 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2875 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2876 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2877 SecurityBlob->MessageType = NtLmNegotiate;
2878 negotiate_flags =
2879 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2880 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2881 NTLMSSP_NEGOTIATE_56 |
2882 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2883 if (sign_CIFS_PDUs)
2884 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2885/* if (ntlmv2_support)
2886 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
2887 /* setup pointers to domain name and workstation name */
2888 bcc_ptr += SecurityBlobLength;
2889
2890 SecurityBlob->WorkstationName.Buffer = 0;
2891 SecurityBlob->WorkstationName.Length = 0;
2892 SecurityBlob->WorkstationName.MaximumLength = 0;
2893
2894 /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2895 along with username on auth request (ie the response to challenge) */
2896 SecurityBlob->DomainName.Buffer = 0;
2897 SecurityBlob->DomainName.Length = 0;
2898 SecurityBlob->DomainName.MaximumLength = 0;
2899 if (ses->capabilities & CAP_UNICODE) {
2900 if ((long) bcc_ptr % 2) {
2901 *bcc_ptr = 0;
2902 bcc_ptr++;
2903 } 2555 }
2904 2556
2905 bytes_returned = 2557 cFYI(1, ("Getting referral for: %s", full_path));
2906 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", 2558 rc = get_dfs_path(xid, pSesInfo , full_path + 1,
2907 32, nls_codepage); 2559 cifs_sb->local_nls, &num_referrals, &referrals,
2908 bcc_ptr += 2 * bytes_returned; 2560 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
2909 bytes_returned = 2561 if (!rc && num_referrals > 0) {
2910 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32, 2562 char *fake_devname = NULL;
2911 nls_codepage); 2563
2912 bcc_ptr += 2 * bytes_returned; 2564 if (mount_data != mount_data_global)
2913 bcc_ptr += 2; /* null terminate Linux version */ 2565 kfree(mount_data);
2914 bytes_returned = 2566 mount_data = cifs_compose_mount_options(
2915 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, 2567 cifs_sb->mountdata, full_path + 1,
2916 64, nls_codepage); 2568 referrals, &fake_devname);
2917 bcc_ptr += 2 * bytes_returned; 2569 kfree(fake_devname);
2918 *(bcc_ptr + 1) = 0; 2570 free_dfs_info_array(referrals, num_referrals);
2919 *(bcc_ptr + 2) = 0; 2571
2920 bcc_ptr += 2; /* null terminate network opsys string */ 2572 if (tcon)
2921 *(bcc_ptr + 1) = 0; 2573 cifs_put_tcon(tcon);
2922 *(bcc_ptr + 2) = 0; 2574 else if (pSesInfo)
2923 bcc_ptr += 2; /* null domain */ 2575 cifs_put_smb_ses(pSesInfo);
2924 } else { /* ASCII */ 2576
2925 strcpy(bcc_ptr, "Linux version "); 2577 cleanup_volume_info(&volume_info);
2926 bcc_ptr += strlen("Linux version "); 2578 FreeXid(xid);
2927 strcpy(bcc_ptr, utsname()->release); 2579 kfree(full_path);
2928 bcc_ptr += strlen(utsname()->release) + 1; 2580 referral_walks_count++;
2929 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); 2581 goto try_mount_again;
2930 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2931 bcc_ptr++; /* empty domain field */
2932 *bcc_ptr = 0;
2933 }
2934 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2935 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2936 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2937 smb_buffer->smb_buf_length += count;
2938 pSMB->req.ByteCount = cpu_to_le16(count);
2939
2940 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2941 &bytes_returned, CIFS_LONG_OP);
2942
2943 if (smb_buffer_response->Status.CifsError ==
2944 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2945 rc = 0;
2946
2947 if (rc) {
2948/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2949 } else if ((smb_buffer_response->WordCount == 3)
2950 || (smb_buffer_response->WordCount == 4)) {
2951 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2952 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2953
2954 if (action & GUEST_LOGIN)
2955 cFYI(1, ("Guest login"));
2956 /* Do we want to set anything in SesInfo struct when guest login? */
2957
2958 bcc_ptr = pByteArea(smb_buffer_response);
2959 /* response can have either 3 or 4 word count - Samba sends 3 */
2960
2961 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2962 if (SecurityBlob2->MessageType != NtLmChallenge) {
2963 cFYI(1, ("Unexpected NTLMSSP message type received %d",
2964 SecurityBlob2->MessageType));
2965 } else if (ses) {
2966 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2967 cFYI(1, ("UID = %d", ses->Suid));
2968 if ((pSMBr->resp.hdr.WordCount == 3)
2969 || ((pSMBr->resp.hdr.WordCount == 4)
2970 && (blob_len <
2971 pSMBr->resp.ByteCount))) {
2972
2973 if (pSMBr->resp.hdr.WordCount == 4) {
2974 bcc_ptr += blob_len;
2975 cFYI(1, ("Security Blob Length %d",
2976 blob_len));
2977 }
2978
2979 cFYI(1, ("NTLMSSP Challenge rcvd"));
2980
2981 memcpy(ses->server->cryptKey,
2982 SecurityBlob2->Challenge,
2983 CIFS_CRYPTO_KEY_SIZE);
2984 if (SecurityBlob2->NegotiateFlags &
2985 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2986 *pNTLMv2_flag = true;
2987
2988 if ((SecurityBlob2->NegotiateFlags &
2989 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2990 || (sign_CIFS_PDUs > 1))
2991 ses->server->secMode |=
2992 SECMODE_SIGN_REQUIRED;
2993 if ((SecurityBlob2->NegotiateFlags &
2994 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2995 ses->server->secMode |=
2996 SECMODE_SIGN_ENABLED;
2997
2998 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2999 if ((long) (bcc_ptr) % 2) {
3000 remaining_words =
3001 (BCC(smb_buffer_response)
3002 - 1) / 2;
3003 /* Must word align unicode strings */
3004 bcc_ptr++;
3005 } else {
3006 remaining_words =
3007 BCC
3008 (smb_buffer_response) / 2;
3009 }
3010 len =
3011 UniStrnlen((wchar_t *) bcc_ptr,
3012 remaining_words - 1);
3013/* We look for obvious messed up bcc or strings in response so we do not go off
3014 the end since (at least) WIN2K and Windows XP have a major bug in not null
3015 terminating last Unicode string in response */
3016 if (ses->serverOS)
3017 kfree(ses->serverOS);
3018 ses->serverOS =
3019 kzalloc(2 * (len + 1), GFP_KERNEL);
3020 cifs_strfromUCS_le(ses->serverOS,
3021 (__le16 *)
3022 bcc_ptr, len,
3023 nls_codepage);
3024 bcc_ptr += 2 * (len + 1);
3025 remaining_words -= len + 1;
3026 ses->serverOS[2 * len] = 0;
3027 ses->serverOS[1 + (2 * len)] = 0;
3028 if (remaining_words > 0) {
3029 len = UniStrnlen((wchar_t *)
3030 bcc_ptr,
3031 remaining_words
3032 - 1);
3033 kfree(ses->serverNOS);
3034 ses->serverNOS =
3035 kzalloc(2 * (len + 1),
3036 GFP_KERNEL);
3037 cifs_strfromUCS_le(ses->
3038 serverNOS,
3039 (__le16 *)
3040 bcc_ptr,
3041 len,
3042 nls_codepage);
3043 bcc_ptr += 2 * (len + 1);
3044 ses->serverNOS[2 * len] = 0;
3045 ses->serverNOS[1 +
3046 (2 * len)] = 0;
3047 remaining_words -= len + 1;
3048 if (remaining_words > 0) {
3049 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3050 /* last string not always null terminated
3051 (for e.g. for Windows XP & 2000) */
3052 kfree(ses->serverDomain);
3053 ses->serverDomain =
3054 kzalloc(2 *
3055 (len +
3056 1),
3057 GFP_KERNEL);
3058 cifs_strfromUCS_le
3059 (ses->serverDomain,
3060 (__le16 *)bcc_ptr,
3061 len, nls_codepage);
3062 bcc_ptr +=
3063 2 * (len + 1);
3064 ses->serverDomain[2*len]
3065 = 0;
3066 ses->serverDomain
3067 [1 + (2 * len)]
3068 = 0;
3069 } /* else no more room so create dummy domain string */
3070 else {
3071 kfree(ses->serverDomain);
3072 ses->serverDomain =
3073 kzalloc(2,
3074 GFP_KERNEL);
3075 }
3076 } else { /* no room so create dummy domain and NOS string */
3077 kfree(ses->serverDomain);
3078 ses->serverDomain =
3079 kzalloc(2, GFP_KERNEL);
3080 kfree(ses->serverNOS);
3081 ses->serverNOS =
3082 kzalloc(2, GFP_KERNEL);
3083 }
3084 } else { /* ASCII */
3085 len = strnlen(bcc_ptr, 1024);
3086 if (((long) bcc_ptr + len) - (long)
3087 pByteArea(smb_buffer_response)
3088 <= BCC(smb_buffer_response)) {
3089 if (ses->serverOS)
3090 kfree(ses->serverOS);
3091 ses->serverOS =
3092 kzalloc(len + 1,
3093 GFP_KERNEL);
3094 strncpy(ses->serverOS,
3095 bcc_ptr, len);
3096
3097 bcc_ptr += len;
3098 bcc_ptr[0] = 0; /* null terminate string */
3099 bcc_ptr++;
3100
3101 len = strnlen(bcc_ptr, 1024);
3102 kfree(ses->serverNOS);
3103 ses->serverNOS =
3104 kzalloc(len + 1,
3105 GFP_KERNEL);
3106 strncpy(ses->serverNOS, bcc_ptr, len);
3107 bcc_ptr += len;
3108 bcc_ptr[0] = 0;
3109 bcc_ptr++;
3110
3111 len = strnlen(bcc_ptr, 1024);
3112 kfree(ses->serverDomain);
3113 ses->serverDomain =
3114 kzalloc(len + 1,
3115 GFP_KERNEL);
3116 strncpy(ses->serverDomain,
3117 bcc_ptr, len);
3118 bcc_ptr += len;
3119 bcc_ptr[0] = 0;
3120 bcc_ptr++;
3121 } else
3122 cFYI(1,
3123 ("field of length %d "
3124 "extends beyond end of smb",
3125 len));
3126 }
3127 } else {
3128 cERROR(1, ("Security Blob Length extends beyond"
3129 " end of SMB"));
3130 }
3131 } else {
3132 cERROR(1, ("No session structure passed in."));
3133 } 2582 }
3134 } else { 2583#else /* No DFS support, return error on mount */
3135 cERROR(1, ("Invalid Word count %d:", 2584 rc = -EOPNOTSUPP;
3136 smb_buffer_response->WordCount)); 2585#endif
3137 rc = -EIO;
3138 }
3139
3140 cifs_buf_release(smb_buffer);
3141
3142 return rc;
3143}
3144static int
3145CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
3146 char *ntlm_session_key, bool ntlmv2_flag,
3147 const struct nls_table *nls_codepage)
3148{
3149 struct smb_hdr *smb_buffer;
3150 struct smb_hdr *smb_buffer_response;
3151 SESSION_SETUP_ANDX *pSMB;
3152 SESSION_SETUP_ANDX *pSMBr;
3153 char *bcc_ptr;
3154 char *user;
3155 char *domain;
3156 int rc = 0;
3157 int remaining_words = 0;
3158 int bytes_returned = 0;
3159 int len;
3160 int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
3161 PAUTHENTICATE_MESSAGE SecurityBlob;
3162 __u32 negotiate_flags, capabilities;
3163 __u16 count;
3164
3165 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
3166 if (ses == NULL)
3167 return -EINVAL;
3168 user = ses->userName;
3169 domain = ses->domainName;
3170 smb_buffer = cifs_buf_get();
3171 if (smb_buffer == NULL) {
3172 return -ENOMEM;
3173 }
3174 smb_buffer_response = smb_buffer;
3175 pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
3176 pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
3177
3178 /* send SMBsessionSetup here */
3179 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
3180 NULL /* no tCon exists yet */ , 12 /* wct */ );
3181
3182 smb_buffer->Mid = GetNextMid(ses->server);
3183 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
3184 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
3185 pSMB->req.AndXCommand = 0xFF;
3186 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
3187 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
3188
3189 pSMB->req.hdr.Uid = ses->Suid;
3190
3191 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
3192 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
3193
3194 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
3195 CAP_EXTENDED_SECURITY;
3196 if (ses->capabilities & CAP_UNICODE) {
3197 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
3198 capabilities |= CAP_UNICODE;
3199 }
3200 if (ses->capabilities & CAP_STATUS32) {
3201 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
3202 capabilities |= CAP_STATUS32;
3203 } 2586 }
3204 if (ses->capabilities & CAP_DFS) {
3205 smb_buffer->Flags2 |= SMBFLG2_DFS;
3206 capabilities |= CAP_DFS;
3207 }
3208 pSMB->req.Capabilities = cpu_to_le32(capabilities);
3209
3210 bcc_ptr = (char *)&pSMB->req.SecurityBlob;
3211 SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
3212 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
3213 SecurityBlob->MessageType = NtLmAuthenticate;
3214 bcc_ptr += SecurityBlobLength;
3215 negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
3216 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
3217 0x80000000 | NTLMSSP_NEGOTIATE_128;
3218 if (sign_CIFS_PDUs)
3219 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
3220 if (ntlmv2_flag)
3221 negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
3222
3223/* setup pointers to domain name and workstation name */
3224
3225 SecurityBlob->WorkstationName.Buffer = 0;
3226 SecurityBlob->WorkstationName.Length = 0;
3227 SecurityBlob->WorkstationName.MaximumLength = 0;
3228 SecurityBlob->SessionKey.Length = 0;
3229 SecurityBlob->SessionKey.MaximumLength = 0;
3230 SecurityBlob->SessionKey.Buffer = 0;
3231
3232 SecurityBlob->LmChallengeResponse.Length = 0;
3233 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
3234 SecurityBlob->LmChallengeResponse.Buffer = 0;
3235
3236 SecurityBlob->NtChallengeResponse.Length =
3237 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3238 SecurityBlob->NtChallengeResponse.MaximumLength =
3239 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3240 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
3241 SecurityBlob->NtChallengeResponse.Buffer =
3242 cpu_to_le32(SecurityBlobLength);
3243 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
3244 bcc_ptr += CIFS_SESS_KEY_SIZE;
3245 2587
3246 if (ses->capabilities & CAP_UNICODE) { 2588mount_fail_check:
3247 if (domain == NULL) { 2589 /* on error free sesinfo and tcon struct if needed */
3248 SecurityBlob->DomainName.Buffer = 0;
3249 SecurityBlob->DomainName.Length = 0;
3250 SecurityBlob->DomainName.MaximumLength = 0;
3251 } else {
3252 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
3253 nls_codepage);
3254 ln *= 2;
3255 SecurityBlob->DomainName.MaximumLength =
3256 cpu_to_le16(ln);
3257 SecurityBlob->DomainName.Buffer =
3258 cpu_to_le32(SecurityBlobLength);
3259 bcc_ptr += ln;
3260 SecurityBlobLength += ln;
3261 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3262 }
3263 if (user == NULL) {
3264 SecurityBlob->UserName.Buffer = 0;
3265 SecurityBlob->UserName.Length = 0;
3266 SecurityBlob->UserName.MaximumLength = 0;
3267 } else {
3268 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
3269 nls_codepage);
3270 ln *= 2;
3271 SecurityBlob->UserName.MaximumLength =
3272 cpu_to_le16(ln);
3273 SecurityBlob->UserName.Buffer =
3274 cpu_to_le32(SecurityBlobLength);
3275 bcc_ptr += ln;
3276 SecurityBlobLength += ln;
3277 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3278 }
3279
3280 /* SecurityBlob->WorkstationName.Length =
3281 cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
3282 SecurityBlob->WorkstationName.Length *= 2;
3283 SecurityBlob->WorkstationName.MaximumLength =
3284 cpu_to_le16(SecurityBlob->WorkstationName.Length);
3285 SecurityBlob->WorkstationName.Buffer =
3286 cpu_to_le32(SecurityBlobLength);
3287 bcc_ptr += SecurityBlob->WorkstationName.Length;
3288 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
3289 SecurityBlob->WorkstationName.Length =
3290 cpu_to_le16(SecurityBlob->WorkstationName.Length); */
3291
3292 if ((long) bcc_ptr % 2) {
3293 *bcc_ptr = 0;
3294 bcc_ptr++;
3295 }
3296 bytes_returned =
3297 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
3298 32, nls_codepage);
3299 bcc_ptr += 2 * bytes_returned;
3300 bytes_returned =
3301 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
3302 nls_codepage);
3303 bcc_ptr += 2 * bytes_returned;
3304 bcc_ptr += 2; /* null term version string */
3305 bytes_returned =
3306 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
3307 64, nls_codepage);
3308 bcc_ptr += 2 * bytes_returned;
3309 *(bcc_ptr + 1) = 0;
3310 *(bcc_ptr + 2) = 0;
3311 bcc_ptr += 2; /* null terminate network opsys string */
3312 *(bcc_ptr + 1) = 0;
3313 *(bcc_ptr + 2) = 0;
3314 bcc_ptr += 2; /* null domain */
3315 } else { /* ASCII */
3316 if (domain == NULL) {
3317 SecurityBlob->DomainName.Buffer = 0;
3318 SecurityBlob->DomainName.Length = 0;
3319 SecurityBlob->DomainName.MaximumLength = 0;
3320 } else {
3321 __u16 ln;
3322 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3323 strncpy(bcc_ptr, domain, 63);
3324 ln = strnlen(domain, 64);
3325 SecurityBlob->DomainName.MaximumLength =
3326 cpu_to_le16(ln);
3327 SecurityBlob->DomainName.Buffer =
3328 cpu_to_le32(SecurityBlobLength);
3329 bcc_ptr += ln;
3330 SecurityBlobLength += ln;
3331 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3332 }
3333 if (user == NULL) {
3334 SecurityBlob->UserName.Buffer = 0;
3335 SecurityBlob->UserName.Length = 0;
3336 SecurityBlob->UserName.MaximumLength = 0;
3337 } else {
3338 __u16 ln;
3339 strncpy(bcc_ptr, user, 63);
3340 ln = strnlen(user, 64);
3341 SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
3342 SecurityBlob->UserName.Buffer =
3343 cpu_to_le32(SecurityBlobLength);
3344 bcc_ptr += ln;
3345 SecurityBlobLength += ln;
3346 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3347 }
3348 /* BB fill in our workstation name if known BB */
3349
3350 strcpy(bcc_ptr, "Linux version ");
3351 bcc_ptr += strlen("Linux version ");
3352 strcpy(bcc_ptr, utsname()->release);
3353 bcc_ptr += strlen(utsname()->release) + 1;
3354 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3355 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3356 bcc_ptr++; /* null domain */
3357 *bcc_ptr = 0;
3358 }
3359 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3360 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3361 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3362 smb_buffer->smb_buf_length += count;
3363 pSMB->req.ByteCount = cpu_to_le16(count);
3364
3365 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3366 &bytes_returned, CIFS_LONG_OP);
3367 if (rc) { 2590 if (rc) {
3368/* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */ 2591 if (mount_data != mount_data_global)
3369 } else if ((smb_buffer_response->WordCount == 3) || 2592 kfree(mount_data);
3370 (smb_buffer_response->WordCount == 4)) { 2593 /* If find_unc succeeded then rc == 0 so we can not end */
3371 __u16 action = le16_to_cpu(pSMBr->resp.Action); 2594 /* up accidently freeing someone elses tcon struct */
3372 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); 2595 if (tcon)
3373 if (action & GUEST_LOGIN) 2596 cifs_put_tcon(tcon);
3374 cFYI(1, ("Guest login")); /* BB Should we set anything 2597 else if (pSesInfo)
3375 in SesInfo struct ? */ 2598 cifs_put_smb_ses(pSesInfo);
3376/* if (SecurityBlob2->MessageType != NtLm??) { 2599 else
3377 cFYI("Unexpected message type on auth response is %d")); 2600 cifs_put_tcp_session(srvTcp);
3378 } */ 2601 goto out;
3379
3380 if (ses) {
3381 cFYI(1,
3382 ("Check challenge UID %d vs auth response UID %d",
3383 ses->Suid, smb_buffer_response->Uid));
3384 /* UID left in wire format */
3385 ses->Suid = smb_buffer_response->Uid;
3386 bcc_ptr = pByteArea(smb_buffer_response);
3387 /* response can have either 3 or 4 word count - Samba sends 3 */
3388 if ((pSMBr->resp.hdr.WordCount == 3)
3389 || ((pSMBr->resp.hdr.WordCount == 4)
3390 && (blob_len <
3391 pSMBr->resp.ByteCount))) {
3392 if (pSMBr->resp.hdr.WordCount == 4) {
3393 bcc_ptr +=
3394 blob_len;
3395 cFYI(1,
3396 ("Security Blob Length %d ",
3397 blob_len));
3398 }
3399
3400 cFYI(1,
3401 ("NTLMSSP response to Authenticate "));
3402
3403 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3404 if ((long) (bcc_ptr) % 2) {
3405 remaining_words =
3406 (BCC(smb_buffer_response)
3407 - 1) / 2;
3408 bcc_ptr++; /* Unicode strings must be word aligned */
3409 } else {
3410 remaining_words = BCC(smb_buffer_response) / 2;
3411 }
3412 len = UniStrnlen((wchar_t *) bcc_ptr,
3413 remaining_words - 1);
3414/* We look for obvious messed up bcc or strings in response so we do not go off
3415 the end since (at least) WIN2K and Windows XP have a major bug in not null
3416 terminating last Unicode string in response */
3417 if (ses->serverOS)
3418 kfree(ses->serverOS);
3419 ses->serverOS =
3420 kzalloc(2 * (len + 1), GFP_KERNEL);
3421 cifs_strfromUCS_le(ses->serverOS,
3422 (__le16 *)
3423 bcc_ptr, len,
3424 nls_codepage);
3425 bcc_ptr += 2 * (len + 1);
3426 remaining_words -= len + 1;
3427 ses->serverOS[2 * len] = 0;
3428 ses->serverOS[1 + (2 * len)] = 0;
3429 if (remaining_words > 0) {
3430 len = UniStrnlen((wchar_t *)
3431 bcc_ptr,
3432 remaining_words
3433 - 1);
3434 kfree(ses->serverNOS);
3435 ses->serverNOS =
3436 kzalloc(2 * (len + 1),
3437 GFP_KERNEL);
3438 cifs_strfromUCS_le(ses->
3439 serverNOS,
3440 (__le16 *)
3441 bcc_ptr,
3442 len,
3443 nls_codepage);
3444 bcc_ptr += 2 * (len + 1);
3445 ses->serverNOS[2 * len] = 0;
3446 ses->serverNOS[1+(2*len)] = 0;
3447 remaining_words -= len + 1;
3448 if (remaining_words > 0) {
3449 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3450 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3451 if (ses->serverDomain)
3452 kfree(ses->serverDomain);
3453 ses->serverDomain =
3454 kzalloc(2 *
3455 (len +
3456 1),
3457 GFP_KERNEL);
3458 cifs_strfromUCS_le
3459 (ses->
3460 serverDomain,
3461 (__le16 *)
3462 bcc_ptr, len,
3463 nls_codepage);
3464 bcc_ptr +=
3465 2 * (len + 1);
3466 ses->
3467 serverDomain[2
3468 * len]
3469 = 0;
3470 ses->
3471 serverDomain[1
3472 +
3473 (2
3474 *
3475 len)]
3476 = 0;
3477 } /* else no more room so create dummy domain string */
3478 else {
3479 if (ses->serverDomain)
3480 kfree(ses->serverDomain);
3481 ses->serverDomain = kzalloc(2,GFP_KERNEL);
3482 }
3483 } else { /* no room so create dummy domain and NOS string */
3484 if (ses->serverDomain)
3485 kfree(ses->serverDomain);
3486 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3487 kfree(ses->serverNOS);
3488 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3489 }
3490 } else { /* ASCII */
3491 len = strnlen(bcc_ptr, 1024);
3492 if (((long) bcc_ptr + len) -
3493 (long) pByteArea(smb_buffer_response)
3494 <= BCC(smb_buffer_response)) {
3495 if (ses->serverOS)
3496 kfree(ses->serverOS);
3497 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
3498 strncpy(ses->serverOS,bcc_ptr, len);
3499
3500 bcc_ptr += len;
3501 bcc_ptr[0] = 0; /* null terminate the string */
3502 bcc_ptr++;
3503
3504 len = strnlen(bcc_ptr, 1024);
3505 kfree(ses->serverNOS);
3506 ses->serverNOS = kzalloc(len+1,
3507 GFP_KERNEL);
3508 strncpy(ses->serverNOS,
3509 bcc_ptr, len);
3510 bcc_ptr += len;
3511 bcc_ptr[0] = 0;
3512 bcc_ptr++;
3513
3514 len = strnlen(bcc_ptr, 1024);
3515 if (ses->serverDomain)
3516 kfree(ses->serverDomain);
3517 ses->serverDomain =
3518 kzalloc(len+1,
3519 GFP_KERNEL);
3520 strncpy(ses->serverDomain,
3521 bcc_ptr, len);
3522 bcc_ptr += len;
3523 bcc_ptr[0] = 0;
3524 bcc_ptr++;
3525 } else
3526 cFYI(1, ("field of length %d "
3527 "extends beyond end of smb ",
3528 len));
3529 }
3530 } else {
3531 cERROR(1, ("Security Blob extends beyond end "
3532 "of SMB"));
3533 }
3534 } else {
3535 cERROR(1, ("No session structure passed in."));
3536 }
3537 } else {
3538 cERROR(1, ("Invalid Word count %d: ",
3539 smb_buffer_response->WordCount));
3540 rc = -EIO;
3541 } 2602 }
3542 2603
3543 cifs_buf_release(smb_buffer); 2604 /* volume_info->password is freed above when existing session found
3544 2605 (in which case it is not needed anymore) but when new sesion is created
2606 the password ptr is put in the new session structure (in which case the
2607 password will be freed at unmount time) */
2608out:
2609 /* zero out password before freeing */
2610 cleanup_volume_info(&volume_info);
2611 FreeXid(xid);
3545 return rc; 2612 return rc;
3546} 2613}
3547 2614
@@ -3556,7 +2623,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3556 TCONX_RSP *pSMBr; 2623 TCONX_RSP *pSMBr;
3557 unsigned char *bcc_ptr; 2624 unsigned char *bcc_ptr;
3558 int rc = 0; 2625 int rc = 0;
3559 int length; 2626 int length, bytes_left;
3560 __u16 count; 2627 __u16 count;
3561 2628
3562 if (ses == NULL) 2629 if (ses == NULL)
@@ -3644,14 +2711,22 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3644 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, 2711 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
3645 CIFS_STD_OP); 2712 CIFS_STD_OP);
3646 2713
3647 /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
3648 /* above now done in SendReceive */ 2714 /* above now done in SendReceive */
3649 if ((rc == 0) && (tcon != NULL)) { 2715 if ((rc == 0) && (tcon != NULL)) {
2716 bool is_unicode;
2717
3650 tcon->tidStatus = CifsGood; 2718 tcon->tidStatus = CifsGood;
3651 tcon->need_reconnect = false; 2719 tcon->need_reconnect = false;
3652 tcon->tid = smb_buffer_response->Tid; 2720 tcon->tid = smb_buffer_response->Tid;
3653 bcc_ptr = pByteArea(smb_buffer_response); 2721 bcc_ptr = pByteArea(smb_buffer_response);
3654 length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); 2722 bytes_left = BCC(smb_buffer_response);
2723 length = strnlen(bcc_ptr, bytes_left - 2);
2724 if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
2725 is_unicode = true;
2726 else
2727 is_unicode = false;
2728
2729
3655 /* skip service field (NB: this field is always ASCII) */ 2730 /* skip service field (NB: this field is always ASCII) */
3656 if (length == 3) { 2731 if (length == 3) {
3657 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') && 2732 if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
@@ -3666,40 +2741,16 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3666 } 2741 }
3667 } 2742 }
3668 bcc_ptr += length + 1; 2743 bcc_ptr += length + 1;
2744 bytes_left -= (length + 1);
3669 strncpy(tcon->treeName, tree, MAX_TREE_SIZE); 2745 strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
3670 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { 2746
3671 length = UniStrnlen((wchar_t *) bcc_ptr, 512); 2747 /* mostly informational -- no need to fail on error here */
3672 if ((bcc_ptr + (2 * length)) - 2748 tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
3673 pByteArea(smb_buffer_response) <= 2749 bytes_left, is_unicode,
3674 BCC(smb_buffer_response)) { 2750 nls_codepage);
3675 kfree(tcon->nativeFileSystem); 2751
3676 tcon->nativeFileSystem = 2752 cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem));
3677 kzalloc(2*(length + 1), GFP_KERNEL); 2753
3678 if (tcon->nativeFileSystem)
3679 cifs_strfromUCS_le(
3680 tcon->nativeFileSystem,
3681 (__le16 *) bcc_ptr,
3682 length, nls_codepage);
3683 bcc_ptr += 2 * length;
3684 bcc_ptr[0] = 0; /* null terminate the string */
3685 bcc_ptr[1] = 0;
3686 bcc_ptr += 2;
3687 }
3688 /* else do not bother copying these information fields*/
3689 } else {
3690 length = strnlen(bcc_ptr, 1024);
3691 if ((bcc_ptr + length) -
3692 pByteArea(smb_buffer_response) <=
3693 BCC(smb_buffer_response)) {
3694 kfree(tcon->nativeFileSystem);
3695 tcon->nativeFileSystem =
3696 kzalloc(length + 1, GFP_KERNEL);
3697 if (tcon->nativeFileSystem)
3698 strncpy(tcon->nativeFileSystem, bcc_ptr,
3699 length);
3700 }
3701 /* else do not bother copying these information fields*/
3702 }
3703 if ((smb_buffer_response->WordCount == 3) || 2754 if ((smb_buffer_response->WordCount == 3) ||
3704 (smb_buffer_response->WordCount == 7)) 2755 (smb_buffer_response->WordCount == 7))
3705 /* field is in same location */ 2756 /* field is in same location */
@@ -3738,8 +2789,6 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3738 struct nls_table *nls_info) 2789 struct nls_table *nls_info)
3739{ 2790{
3740 int rc = 0; 2791 int rc = 0;
3741 char ntlm_session_key[CIFS_SESS_KEY_SIZE];
3742 bool ntlmv2_flag = false;
3743 int first_time = 0; 2792 int first_time = 0;
3744 struct TCP_Server_Info *server = pSesInfo->server; 2793 struct TCP_Server_Info *server = pSesInfo->server;
3745 2794
@@ -3771,83 +2820,19 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
3771 pSesInfo->capabilities = server->capabilities; 2820 pSesInfo->capabilities = server->capabilities;
3772 if (linuxExtEnabled == 0) 2821 if (linuxExtEnabled == 0)
3773 pSesInfo->capabilities &= (~CAP_UNIX); 2822 pSesInfo->capabilities &= (~CAP_UNIX);
3774 /* pSesInfo->sequence_number = 0;*/ 2823
3775 cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", 2824 cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
3776 server->secMode, server->capabilities, server->timeAdj)); 2825 server->secMode, server->capabilities, server->timeAdj));
3777 2826
3778 if (experimEnabled < 2) 2827 rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
3779 rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
3780 else if (extended_security
3781 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3782 && (server->secType == NTLMSSP)) {
3783 rc = -EOPNOTSUPP;
3784 } else if (extended_security
3785 && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
3786 && (server->secType == RawNTLMSSP)) {
3787 cFYI(1, ("NTLMSSP sesssetup"));
3788 rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag,
3789 nls_info);
3790 if (!rc) {
3791 if (ntlmv2_flag) {
3792 char *v2_response;
3793 cFYI(1, ("more secure NTLM ver2 hash"));
3794 if (CalcNTLMv2_partial_mac_key(pSesInfo,
3795 nls_info)) {
3796 rc = -ENOMEM;
3797 goto ss_err_exit;
3798 } else
3799 v2_response = kmalloc(16 + 64 /* blob*/,
3800 GFP_KERNEL);
3801 if (v2_response) {
3802 CalcNTLMv2_response(pSesInfo,
3803 v2_response);
3804 /* if (first_time)
3805 cifs_calculate_ntlmv2_mac_key */
3806 kfree(v2_response);
3807 /* BB Put dummy sig in SessSetup PDU? */
3808 } else {
3809 rc = -ENOMEM;
3810 goto ss_err_exit;
3811 }
3812
3813 } else {
3814 SMBNTencrypt(pSesInfo->password,
3815 server->cryptKey,
3816 ntlm_session_key);
3817
3818 if (first_time)
3819 cifs_calculate_mac_key(
3820 &server->mac_signing_key,
3821 ntlm_session_key,
3822 pSesInfo->password);
3823 }
3824 /* for better security the weaker lanman hash not sent
3825 in AuthSessSetup so we no longer calculate it */
3826
3827 rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo,
3828 ntlm_session_key,
3829 ntlmv2_flag,
3830 nls_info);
3831 }
3832 } else { /* old style NTLM 0.12 session setup */
3833 SMBNTencrypt(pSesInfo->password, server->cryptKey,
3834 ntlm_session_key);
3835
3836 if (first_time)
3837 cifs_calculate_mac_key(&server->mac_signing_key,
3838 ntlm_session_key,
3839 pSesInfo->password);
3840
3841 rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info);
3842 }
3843 if (rc) { 2828 if (rc) {
3844 cERROR(1, ("Send error in SessSetup = %d", rc)); 2829 cERROR(1, ("Send error in SessSetup = %d", rc));
3845 } else { 2830 } else {
3846 cFYI(1, ("CIFS Session Established successfully")); 2831 cFYI(1, ("CIFS Session Established successfully"));
3847 spin_lock(&GlobalMid_Lock); 2832 spin_lock(&GlobalMid_Lock);
3848 pSesInfo->status = CifsGood; 2833 pSesInfo->status = CifsGood;
3849 pSesInfo->need_reconnect = false; 2834 pSesInfo->need_reconnect = false;
3850 spin_unlock(&GlobalMid_Lock); 2835 spin_unlock(&GlobalMid_Lock);
3851 } 2836 }
3852 2837
3853ss_err_exit: 2838ss_err_exit: