diff options
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 1190 |
1 files changed, 47 insertions, 1143 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index bacdef1546b7..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; |
@@ -2278,6 +2286,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
2278 | #ifdef CONFIG_CIFS_DFS_UPCALL | 2286 | #ifdef CONFIG_CIFS_DFS_UPCALL |
2279 | struct dfs_info3_param *referrals = NULL; | 2287 | struct dfs_info3_param *referrals = NULL; |
2280 | unsigned int num_referrals = 0; | 2288 | unsigned int num_referrals = 0; |
2289 | int referral_walks_count = 0; | ||
2281 | try_mount_again: | 2290 | try_mount_again: |
2282 | #endif | 2291 | #endif |
2283 | full_path = NULL; | 2292 | full_path = NULL; |
@@ -2525,6 +2534,16 @@ remote_path_check: | |||
2525 | /* get referral if needed */ | 2534 | /* get referral if needed */ |
2526 | if (rc == -EREMOTE) { | 2535 | if (rc == -EREMOTE) { |
2527 | #ifdef CONFIG_CIFS_DFS_UPCALL | 2536 | #ifdef CONFIG_CIFS_DFS_UPCALL |
2537 | if (referral_walks_count > MAX_NESTED_LINKS) { | ||
2538 | /* | ||
2539 | * BB: when we implement proper loop detection, | ||
2540 | * we will remove this check. But now we need it | ||
2541 | * to prevent an indefinite loop if 'DFS tree' is | ||
2542 | * misconfigured (i.e. has loops). | ||
2543 | */ | ||
2544 | rc = -ELOOP; | ||
2545 | goto mount_fail_check; | ||
2546 | } | ||
2528 | /* convert forward to back slashes in prepath here if needed */ | 2547 | /* convert forward to back slashes in prepath here if needed */ |
2529 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0) | 2548 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0) |
2530 | convert_delimiter(cifs_sb->prepath, | 2549 | convert_delimiter(cifs_sb->prepath, |
@@ -2558,6 +2577,7 @@ remote_path_check: | |||
2558 | cleanup_volume_info(&volume_info); | 2577 | cleanup_volume_info(&volume_info); |
2559 | FreeXid(xid); | 2578 | FreeXid(xid); |
2560 | kfree(full_path); | 2579 | kfree(full_path); |
2580 | referral_walks_count++; | ||
2561 | goto try_mount_again; | 2581 | goto try_mount_again; |
2562 | } | 2582 | } |
2563 | #else /* No DFS support, return error on mount */ | 2583 | #else /* No DFS support, return error on mount */ |
@@ -2592,1041 +2612,6 @@ out: | |||
2592 | return rc; | 2612 | return rc; |
2593 | } | 2613 | } |
2594 | 2614 | ||
2595 | static int | ||
2596 | CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, | ||
2597 | char session_key[CIFS_SESS_KEY_SIZE], | ||
2598 | const struct nls_table *nls_codepage) | ||
2599 | { | ||
2600 | struct smb_hdr *smb_buffer; | ||
2601 | struct smb_hdr *smb_buffer_response; | ||
2602 | SESSION_SETUP_ANDX *pSMB; | ||
2603 | SESSION_SETUP_ANDX *pSMBr; | ||
2604 | char *bcc_ptr; | ||
2605 | char *user; | ||
2606 | char *domain; | ||
2607 | int rc = 0; | ||
2608 | int remaining_words = 0; | ||
2609 | int bytes_returned = 0; | ||
2610 | int len; | ||
2611 | __u32 capabilities; | ||
2612 | __u16 count; | ||
2613 | |||
2614 | cFYI(1, ("In sesssetup")); | ||
2615 | if (ses == NULL) | ||
2616 | return -EINVAL; | ||
2617 | user = ses->userName; | ||
2618 | domain = ses->domainName; | ||
2619 | smb_buffer = cifs_buf_get(); | ||
2620 | |||
2621 | if (smb_buffer == NULL) | ||
2622 | return -ENOMEM; | ||
2623 | |||
2624 | smb_buffer_response = smb_buffer; | ||
2625 | pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer; | ||
2626 | |||
2627 | /* send SMBsessionSetup here */ | ||
2628 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | ||
2629 | NULL /* no tCon exists yet */ , 13 /* wct */ ); | ||
2630 | |||
2631 | smb_buffer->Mid = GetNextMid(ses->server); | ||
2632 | pSMB->req_no_secext.AndXCommand = 0xFF; | ||
2633 | pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | ||
2634 | pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq); | ||
2635 | |||
2636 | if (ses->server->secMode & | ||
2637 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
2638 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | ||
2639 | |||
2640 | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | | ||
2641 | CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; | ||
2642 | if (ses->capabilities & CAP_UNICODE) { | ||
2643 | smb_buffer->Flags2 |= SMBFLG2_UNICODE; | ||
2644 | capabilities |= CAP_UNICODE; | ||
2645 | } | ||
2646 | if (ses->capabilities & CAP_STATUS32) { | ||
2647 | smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; | ||
2648 | capabilities |= CAP_STATUS32; | ||
2649 | } | ||
2650 | if (ses->capabilities & CAP_DFS) { | ||
2651 | smb_buffer->Flags2 |= SMBFLG2_DFS; | ||
2652 | capabilities |= CAP_DFS; | ||
2653 | } | ||
2654 | pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); | ||
2655 | |||
2656 | pSMB->req_no_secext.CaseInsensitivePasswordLength = | ||
2657 | cpu_to_le16(CIFS_SESS_KEY_SIZE); | ||
2658 | |||
2659 | pSMB->req_no_secext.CaseSensitivePasswordLength = | ||
2660 | cpu_to_le16(CIFS_SESS_KEY_SIZE); | ||
2661 | bcc_ptr = pByteArea(smb_buffer); | ||
2662 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE); | ||
2663 | bcc_ptr += CIFS_SESS_KEY_SIZE; | ||
2664 | memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE); | ||
2665 | bcc_ptr += CIFS_SESS_KEY_SIZE; | ||
2666 | |||
2667 | if (ses->capabilities & CAP_UNICODE) { | ||
2668 | if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */ | ||
2669 | *bcc_ptr = 0; | ||
2670 | bcc_ptr++; | ||
2671 | } | ||
2672 | if (user == NULL) | ||
2673 | bytes_returned = 0; /* skip null user */ | ||
2674 | else | ||
2675 | bytes_returned = | ||
2676 | cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, | ||
2677 | nls_codepage); | ||
2678 | /* convert number of 16 bit words to bytes */ | ||
2679 | bcc_ptr += 2 * bytes_returned; | ||
2680 | bcc_ptr += 2; /* trailing null */ | ||
2681 | if (domain == NULL) | ||
2682 | bytes_returned = | ||
2683 | cifs_strtoUCS((__le16 *) bcc_ptr, | ||
2684 | "CIFS_LINUX_DOM", 32, nls_codepage); | ||
2685 | else | ||
2686 | bytes_returned = | ||
2687 | cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, | ||
2688 | nls_codepage); | ||
2689 | bcc_ptr += 2 * bytes_returned; | ||
2690 | bcc_ptr += 2; | ||
2691 | bytes_returned = | ||
2692 | cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", | ||
2693 | 32, nls_codepage); | ||
2694 | bcc_ptr += 2 * bytes_returned; | ||
2695 | bytes_returned = | ||
2696 | cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, | ||
2697 | 32, nls_codepage); | ||
2698 | bcc_ptr += 2 * bytes_returned; | ||
2699 | bcc_ptr += 2; | ||
2700 | bytes_returned = | ||
2701 | cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, | ||
2702 | 64, nls_codepage); | ||
2703 | bcc_ptr += 2 * bytes_returned; | ||
2704 | bcc_ptr += 2; | ||
2705 | } else { | ||
2706 | if (user != NULL) { | ||
2707 | strncpy(bcc_ptr, user, 200); | ||
2708 | bcc_ptr += strnlen(user, 200); | ||
2709 | } | ||
2710 | *bcc_ptr = 0; | ||
2711 | bcc_ptr++; | ||
2712 | if (domain == NULL) { | ||
2713 | strcpy(bcc_ptr, "CIFS_LINUX_DOM"); | ||
2714 | bcc_ptr += strlen("CIFS_LINUX_DOM") + 1; | ||
2715 | } else { | ||
2716 | strncpy(bcc_ptr, domain, 64); | ||
2717 | bcc_ptr += strnlen(domain, 64); | ||
2718 | *bcc_ptr = 0; | ||
2719 | bcc_ptr++; | ||
2720 | } | ||
2721 | strcpy(bcc_ptr, "Linux version "); | ||
2722 | bcc_ptr += strlen("Linux version "); | ||
2723 | strcpy(bcc_ptr, utsname()->release); | ||
2724 | bcc_ptr += strlen(utsname()->release) + 1; | ||
2725 | strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); | ||
2726 | bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; | ||
2727 | } | ||
2728 | count = (long) bcc_ptr - (long) pByteArea(smb_buffer); | ||
2729 | smb_buffer->smb_buf_length += count; | ||
2730 | pSMB->req_no_secext.ByteCount = cpu_to_le16(count); | ||
2731 | |||
2732 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | ||
2733 | &bytes_returned, CIFS_LONG_OP); | ||
2734 | if (rc) { | ||
2735 | /* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */ | ||
2736 | } else if ((smb_buffer_response->WordCount == 3) | ||
2737 | || (smb_buffer_response->WordCount == 4)) { | ||
2738 | __u16 action = le16_to_cpu(pSMBr->resp.Action); | ||
2739 | __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); | ||
2740 | if (action & GUEST_LOGIN) | ||
2741 | cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */ | ||
2742 | ses->Suid = smb_buffer_response->Uid; /* UID left in wire format | ||
2743 | (little endian) */ | ||
2744 | cFYI(1, ("UID = %d ", ses->Suid)); | ||
2745 | /* response can have either 3 or 4 word count - Samba sends 3 */ | ||
2746 | bcc_ptr = pByteArea(smb_buffer_response); | ||
2747 | if ((pSMBr->resp.hdr.WordCount == 3) | ||
2748 | || ((pSMBr->resp.hdr.WordCount == 4) | ||
2749 | && (blob_len < pSMBr->resp.ByteCount))) { | ||
2750 | if (pSMBr->resp.hdr.WordCount == 4) | ||
2751 | bcc_ptr += blob_len; | ||
2752 | |||
2753 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { | ||
2754 | if ((long) (bcc_ptr) % 2) { | ||
2755 | remaining_words = | ||
2756 | (BCC(smb_buffer_response) - 1) / 2; | ||
2757 | /* Unicode strings must be word | ||
2758 | aligned */ | ||
2759 | bcc_ptr++; | ||
2760 | } else { | ||
2761 | remaining_words = | ||
2762 | BCC(smb_buffer_response) / 2; | ||
2763 | } | ||
2764 | len = | ||
2765 | UniStrnlen((wchar_t *) bcc_ptr, | ||
2766 | remaining_words - 1); | ||
2767 | /* We look for obvious messed up bcc or strings in response so we do not go off | ||
2768 | the end since (at least) WIN2K and Windows XP have a major bug in not null | ||
2769 | terminating last Unicode string in response */ | ||
2770 | kfree(ses->serverOS); | ||
2771 | ses->serverOS = kzalloc(2 * (len + 1), | ||
2772 | GFP_KERNEL); | ||
2773 | if (ses->serverOS == NULL) | ||
2774 | goto sesssetup_nomem; | ||
2775 | cifs_strfromUCS_le(ses->serverOS, | ||
2776 | (__le16 *)bcc_ptr, | ||
2777 | len, nls_codepage); | ||
2778 | bcc_ptr += 2 * (len + 1); | ||
2779 | remaining_words -= len + 1; | ||
2780 | ses->serverOS[2 * len] = 0; | ||
2781 | ses->serverOS[1 + (2 * len)] = 0; | ||
2782 | if (remaining_words > 0) { | ||
2783 | len = UniStrnlen((wchar_t *)bcc_ptr, | ||
2784 | remaining_words-1); | ||
2785 | kfree(ses->serverNOS); | ||
2786 | ses->serverNOS = kzalloc(2 * (len + 1), | ||
2787 | GFP_KERNEL); | ||
2788 | if (ses->serverNOS == NULL) | ||
2789 | goto sesssetup_nomem; | ||
2790 | cifs_strfromUCS_le(ses->serverNOS, | ||
2791 | (__le16 *)bcc_ptr, | ||
2792 | len, nls_codepage); | ||
2793 | bcc_ptr += 2 * (len + 1); | ||
2794 | ses->serverNOS[2 * len] = 0; | ||
2795 | ses->serverNOS[1 + (2 * len)] = 0; | ||
2796 | if (strncmp(ses->serverNOS, | ||
2797 | "NT LAN Manager 4", 16) == 0) { | ||
2798 | cFYI(1, ("NT4 server")); | ||
2799 | ses->flags |= CIFS_SES_NT4; | ||
2800 | } | ||
2801 | remaining_words -= len + 1; | ||
2802 | if (remaining_words > 0) { | ||
2803 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); | ||
2804 | /* last string is not always null terminated | ||
2805 | (for e.g. for Windows XP & 2000) */ | ||
2806 | kfree(ses->serverDomain); | ||
2807 | ses->serverDomain = | ||
2808 | kzalloc(2*(len+1), | ||
2809 | GFP_KERNEL); | ||
2810 | if (ses->serverDomain == NULL) | ||
2811 | goto sesssetup_nomem; | ||
2812 | cifs_strfromUCS_le(ses->serverDomain, | ||
2813 | (__le16 *)bcc_ptr, | ||
2814 | len, nls_codepage); | ||
2815 | bcc_ptr += 2 * (len + 1); | ||
2816 | ses->serverDomain[2*len] = 0; | ||
2817 | ses->serverDomain[1+(2*len)] = 0; | ||
2818 | } else { /* else no more room so create | ||
2819 | dummy domain string */ | ||
2820 | kfree(ses->serverDomain); | ||
2821 | ses->serverDomain = | ||
2822 | kzalloc(2, GFP_KERNEL); | ||
2823 | } | ||
2824 | } else { /* no room so create dummy domain | ||
2825 | and NOS string */ | ||
2826 | |||
2827 | /* if these kcallocs fail not much we | ||
2828 | can do, but better to not fail the | ||
2829 | sesssetup itself */ | ||
2830 | kfree(ses->serverDomain); | ||
2831 | ses->serverDomain = | ||
2832 | kzalloc(2, GFP_KERNEL); | ||
2833 | kfree(ses->serverNOS); | ||
2834 | ses->serverNOS = | ||
2835 | kzalloc(2, GFP_KERNEL); | ||
2836 | } | ||
2837 | } else { /* ASCII */ | ||
2838 | len = strnlen(bcc_ptr, 1024); | ||
2839 | if (((long) bcc_ptr + len) - (long) | ||
2840 | pByteArea(smb_buffer_response) | ||
2841 | <= BCC(smb_buffer_response)) { | ||
2842 | kfree(ses->serverOS); | ||
2843 | ses->serverOS = kzalloc(len + 1, | ||
2844 | GFP_KERNEL); | ||
2845 | if (ses->serverOS == NULL) | ||
2846 | goto sesssetup_nomem; | ||
2847 | strncpy(ses->serverOS, bcc_ptr, len); | ||
2848 | |||
2849 | bcc_ptr += len; | ||
2850 | /* null terminate the string */ | ||
2851 | bcc_ptr[0] = 0; | ||
2852 | bcc_ptr++; | ||
2853 | |||
2854 | len = strnlen(bcc_ptr, 1024); | ||
2855 | kfree(ses->serverNOS); | ||
2856 | ses->serverNOS = kzalloc(len + 1, | ||
2857 | GFP_KERNEL); | ||
2858 | if (ses->serverNOS == NULL) | ||
2859 | goto sesssetup_nomem; | ||
2860 | strncpy(ses->serverNOS, bcc_ptr, len); | ||
2861 | bcc_ptr += len; | ||
2862 | bcc_ptr[0] = 0; | ||
2863 | bcc_ptr++; | ||
2864 | |||
2865 | len = strnlen(bcc_ptr, 1024); | ||
2866 | kfree(ses->serverDomain); | ||
2867 | ses->serverDomain = kzalloc(len + 1, | ||
2868 | GFP_KERNEL); | ||
2869 | if (ses->serverDomain == NULL) | ||
2870 | goto sesssetup_nomem; | ||
2871 | strncpy(ses->serverDomain, bcc_ptr, | ||
2872 | len); | ||
2873 | bcc_ptr += len; | ||
2874 | bcc_ptr[0] = 0; | ||
2875 | bcc_ptr++; | ||
2876 | } else | ||
2877 | cFYI(1, | ||
2878 | ("Variable field of length %d " | ||
2879 | "extends beyond end of smb ", | ||
2880 | len)); | ||
2881 | } | ||
2882 | } else { | ||
2883 | cERROR(1, ("Security Blob Length extends beyond " | ||
2884 | "end of SMB")); | ||
2885 | } | ||
2886 | } else { | ||
2887 | cERROR(1, ("Invalid Word count %d: ", | ||
2888 | smb_buffer_response->WordCount)); | ||
2889 | rc = -EIO; | ||
2890 | } | ||
2891 | sesssetup_nomem: /* do not return an error on nomem for the info strings, | ||
2892 | since that could make reconnection harder, and | ||
2893 | reconnection might be needed to free memory */ | ||
2894 | cifs_buf_release(smb_buffer); | ||
2895 | |||
2896 | return rc; | ||
2897 | } | ||
2898 | |||
2899 | static int | ||
2900 | CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, | ||
2901 | struct cifsSesInfo *ses, bool *pNTLMv2_flag, | ||
2902 | const struct nls_table *nls_codepage) | ||
2903 | { | ||
2904 | struct smb_hdr *smb_buffer; | ||
2905 | struct smb_hdr *smb_buffer_response; | ||
2906 | SESSION_SETUP_ANDX *pSMB; | ||
2907 | SESSION_SETUP_ANDX *pSMBr; | ||
2908 | char *bcc_ptr; | ||
2909 | char *domain; | ||
2910 | int rc = 0; | ||
2911 | int remaining_words = 0; | ||
2912 | int bytes_returned = 0; | ||
2913 | int len; | ||
2914 | int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE); | ||
2915 | PNEGOTIATE_MESSAGE SecurityBlob; | ||
2916 | PCHALLENGE_MESSAGE SecurityBlob2; | ||
2917 | __u32 negotiate_flags, capabilities; | ||
2918 | __u16 count; | ||
2919 | |||
2920 | cFYI(1, ("In NTLMSSP sesssetup (negotiate)")); | ||
2921 | if (ses == NULL) | ||
2922 | return -EINVAL; | ||
2923 | domain = ses->domainName; | ||
2924 | *pNTLMv2_flag = false; | ||
2925 | smb_buffer = cifs_buf_get(); | ||
2926 | if (smb_buffer == NULL) { | ||
2927 | return -ENOMEM; | ||
2928 | } | ||
2929 | smb_buffer_response = smb_buffer; | ||
2930 | pSMB = (SESSION_SETUP_ANDX *) smb_buffer; | ||
2931 | pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response; | ||
2932 | |||
2933 | /* send SMBsessionSetup here */ | ||
2934 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | ||
2935 | NULL /* no tCon exists yet */ , 12 /* wct */ ); | ||
2936 | |||
2937 | smb_buffer->Mid = GetNextMid(ses->server); | ||
2938 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | ||
2939 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); | ||
2940 | |||
2941 | pSMB->req.AndXCommand = 0xFF; | ||
2942 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | ||
2943 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); | ||
2944 | |||
2945 | if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
2946 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | ||
2947 | |||
2948 | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | | ||
2949 | CAP_EXTENDED_SECURITY; | ||
2950 | if (ses->capabilities & CAP_UNICODE) { | ||
2951 | smb_buffer->Flags2 |= SMBFLG2_UNICODE; | ||
2952 | capabilities |= CAP_UNICODE; | ||
2953 | } | ||
2954 | if (ses->capabilities & CAP_STATUS32) { | ||
2955 | smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; | ||
2956 | capabilities |= CAP_STATUS32; | ||
2957 | } | ||
2958 | if (ses->capabilities & CAP_DFS) { | ||
2959 | smb_buffer->Flags2 |= SMBFLG2_DFS; | ||
2960 | capabilities |= CAP_DFS; | ||
2961 | } | ||
2962 | pSMB->req.Capabilities = cpu_to_le32(capabilities); | ||
2963 | |||
2964 | bcc_ptr = (char *) &pSMB->req.SecurityBlob; | ||
2965 | SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr; | ||
2966 | strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); | ||
2967 | SecurityBlob->MessageType = NtLmNegotiate; | ||
2968 | negotiate_flags = | ||
2969 | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM | | ||
2970 | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM | | ||
2971 | NTLMSSP_NEGOTIATE_56 | | ||
2972 | /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128; | ||
2973 | if (sign_CIFS_PDUs) | ||
2974 | negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN; | ||
2975 | /* if (ntlmv2_support) | ||
2976 | negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/ | ||
2977 | /* setup pointers to domain name and workstation name */ | ||
2978 | bcc_ptr += SecurityBlobLength; | ||
2979 | |||
2980 | SecurityBlob->WorkstationName.Buffer = 0; | ||
2981 | SecurityBlob->WorkstationName.Length = 0; | ||
2982 | SecurityBlob->WorkstationName.MaximumLength = 0; | ||
2983 | |||
2984 | /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent | ||
2985 | along with username on auth request (ie the response to challenge) */ | ||
2986 | SecurityBlob->DomainName.Buffer = 0; | ||
2987 | SecurityBlob->DomainName.Length = 0; | ||
2988 | SecurityBlob->DomainName.MaximumLength = 0; | ||
2989 | if (ses->capabilities & CAP_UNICODE) { | ||
2990 | if ((long) bcc_ptr % 2) { | ||
2991 | *bcc_ptr = 0; | ||
2992 | bcc_ptr++; | ||
2993 | } | ||
2994 | |||
2995 | bytes_returned = | ||
2996 | cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", | ||
2997 | 32, nls_codepage); | ||
2998 | bcc_ptr += 2 * bytes_returned; | ||
2999 | bytes_returned = | ||
3000 | cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32, | ||
3001 | nls_codepage); | ||
3002 | bcc_ptr += 2 * bytes_returned; | ||
3003 | bcc_ptr += 2; /* null terminate Linux version */ | ||
3004 | bytes_returned = | ||
3005 | cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, | ||
3006 | 64, nls_codepage); | ||
3007 | bcc_ptr += 2 * bytes_returned; | ||
3008 | *(bcc_ptr + 1) = 0; | ||
3009 | *(bcc_ptr + 2) = 0; | ||
3010 | bcc_ptr += 2; /* null terminate network opsys string */ | ||
3011 | *(bcc_ptr + 1) = 0; | ||
3012 | *(bcc_ptr + 2) = 0; | ||
3013 | bcc_ptr += 2; /* null domain */ | ||
3014 | } else { /* ASCII */ | ||
3015 | strcpy(bcc_ptr, "Linux version "); | ||
3016 | bcc_ptr += strlen("Linux version "); | ||
3017 | strcpy(bcc_ptr, utsname()->release); | ||
3018 | bcc_ptr += strlen(utsname()->release) + 1; | ||
3019 | strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); | ||
3020 | bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; | ||
3021 | bcc_ptr++; /* empty domain field */ | ||
3022 | *bcc_ptr = 0; | ||
3023 | } | ||
3024 | SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags); | ||
3025 | pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); | ||
3026 | count = (long) bcc_ptr - (long) pByteArea(smb_buffer); | ||
3027 | smb_buffer->smb_buf_length += count; | ||
3028 | pSMB->req.ByteCount = cpu_to_le16(count); | ||
3029 | |||
3030 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | ||
3031 | &bytes_returned, CIFS_LONG_OP); | ||
3032 | |||
3033 | if (smb_buffer_response->Status.CifsError == | ||
3034 | cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED)) | ||
3035 | rc = 0; | ||
3036 | |||
3037 | if (rc) { | ||
3038 | /* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */ | ||
3039 | } else if ((smb_buffer_response->WordCount == 3) | ||
3040 | || (smb_buffer_response->WordCount == 4)) { | ||
3041 | __u16 action = le16_to_cpu(pSMBr->resp.Action); | ||
3042 | __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); | ||
3043 | |||
3044 | if (action & GUEST_LOGIN) | ||
3045 | cFYI(1, ("Guest login")); | ||
3046 | /* Do we want to set anything in SesInfo struct when guest login? */ | ||
3047 | |||
3048 | bcc_ptr = pByteArea(smb_buffer_response); | ||
3049 | /* response can have either 3 or 4 word count - Samba sends 3 */ | ||
3050 | |||
3051 | SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr; | ||
3052 | if (SecurityBlob2->MessageType != NtLmChallenge) { | ||
3053 | cFYI(1, ("Unexpected NTLMSSP message type received %d", | ||
3054 | SecurityBlob2->MessageType)); | ||
3055 | } else if (ses) { | ||
3056 | ses->Suid = smb_buffer_response->Uid; /* UID left in le format */ | ||
3057 | cFYI(1, ("UID = %d", ses->Suid)); | ||
3058 | if ((pSMBr->resp.hdr.WordCount == 3) | ||
3059 | || ((pSMBr->resp.hdr.WordCount == 4) | ||
3060 | && (blob_len < | ||
3061 | pSMBr->resp.ByteCount))) { | ||
3062 | |||
3063 | if (pSMBr->resp.hdr.WordCount == 4) { | ||
3064 | bcc_ptr += blob_len; | ||
3065 | cFYI(1, ("Security Blob Length %d", | ||
3066 | blob_len)); | ||
3067 | } | ||
3068 | |||
3069 | cFYI(1, ("NTLMSSP Challenge rcvd")); | ||
3070 | |||
3071 | memcpy(ses->server->cryptKey, | ||
3072 | SecurityBlob2->Challenge, | ||
3073 | CIFS_CRYPTO_KEY_SIZE); | ||
3074 | if (SecurityBlob2->NegotiateFlags & | ||
3075 | cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2)) | ||
3076 | *pNTLMv2_flag = true; | ||
3077 | |||
3078 | if ((SecurityBlob2->NegotiateFlags & | ||
3079 | cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) | ||
3080 | || (sign_CIFS_PDUs > 1)) | ||
3081 | ses->server->secMode |= | ||
3082 | SECMODE_SIGN_REQUIRED; | ||
3083 | if ((SecurityBlob2->NegotiateFlags & | ||
3084 | cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs)) | ||
3085 | ses->server->secMode |= | ||
3086 | SECMODE_SIGN_ENABLED; | ||
3087 | |||
3088 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { | ||
3089 | if ((long) (bcc_ptr) % 2) { | ||
3090 | remaining_words = | ||
3091 | (BCC(smb_buffer_response) | ||
3092 | - 1) / 2; | ||
3093 | /* Must word align unicode strings */ | ||
3094 | bcc_ptr++; | ||
3095 | } else { | ||
3096 | remaining_words = | ||
3097 | BCC | ||
3098 | (smb_buffer_response) / 2; | ||
3099 | } | ||
3100 | len = | ||
3101 | UniStrnlen((wchar_t *) bcc_ptr, | ||
3102 | remaining_words - 1); | ||
3103 | /* We look for obvious messed up bcc or strings in response so we do not go off | ||
3104 | the end since (at least) WIN2K and Windows XP have a major bug in not null | ||
3105 | terminating last Unicode string in response */ | ||
3106 | kfree(ses->serverOS); | ||
3107 | ses->serverOS = | ||
3108 | kzalloc(2 * (len + 1), GFP_KERNEL); | ||
3109 | cifs_strfromUCS_le(ses->serverOS, | ||
3110 | (__le16 *) | ||
3111 | bcc_ptr, len, | ||
3112 | nls_codepage); | ||
3113 | bcc_ptr += 2 * (len + 1); | ||
3114 | remaining_words -= len + 1; | ||
3115 | ses->serverOS[2 * len] = 0; | ||
3116 | ses->serverOS[1 + (2 * len)] = 0; | ||
3117 | if (remaining_words > 0) { | ||
3118 | len = UniStrnlen((wchar_t *) | ||
3119 | bcc_ptr, | ||
3120 | remaining_words | ||
3121 | - 1); | ||
3122 | kfree(ses->serverNOS); | ||
3123 | ses->serverNOS = | ||
3124 | kzalloc(2 * (len + 1), | ||
3125 | GFP_KERNEL); | ||
3126 | cifs_strfromUCS_le(ses-> | ||
3127 | serverNOS, | ||
3128 | (__le16 *) | ||
3129 | bcc_ptr, | ||
3130 | len, | ||
3131 | nls_codepage); | ||
3132 | bcc_ptr += 2 * (len + 1); | ||
3133 | ses->serverNOS[2 * len] = 0; | ||
3134 | ses->serverNOS[1 + | ||
3135 | (2 * len)] = 0; | ||
3136 | remaining_words -= len + 1; | ||
3137 | if (remaining_words > 0) { | ||
3138 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); | ||
3139 | /* last string not always null terminated | ||
3140 | (for e.g. for Windows XP & 2000) */ | ||
3141 | kfree(ses->serverDomain); | ||
3142 | ses->serverDomain = | ||
3143 | kzalloc(2 * | ||
3144 | (len + | ||
3145 | 1), | ||
3146 | GFP_KERNEL); | ||
3147 | cifs_strfromUCS_le | ||
3148 | (ses->serverDomain, | ||
3149 | (__le16 *)bcc_ptr, | ||
3150 | len, nls_codepage); | ||
3151 | bcc_ptr += | ||
3152 | 2 * (len + 1); | ||
3153 | ses->serverDomain[2*len] | ||
3154 | = 0; | ||
3155 | ses->serverDomain | ||
3156 | [1 + (2 * len)] | ||
3157 | = 0; | ||
3158 | } /* else no more room so create dummy domain string */ | ||
3159 | else { | ||
3160 | kfree(ses->serverDomain); | ||
3161 | ses->serverDomain = | ||
3162 | kzalloc(2, | ||
3163 | GFP_KERNEL); | ||
3164 | } | ||
3165 | } else { /* no room so create dummy domain and NOS string */ | ||
3166 | kfree(ses->serverDomain); | ||
3167 | ses->serverDomain = | ||
3168 | kzalloc(2, GFP_KERNEL); | ||
3169 | kfree(ses->serverNOS); | ||
3170 | ses->serverNOS = | ||
3171 | kzalloc(2, GFP_KERNEL); | ||
3172 | } | ||
3173 | } else { /* ASCII */ | ||
3174 | len = strnlen(bcc_ptr, 1024); | ||
3175 | if (((long) bcc_ptr + len) - (long) | ||
3176 | pByteArea(smb_buffer_response) | ||
3177 | <= BCC(smb_buffer_response)) { | ||
3178 | kfree(ses->serverOS); | ||
3179 | ses->serverOS = | ||
3180 | kzalloc(len + 1, | ||
3181 | GFP_KERNEL); | ||
3182 | strncpy(ses->serverOS, | ||
3183 | bcc_ptr, len); | ||
3184 | |||
3185 | bcc_ptr += len; | ||
3186 | bcc_ptr[0] = 0; /* null terminate string */ | ||
3187 | bcc_ptr++; | ||
3188 | |||
3189 | len = strnlen(bcc_ptr, 1024); | ||
3190 | kfree(ses->serverNOS); | ||
3191 | ses->serverNOS = | ||
3192 | kzalloc(len + 1, | ||
3193 | GFP_KERNEL); | ||
3194 | strncpy(ses->serverNOS, bcc_ptr, len); | ||
3195 | bcc_ptr += len; | ||
3196 | bcc_ptr[0] = 0; | ||
3197 | bcc_ptr++; | ||
3198 | |||
3199 | len = strnlen(bcc_ptr, 1024); | ||
3200 | kfree(ses->serverDomain); | ||
3201 | ses->serverDomain = | ||
3202 | kzalloc(len + 1, | ||
3203 | GFP_KERNEL); | ||
3204 | strncpy(ses->serverDomain, | ||
3205 | bcc_ptr, len); | ||
3206 | bcc_ptr += len; | ||
3207 | bcc_ptr[0] = 0; | ||
3208 | bcc_ptr++; | ||
3209 | } else | ||
3210 | cFYI(1, | ||
3211 | ("field of length %d " | ||
3212 | "extends beyond end of smb", | ||
3213 | len)); | ||
3214 | } | ||
3215 | } else { | ||
3216 | cERROR(1, ("Security Blob Length extends beyond" | ||
3217 | " end of SMB")); | ||
3218 | } | ||
3219 | } else { | ||
3220 | cERROR(1, ("No session structure passed in.")); | ||
3221 | } | ||
3222 | } else { | ||
3223 | cERROR(1, ("Invalid Word count %d:", | ||
3224 | smb_buffer_response->WordCount)); | ||
3225 | rc = -EIO; | ||
3226 | } | ||
3227 | |||
3228 | cifs_buf_release(smb_buffer); | ||
3229 | |||
3230 | return rc; | ||
3231 | } | ||
3232 | static int | ||
3233 | CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, | ||
3234 | char *ntlm_session_key, bool ntlmv2_flag, | ||
3235 | const struct nls_table *nls_codepage) | ||
3236 | { | ||
3237 | struct smb_hdr *smb_buffer; | ||
3238 | struct smb_hdr *smb_buffer_response; | ||
3239 | SESSION_SETUP_ANDX *pSMB; | ||
3240 | SESSION_SETUP_ANDX *pSMBr; | ||
3241 | char *bcc_ptr; | ||
3242 | char *user; | ||
3243 | char *domain; | ||
3244 | int rc = 0; | ||
3245 | int remaining_words = 0; | ||
3246 | int bytes_returned = 0; | ||
3247 | int len; | ||
3248 | int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE); | ||
3249 | PAUTHENTICATE_MESSAGE SecurityBlob; | ||
3250 | __u32 negotiate_flags, capabilities; | ||
3251 | __u16 count; | ||
3252 | |||
3253 | cFYI(1, ("In NTLMSSPSessSetup (Authenticate)")); | ||
3254 | if (ses == NULL) | ||
3255 | return -EINVAL; | ||
3256 | user = ses->userName; | ||
3257 | domain = ses->domainName; | ||
3258 | smb_buffer = cifs_buf_get(); | ||
3259 | if (smb_buffer == NULL) { | ||
3260 | return -ENOMEM; | ||
3261 | } | ||
3262 | smb_buffer_response = smb_buffer; | ||
3263 | pSMB = (SESSION_SETUP_ANDX *)smb_buffer; | ||
3264 | pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response; | ||
3265 | |||
3266 | /* send SMBsessionSetup here */ | ||
3267 | header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX, | ||
3268 | NULL /* no tCon exists yet */ , 12 /* wct */ ); | ||
3269 | |||
3270 | smb_buffer->Mid = GetNextMid(ses->server); | ||
3271 | pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT); | ||
3272 | pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; | ||
3273 | pSMB->req.AndXCommand = 0xFF; | ||
3274 | pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); | ||
3275 | pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); | ||
3276 | |||
3277 | pSMB->req.hdr.Uid = ses->Suid; | ||
3278 | |||
3279 | if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
3280 | smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | ||
3281 | |||
3282 | capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | | ||
3283 | CAP_EXTENDED_SECURITY; | ||
3284 | if (ses->capabilities & CAP_UNICODE) { | ||
3285 | smb_buffer->Flags2 |= SMBFLG2_UNICODE; | ||
3286 | capabilities |= CAP_UNICODE; | ||
3287 | } | ||
3288 | if (ses->capabilities & CAP_STATUS32) { | ||
3289 | smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS; | ||
3290 | capabilities |= CAP_STATUS32; | ||
3291 | } | ||
3292 | if (ses->capabilities & CAP_DFS) { | ||
3293 | smb_buffer->Flags2 |= SMBFLG2_DFS; | ||
3294 | capabilities |= CAP_DFS; | ||
3295 | } | ||
3296 | pSMB->req.Capabilities = cpu_to_le32(capabilities); | ||
3297 | |||
3298 | bcc_ptr = (char *)&pSMB->req.SecurityBlob; | ||
3299 | SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr; | ||
3300 | strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8); | ||
3301 | SecurityBlob->MessageType = NtLmAuthenticate; | ||
3302 | bcc_ptr += SecurityBlobLength; | ||
3303 | negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | | ||
3304 | NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO | | ||
3305 | 0x80000000 | NTLMSSP_NEGOTIATE_128; | ||
3306 | if (sign_CIFS_PDUs) | ||
3307 | negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN; | ||
3308 | if (ntlmv2_flag) | ||
3309 | negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2; | ||
3310 | |||
3311 | /* setup pointers to domain name and workstation name */ | ||
3312 | |||
3313 | SecurityBlob->WorkstationName.Buffer = 0; | ||
3314 | SecurityBlob->WorkstationName.Length = 0; | ||
3315 | SecurityBlob->WorkstationName.MaximumLength = 0; | ||
3316 | SecurityBlob->SessionKey.Length = 0; | ||
3317 | SecurityBlob->SessionKey.MaximumLength = 0; | ||
3318 | SecurityBlob->SessionKey.Buffer = 0; | ||
3319 | |||
3320 | SecurityBlob->LmChallengeResponse.Length = 0; | ||
3321 | SecurityBlob->LmChallengeResponse.MaximumLength = 0; | ||
3322 | SecurityBlob->LmChallengeResponse.Buffer = 0; | ||
3323 | |||
3324 | SecurityBlob->NtChallengeResponse.Length = | ||
3325 | cpu_to_le16(CIFS_SESS_KEY_SIZE); | ||
3326 | SecurityBlob->NtChallengeResponse.MaximumLength = | ||
3327 | cpu_to_le16(CIFS_SESS_KEY_SIZE); | ||
3328 | memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE); | ||
3329 | SecurityBlob->NtChallengeResponse.Buffer = | ||
3330 | cpu_to_le32(SecurityBlobLength); | ||
3331 | SecurityBlobLength += CIFS_SESS_KEY_SIZE; | ||
3332 | bcc_ptr += CIFS_SESS_KEY_SIZE; | ||
3333 | |||
3334 | if (ses->capabilities & CAP_UNICODE) { | ||
3335 | if (domain == NULL) { | ||
3336 | SecurityBlob->DomainName.Buffer = 0; | ||
3337 | SecurityBlob->DomainName.Length = 0; | ||
3338 | SecurityBlob->DomainName.MaximumLength = 0; | ||
3339 | } else { | ||
3340 | __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64, | ||
3341 | nls_codepage); | ||
3342 | ln *= 2; | ||
3343 | SecurityBlob->DomainName.MaximumLength = | ||
3344 | cpu_to_le16(ln); | ||
3345 | SecurityBlob->DomainName.Buffer = | ||
3346 | cpu_to_le32(SecurityBlobLength); | ||
3347 | bcc_ptr += ln; | ||
3348 | SecurityBlobLength += ln; | ||
3349 | SecurityBlob->DomainName.Length = cpu_to_le16(ln); | ||
3350 | } | ||
3351 | if (user == NULL) { | ||
3352 | SecurityBlob->UserName.Buffer = 0; | ||
3353 | SecurityBlob->UserName.Length = 0; | ||
3354 | SecurityBlob->UserName.MaximumLength = 0; | ||
3355 | } else { | ||
3356 | __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64, | ||
3357 | nls_codepage); | ||
3358 | ln *= 2; | ||
3359 | SecurityBlob->UserName.MaximumLength = | ||
3360 | cpu_to_le16(ln); | ||
3361 | SecurityBlob->UserName.Buffer = | ||
3362 | cpu_to_le32(SecurityBlobLength); | ||
3363 | bcc_ptr += ln; | ||
3364 | SecurityBlobLength += ln; | ||
3365 | SecurityBlob->UserName.Length = cpu_to_le16(ln); | ||
3366 | } | ||
3367 | |||
3368 | /* SecurityBlob->WorkstationName.Length = | ||
3369 | cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage); | ||
3370 | SecurityBlob->WorkstationName.Length *= 2; | ||
3371 | SecurityBlob->WorkstationName.MaximumLength = | ||
3372 | cpu_to_le16(SecurityBlob->WorkstationName.Length); | ||
3373 | SecurityBlob->WorkstationName.Buffer = | ||
3374 | cpu_to_le32(SecurityBlobLength); | ||
3375 | bcc_ptr += SecurityBlob->WorkstationName.Length; | ||
3376 | SecurityBlobLength += SecurityBlob->WorkstationName.Length; | ||
3377 | SecurityBlob->WorkstationName.Length = | ||
3378 | cpu_to_le16(SecurityBlob->WorkstationName.Length); */ | ||
3379 | |||
3380 | if ((long) bcc_ptr % 2) { | ||
3381 | *bcc_ptr = 0; | ||
3382 | bcc_ptr++; | ||
3383 | } | ||
3384 | bytes_returned = | ||
3385 | cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ", | ||
3386 | 32, nls_codepage); | ||
3387 | bcc_ptr += 2 * bytes_returned; | ||
3388 | bytes_returned = | ||
3389 | cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32, | ||
3390 | nls_codepage); | ||
3391 | bcc_ptr += 2 * bytes_returned; | ||
3392 | bcc_ptr += 2; /* null term version string */ | ||
3393 | bytes_returned = | ||
3394 | cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, | ||
3395 | 64, nls_codepage); | ||
3396 | bcc_ptr += 2 * bytes_returned; | ||
3397 | *(bcc_ptr + 1) = 0; | ||
3398 | *(bcc_ptr + 2) = 0; | ||
3399 | bcc_ptr += 2; /* null terminate network opsys string */ | ||
3400 | *(bcc_ptr + 1) = 0; | ||
3401 | *(bcc_ptr + 2) = 0; | ||
3402 | bcc_ptr += 2; /* null domain */ | ||
3403 | } else { /* ASCII */ | ||
3404 | if (domain == NULL) { | ||
3405 | SecurityBlob->DomainName.Buffer = 0; | ||
3406 | SecurityBlob->DomainName.Length = 0; | ||
3407 | SecurityBlob->DomainName.MaximumLength = 0; | ||
3408 | } else { | ||
3409 | __u16 ln; | ||
3410 | negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED; | ||
3411 | strncpy(bcc_ptr, domain, 63); | ||
3412 | ln = strnlen(domain, 64); | ||
3413 | SecurityBlob->DomainName.MaximumLength = | ||
3414 | cpu_to_le16(ln); | ||
3415 | SecurityBlob->DomainName.Buffer = | ||
3416 | cpu_to_le32(SecurityBlobLength); | ||
3417 | bcc_ptr += ln; | ||
3418 | SecurityBlobLength += ln; | ||
3419 | SecurityBlob->DomainName.Length = cpu_to_le16(ln); | ||
3420 | } | ||
3421 | if (user == NULL) { | ||
3422 | SecurityBlob->UserName.Buffer = 0; | ||
3423 | SecurityBlob->UserName.Length = 0; | ||
3424 | SecurityBlob->UserName.MaximumLength = 0; | ||
3425 | } else { | ||
3426 | __u16 ln; | ||
3427 | strncpy(bcc_ptr, user, 63); | ||
3428 | ln = strnlen(user, 64); | ||
3429 | SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln); | ||
3430 | SecurityBlob->UserName.Buffer = | ||
3431 | cpu_to_le32(SecurityBlobLength); | ||
3432 | bcc_ptr += ln; | ||
3433 | SecurityBlobLength += ln; | ||
3434 | SecurityBlob->UserName.Length = cpu_to_le16(ln); | ||
3435 | } | ||
3436 | /* BB fill in our workstation name if known BB */ | ||
3437 | |||
3438 | strcpy(bcc_ptr, "Linux version "); | ||
3439 | bcc_ptr += strlen("Linux version "); | ||
3440 | strcpy(bcc_ptr, utsname()->release); | ||
3441 | bcc_ptr += strlen(utsname()->release) + 1; | ||
3442 | strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); | ||
3443 | bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; | ||
3444 | bcc_ptr++; /* null domain */ | ||
3445 | *bcc_ptr = 0; | ||
3446 | } | ||
3447 | SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags); | ||
3448 | pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength); | ||
3449 | count = (long) bcc_ptr - (long) pByteArea(smb_buffer); | ||
3450 | smb_buffer->smb_buf_length += count; | ||
3451 | pSMB->req.ByteCount = cpu_to_le16(count); | ||
3452 | |||
3453 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, | ||
3454 | &bytes_returned, CIFS_LONG_OP); | ||
3455 | if (rc) { | ||
3456 | /* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */ | ||
3457 | } else if ((smb_buffer_response->WordCount == 3) || | ||
3458 | (smb_buffer_response->WordCount == 4)) { | ||
3459 | __u16 action = le16_to_cpu(pSMBr->resp.Action); | ||
3460 | __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength); | ||
3461 | if (action & GUEST_LOGIN) | ||
3462 | cFYI(1, ("Guest login")); /* BB Should we set anything | ||
3463 | in SesInfo struct ? */ | ||
3464 | /* if (SecurityBlob2->MessageType != NtLm??) { | ||
3465 | cFYI("Unexpected message type on auth response is %d")); | ||
3466 | } */ | ||
3467 | |||
3468 | if (ses) { | ||
3469 | cFYI(1, | ||
3470 | ("Check challenge UID %d vs auth response UID %d", | ||
3471 | ses->Suid, smb_buffer_response->Uid)); | ||
3472 | /* UID left in wire format */ | ||
3473 | ses->Suid = smb_buffer_response->Uid; | ||
3474 | bcc_ptr = pByteArea(smb_buffer_response); | ||
3475 | /* response can have either 3 or 4 word count - Samba sends 3 */ | ||
3476 | if ((pSMBr->resp.hdr.WordCount == 3) | ||
3477 | || ((pSMBr->resp.hdr.WordCount == 4) | ||
3478 | && (blob_len < | ||
3479 | pSMBr->resp.ByteCount))) { | ||
3480 | if (pSMBr->resp.hdr.WordCount == 4) { | ||
3481 | bcc_ptr += | ||
3482 | blob_len; | ||
3483 | cFYI(1, | ||
3484 | ("Security Blob Length %d ", | ||
3485 | blob_len)); | ||
3486 | } | ||
3487 | |||
3488 | cFYI(1, | ||
3489 | ("NTLMSSP response to Authenticate ")); | ||
3490 | |||
3491 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { | ||
3492 | if ((long) (bcc_ptr) % 2) { | ||
3493 | remaining_words = | ||
3494 | (BCC(smb_buffer_response) | ||
3495 | - 1) / 2; | ||
3496 | bcc_ptr++; /* Unicode strings must be word aligned */ | ||
3497 | } else { | ||
3498 | remaining_words = BCC(smb_buffer_response) / 2; | ||
3499 | } | ||
3500 | len = UniStrnlen((wchar_t *) bcc_ptr, | ||
3501 | remaining_words - 1); | ||
3502 | /* We look for obvious messed up bcc or strings in response so we do not go off | ||
3503 | the end since (at least) WIN2K and Windows XP have a major bug in not null | ||
3504 | terminating last Unicode string in response */ | ||
3505 | kfree(ses->serverOS); | ||
3506 | ses->serverOS = | ||
3507 | kzalloc(2 * (len + 1), GFP_KERNEL); | ||
3508 | cifs_strfromUCS_le(ses->serverOS, | ||
3509 | (__le16 *) | ||
3510 | bcc_ptr, len, | ||
3511 | nls_codepage); | ||
3512 | bcc_ptr += 2 * (len + 1); | ||
3513 | remaining_words -= len + 1; | ||
3514 | ses->serverOS[2 * len] = 0; | ||
3515 | ses->serverOS[1 + (2 * len)] = 0; | ||
3516 | if (remaining_words > 0) { | ||
3517 | len = UniStrnlen((wchar_t *) | ||
3518 | bcc_ptr, | ||
3519 | remaining_words | ||
3520 | - 1); | ||
3521 | kfree(ses->serverNOS); | ||
3522 | ses->serverNOS = | ||
3523 | kzalloc(2 * (len + 1), | ||
3524 | GFP_KERNEL); | ||
3525 | cifs_strfromUCS_le(ses-> | ||
3526 | serverNOS, | ||
3527 | (__le16 *) | ||
3528 | bcc_ptr, | ||
3529 | len, | ||
3530 | nls_codepage); | ||
3531 | bcc_ptr += 2 * (len + 1); | ||
3532 | ses->serverNOS[2 * len] = 0; | ||
3533 | ses->serverNOS[1+(2*len)] = 0; | ||
3534 | remaining_words -= len + 1; | ||
3535 | if (remaining_words > 0) { | ||
3536 | len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); | ||
3537 | /* last string not always null terminated (e.g. for Windows XP & 2000) */ | ||
3538 | kfree(ses->serverDomain); | ||
3539 | ses->serverDomain = | ||
3540 | kzalloc(2 * | ||
3541 | (len + | ||
3542 | 1), | ||
3543 | GFP_KERNEL); | ||
3544 | cifs_strfromUCS_le | ||
3545 | (ses-> | ||
3546 | serverDomain, | ||
3547 | (__le16 *) | ||
3548 | bcc_ptr, len, | ||
3549 | nls_codepage); | ||
3550 | bcc_ptr += | ||
3551 | 2 * (len + 1); | ||
3552 | ses-> | ||
3553 | serverDomain[2 | ||
3554 | * len] | ||
3555 | = 0; | ||
3556 | ses-> | ||
3557 | serverDomain[1 | ||
3558 | + | ||
3559 | (2 | ||
3560 | * | ||
3561 | len)] | ||
3562 | = 0; | ||
3563 | } /* else no more room so create dummy domain string */ | ||
3564 | else { | ||
3565 | kfree(ses->serverDomain); | ||
3566 | ses->serverDomain = kzalloc(2,GFP_KERNEL); | ||
3567 | } | ||
3568 | } else { /* no room so create dummy domain and NOS string */ | ||
3569 | kfree(ses->serverDomain); | ||
3570 | ses->serverDomain = kzalloc(2, GFP_KERNEL); | ||
3571 | kfree(ses->serverNOS); | ||
3572 | ses->serverNOS = kzalloc(2, GFP_KERNEL); | ||
3573 | } | ||
3574 | } else { /* ASCII */ | ||
3575 | len = strnlen(bcc_ptr, 1024); | ||
3576 | if (((long) bcc_ptr + len) - | ||
3577 | (long) pByteArea(smb_buffer_response) | ||
3578 | <= BCC(smb_buffer_response)) { | ||
3579 | kfree(ses->serverOS); | ||
3580 | ses->serverOS = kzalloc(len + 1, GFP_KERNEL); | ||
3581 | strncpy(ses->serverOS,bcc_ptr, len); | ||
3582 | |||
3583 | bcc_ptr += len; | ||
3584 | bcc_ptr[0] = 0; /* null terminate the string */ | ||
3585 | bcc_ptr++; | ||
3586 | |||
3587 | len = strnlen(bcc_ptr, 1024); | ||
3588 | kfree(ses->serverNOS); | ||
3589 | ses->serverNOS = kzalloc(len+1, | ||
3590 | GFP_KERNEL); | ||
3591 | strncpy(ses->serverNOS, | ||
3592 | bcc_ptr, len); | ||
3593 | bcc_ptr += len; | ||
3594 | bcc_ptr[0] = 0; | ||
3595 | bcc_ptr++; | ||
3596 | |||
3597 | len = strnlen(bcc_ptr, 1024); | ||
3598 | kfree(ses->serverDomain); | ||
3599 | ses->serverDomain = | ||
3600 | kzalloc(len+1, | ||
3601 | GFP_KERNEL); | ||
3602 | strncpy(ses->serverDomain, | ||
3603 | bcc_ptr, len); | ||
3604 | bcc_ptr += len; | ||
3605 | bcc_ptr[0] = 0; | ||
3606 | bcc_ptr++; | ||
3607 | } else | ||
3608 | cFYI(1, ("field of length %d " | ||
3609 | "extends beyond end of smb ", | ||
3610 | len)); | ||
3611 | } | ||
3612 | } else { | ||
3613 | cERROR(1, ("Security Blob extends beyond end " | ||
3614 | "of SMB")); | ||
3615 | } | ||
3616 | } else { | ||
3617 | cERROR(1, ("No session structure passed in.")); | ||
3618 | } | ||
3619 | } else { | ||
3620 | cERROR(1, ("Invalid Word count %d: ", | ||
3621 | smb_buffer_response->WordCount)); | ||
3622 | rc = -EIO; | ||
3623 | } | ||
3624 | |||
3625 | cifs_buf_release(smb_buffer); | ||
3626 | |||
3627 | return rc; | ||
3628 | } | ||
3629 | |||
3630 | int | 2615 | int |
3631 | CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | 2616 | CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, |
3632 | const char *tree, struct cifsTconInfo *tcon, | 2617 | const char *tree, struct cifsTconInfo *tcon, |
@@ -3638,7 +2623,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3638 | TCONX_RSP *pSMBr; | 2623 | TCONX_RSP *pSMBr; |
3639 | unsigned char *bcc_ptr; | 2624 | unsigned char *bcc_ptr; |
3640 | int rc = 0; | 2625 | int rc = 0; |
3641 | int length; | 2626 | int length, bytes_left; |
3642 | __u16 count; | 2627 | __u16 count; |
3643 | 2628 | ||
3644 | if (ses == NULL) | 2629 | if (ses == NULL) |
@@ -3726,14 +2711,22 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3726 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, | 2711 | rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length, |
3727 | CIFS_STD_OP); | 2712 | CIFS_STD_OP); |
3728 | 2713 | ||
3729 | /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */ | ||
3730 | /* above now done in SendReceive */ | 2714 | /* above now done in SendReceive */ |
3731 | if ((rc == 0) && (tcon != NULL)) { | 2715 | if ((rc == 0) && (tcon != NULL)) { |
2716 | bool is_unicode; | ||
2717 | |||
3732 | tcon->tidStatus = CifsGood; | 2718 | tcon->tidStatus = CifsGood; |
3733 | tcon->need_reconnect = false; | 2719 | tcon->need_reconnect = false; |
3734 | tcon->tid = smb_buffer_response->Tid; | 2720 | tcon->tid = smb_buffer_response->Tid; |
3735 | bcc_ptr = pByteArea(smb_buffer_response); | 2721 | bcc_ptr = pByteArea(smb_buffer_response); |
3736 | 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 | |||
3737 | /* skip service field (NB: this field is always ASCII) */ | 2730 | /* skip service field (NB: this field is always ASCII) */ |
3738 | if (length == 3) { | 2731 | if (length == 3) { |
3739 | if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') && | 2732 | if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') && |
@@ -3748,39 +2741,16 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
3748 | } | 2741 | } |
3749 | } | 2742 | } |
3750 | bcc_ptr += length + 1; | 2743 | bcc_ptr += length + 1; |
2744 | bytes_left -= (length + 1); | ||
3751 | strncpy(tcon->treeName, tree, MAX_TREE_SIZE); | 2745 | strncpy(tcon->treeName, tree, MAX_TREE_SIZE); |
3752 | if (smb_buffer->Flags2 & SMBFLG2_UNICODE) { | 2746 | |
3753 | length = UniStrnlen((wchar_t *) bcc_ptr, 512); | 2747 | /* mostly informational -- no need to fail on error here */ |
3754 | if ((bcc_ptr + (2 * length)) - | 2748 | tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr, |
3755 | pByteArea(smb_buffer_response) <= | 2749 | bytes_left, is_unicode, |
3756 | BCC(smb_buffer_response)) { | 2750 | nls_codepage); |
3757 | kfree(tcon->nativeFileSystem); | 2751 | |
3758 | tcon->nativeFileSystem = | 2752 | cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem)); |
3759 | kzalloc((4 * length) + 2, GFP_KERNEL); | 2753 | |
3760 | if (tcon->nativeFileSystem) { | ||
3761 | cifs_strfromUCS_le( | ||
3762 | tcon->nativeFileSystem, | ||
3763 | (__le16 *) bcc_ptr, | ||
3764 | length, nls_codepage); | ||
3765 | cFYI(1, ("nativeFileSystem=%s", | ||
3766 | tcon->nativeFileSystem)); | ||
3767 | } | ||
3768 | } | ||
3769 | /* else do not bother copying these information fields*/ | ||
3770 | } else { | ||
3771 | length = strnlen(bcc_ptr, 1024); | ||
3772 | if ((bcc_ptr + length) - | ||
3773 | pByteArea(smb_buffer_response) <= | ||
3774 | BCC(smb_buffer_response)) { | ||
3775 | kfree(tcon->nativeFileSystem); | ||
3776 | tcon->nativeFileSystem = | ||
3777 | kzalloc(length + 1, GFP_KERNEL); | ||
3778 | if (tcon->nativeFileSystem) | ||
3779 | strncpy(tcon->nativeFileSystem, bcc_ptr, | ||
3780 | length); | ||
3781 | } | ||
3782 | /* else do not bother copying these information fields*/ | ||
3783 | } | ||
3784 | if ((smb_buffer_response->WordCount == 3) || | 2754 | if ((smb_buffer_response->WordCount == 3) || |
3785 | (smb_buffer_response->WordCount == 7)) | 2755 | (smb_buffer_response->WordCount == 7)) |
3786 | /* field is in same location */ | 2756 | /* field is in same location */ |
@@ -3819,8 +2789,6 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
3819 | struct nls_table *nls_info) | 2789 | struct nls_table *nls_info) |
3820 | { | 2790 | { |
3821 | int rc = 0; | 2791 | int rc = 0; |
3822 | char ntlm_session_key[CIFS_SESS_KEY_SIZE]; | ||
3823 | bool ntlmv2_flag = false; | ||
3824 | int first_time = 0; | 2792 | int first_time = 0; |
3825 | struct TCP_Server_Info *server = pSesInfo->server; | 2793 | struct TCP_Server_Info *server = pSesInfo->server; |
3826 | 2794 | ||
@@ -3852,83 +2820,19 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
3852 | pSesInfo->capabilities = server->capabilities; | 2820 | pSesInfo->capabilities = server->capabilities; |
3853 | if (linuxExtEnabled == 0) | 2821 | if (linuxExtEnabled == 0) |
3854 | pSesInfo->capabilities &= (~CAP_UNIX); | 2822 | pSesInfo->capabilities &= (~CAP_UNIX); |
3855 | /* pSesInfo->sequence_number = 0;*/ | 2823 | |
3856 | cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", | 2824 | cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", |
3857 | server->secMode, server->capabilities, server->timeAdj)); | 2825 | server->secMode, server->capabilities, server->timeAdj)); |
3858 | 2826 | ||
3859 | if (experimEnabled < 2) | 2827 | rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); |
3860 | rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); | ||
3861 | else if (extended_security | ||
3862 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) | ||
3863 | && (server->secType == NTLMSSP)) { | ||
3864 | rc = -EOPNOTSUPP; | ||
3865 | } else if (extended_security | ||
3866 | && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY) | ||
3867 | && (server->secType == RawNTLMSSP)) { | ||
3868 | cFYI(1, ("NTLMSSP sesssetup")); | ||
3869 | rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag, | ||
3870 | nls_info); | ||
3871 | if (!rc) { | ||
3872 | if (ntlmv2_flag) { | ||
3873 | char *v2_response; | ||
3874 | cFYI(1, ("more secure NTLM ver2 hash")); | ||
3875 | if (CalcNTLMv2_partial_mac_key(pSesInfo, | ||
3876 | nls_info)) { | ||
3877 | rc = -ENOMEM; | ||
3878 | goto ss_err_exit; | ||
3879 | } else | ||
3880 | v2_response = kmalloc(16 + 64 /* blob*/, | ||
3881 | GFP_KERNEL); | ||
3882 | if (v2_response) { | ||
3883 | CalcNTLMv2_response(pSesInfo, | ||
3884 | v2_response); | ||
3885 | /* if (first_time) | ||
3886 | cifs_calculate_ntlmv2_mac_key */ | ||
3887 | kfree(v2_response); | ||
3888 | /* BB Put dummy sig in SessSetup PDU? */ | ||
3889 | } else { | ||
3890 | rc = -ENOMEM; | ||
3891 | goto ss_err_exit; | ||
3892 | } | ||
3893 | |||
3894 | } else { | ||
3895 | SMBNTencrypt(pSesInfo->password, | ||
3896 | server->cryptKey, | ||
3897 | ntlm_session_key); | ||
3898 | |||
3899 | if (first_time) | ||
3900 | cifs_calculate_mac_key( | ||
3901 | &server->mac_signing_key, | ||
3902 | ntlm_session_key, | ||
3903 | pSesInfo->password); | ||
3904 | } | ||
3905 | /* for better security the weaker lanman hash not sent | ||
3906 | in AuthSessSetup so we no longer calculate it */ | ||
3907 | |||
3908 | rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo, | ||
3909 | ntlm_session_key, | ||
3910 | ntlmv2_flag, | ||
3911 | nls_info); | ||
3912 | } | ||
3913 | } else { /* old style NTLM 0.12 session setup */ | ||
3914 | SMBNTencrypt(pSesInfo->password, server->cryptKey, | ||
3915 | ntlm_session_key); | ||
3916 | |||
3917 | if (first_time) | ||
3918 | cifs_calculate_mac_key(&server->mac_signing_key, | ||
3919 | ntlm_session_key, | ||
3920 | pSesInfo->password); | ||
3921 | |||
3922 | rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info); | ||
3923 | } | ||
3924 | if (rc) { | 2828 | if (rc) { |
3925 | cERROR(1, ("Send error in SessSetup = %d", rc)); | 2829 | cERROR(1, ("Send error in SessSetup = %d", rc)); |
3926 | } else { | 2830 | } else { |
3927 | cFYI(1, ("CIFS Session Established successfully")); | 2831 | cFYI(1, ("CIFS Session Established successfully")); |
3928 | spin_lock(&GlobalMid_Lock); | 2832 | spin_lock(&GlobalMid_Lock); |
3929 | pSesInfo->status = CifsGood; | 2833 | pSesInfo->status = CifsGood; |
3930 | pSesInfo->need_reconnect = false; | 2834 | pSesInfo->need_reconnect = false; |
3931 | spin_unlock(&GlobalMid_Lock); | 2835 | spin_unlock(&GlobalMid_Lock); |
3932 | } | 2836 | } |
3933 | 2837 | ||
3934 | ss_err_exit: | 2838 | ss_err_exit: |