aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/connect.c730
1 files changed, 0 insertions, 730 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 9dcdb0c707ea..3a934dd84225 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -2605,736 +2605,6 @@ out:
2605 return rc; 2605 return rc;
2606} 2606}
2607 2607
2608static int
2609CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
2610 struct cifsSesInfo *ses, bool *pNTLMv2_flag,
2611 const struct nls_table *nls_codepage)
2612{
2613 struct smb_hdr *smb_buffer;
2614 struct smb_hdr *smb_buffer_response;
2615 SESSION_SETUP_ANDX *pSMB;
2616 SESSION_SETUP_ANDX *pSMBr;
2617 char *bcc_ptr;
2618 char *domain;
2619 int rc = 0;
2620 int remaining_words = 0;
2621 int bytes_returned = 0;
2622 int len;
2623 int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
2624 PNEGOTIATE_MESSAGE SecurityBlob;
2625 PCHALLENGE_MESSAGE SecurityBlob2;
2626 __u32 negotiate_flags, capabilities;
2627 __u16 count;
2628
2629 cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
2630 if (ses == NULL)
2631 return -EINVAL;
2632 domain = ses->domainName;
2633 *pNTLMv2_flag = false;
2634 smb_buffer = cifs_buf_get();
2635 if (smb_buffer == NULL) {
2636 return -ENOMEM;
2637 }
2638 smb_buffer_response = smb_buffer;
2639 pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
2640 pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
2641
2642 /* send SMBsessionSetup here */
2643 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2644 NULL /* no tCon exists yet */ , 12 /* wct */ );
2645
2646 smb_buffer->Mid = GetNextMid(ses->server);
2647 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2648 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2649
2650 pSMB->req.AndXCommand = 0xFF;
2651 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2652 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2653
2654 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2655 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2656
2657 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2658 CAP_EXTENDED_SECURITY;
2659 if (ses->capabilities & CAP_UNICODE) {
2660 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2661 capabilities |= CAP_UNICODE;
2662 }
2663 if (ses->capabilities & CAP_STATUS32) {
2664 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2665 capabilities |= CAP_STATUS32;
2666 }
2667 if (ses->capabilities & CAP_DFS) {
2668 smb_buffer->Flags2 |= SMBFLG2_DFS;
2669 capabilities |= CAP_DFS;
2670 }
2671 pSMB->req.Capabilities = cpu_to_le32(capabilities);
2672
2673 bcc_ptr = (char *) &pSMB->req.SecurityBlob;
2674 SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
2675 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
2676 SecurityBlob->MessageType = NtLmNegotiate;
2677 negotiate_flags =
2678 NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
2679 NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
2680 NTLMSSP_NEGOTIATE_56 |
2681 /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
2682 if (sign_CIFS_PDUs)
2683 negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
2684 /* setup pointers to domain name and workstation name */
2685 bcc_ptr += SecurityBlobLength;
2686
2687 SecurityBlob->WorkstationName.BufferOffset = 0;
2688 SecurityBlob->WorkstationName.Length = 0;
2689 SecurityBlob->WorkstationName.MaximumLength = 0;
2690
2691 /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
2692 along with username on auth request (ie the response to challenge) */
2693 SecurityBlob->DomainName.BufferOffset = 0;
2694 SecurityBlob->DomainName.Length = 0;
2695 SecurityBlob->DomainName.MaximumLength = 0;
2696 if (ses->capabilities & CAP_UNICODE) {
2697 if ((long) bcc_ptr % 2) {
2698 *bcc_ptr = 0;
2699 bcc_ptr++;
2700 }
2701
2702 bytes_returned =
2703 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
2704 32, nls_codepage);
2705 bcc_ptr += 2 * bytes_returned;
2706 bytes_returned =
2707 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
2708 nls_codepage);
2709 bcc_ptr += 2 * bytes_returned;
2710 bcc_ptr += 2; /* null terminate Linux version */
2711 bytes_returned =
2712 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
2713 64, nls_codepage);
2714 bcc_ptr += 2 * bytes_returned;
2715 *(bcc_ptr + 1) = 0;
2716 *(bcc_ptr + 2) = 0;
2717 bcc_ptr += 2; /* null terminate network opsys string */
2718 *(bcc_ptr + 1) = 0;
2719 *(bcc_ptr + 2) = 0;
2720 bcc_ptr += 2; /* null domain */
2721 } else { /* ASCII */
2722 strcpy(bcc_ptr, "Linux version ");
2723 bcc_ptr += strlen("Linux version ");
2724 strcpy(bcc_ptr, utsname()->release);
2725 bcc_ptr += strlen(utsname()->release) + 1;
2726 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
2727 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
2728 bcc_ptr++; /* empty domain field */
2729 *bcc_ptr = 0;
2730 }
2731 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
2732 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
2733 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
2734 smb_buffer->smb_buf_length += count;
2735 pSMB->req.ByteCount = cpu_to_le16(count);
2736
2737 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
2738 &bytes_returned, CIFS_LONG_OP);
2739
2740 if (smb_buffer_response->Status.CifsError ==
2741 cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
2742 rc = 0;
2743
2744 if (rc) {
2745/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
2746 } else if ((smb_buffer_response->WordCount == 3)
2747 || (smb_buffer_response->WordCount == 4)) {
2748 __u16 action = le16_to_cpu(pSMBr->resp.Action);
2749 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
2750
2751 if (action & GUEST_LOGIN)
2752 cFYI(1, ("Guest login"));
2753 /* Do we want to set anything in SesInfo struct when guest login? */
2754
2755 bcc_ptr = pByteArea(smb_buffer_response);
2756 /* response can have either 3 or 4 word count - Samba sends 3 */
2757
2758 SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
2759 if (SecurityBlob2->MessageType != NtLmChallenge) {
2760 cFYI(1, ("Unexpected NTLMSSP message type received %d",
2761 SecurityBlob2->MessageType));
2762 } else if (ses) {
2763 ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
2764 cFYI(1, ("UID = %d", ses->Suid));
2765 if ((pSMBr->resp.hdr.WordCount == 3)
2766 || ((pSMBr->resp.hdr.WordCount == 4)
2767 && (blob_len <
2768 pSMBr->resp.ByteCount))) {
2769
2770 if (pSMBr->resp.hdr.WordCount == 4) {
2771 bcc_ptr += blob_len;
2772 cFYI(1, ("Security Blob Length %d",
2773 blob_len));
2774 }
2775
2776 cFYI(1, ("NTLMSSP Challenge rcvd"));
2777
2778 memcpy(ses->server->cryptKey,
2779 SecurityBlob2->Challenge,
2780 CIFS_CRYPTO_KEY_SIZE);
2781/* NTLMV2 flag is not for NTLMv2 password hash */
2782/* if (SecurityBlob2->NegotiateFlags &
2783 cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
2784 *pNTLMv2_flag = true; */ /* BB wrong */
2785
2786 if ((SecurityBlob2->NegotiateFlags &
2787 cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
2788 || (sign_CIFS_PDUs > 1))
2789 ses->server->secMode |=
2790 SECMODE_SIGN_REQUIRED;
2791 if ((SecurityBlob2->NegotiateFlags &
2792 cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
2793 ses->server->secMode |=
2794 SECMODE_SIGN_ENABLED;
2795
2796 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
2797 if ((long) (bcc_ptr) % 2) {
2798 remaining_words =
2799 (BCC(smb_buffer_response)
2800 - 1) / 2;
2801 /* Must word align unicode strings */
2802 bcc_ptr++;
2803 } else {
2804 remaining_words =
2805 BCC
2806 (smb_buffer_response) / 2;
2807 }
2808 len =
2809 UniStrnlen((wchar_t *) bcc_ptr,
2810 remaining_words - 1);
2811/* We look for obvious messed up bcc or strings in response so we do not go off
2812 the end since (at least) WIN2K and Windows XP have a major bug in not null
2813 terminating last Unicode string in response */
2814 kfree(ses->serverOS);
2815 ses->serverOS =
2816 kzalloc(2 * (len + 1), GFP_KERNEL);
2817 cifs_strfromUCS_le(ses->serverOS,
2818 (__le16 *)
2819 bcc_ptr, len,
2820 nls_codepage);
2821 bcc_ptr += 2 * (len + 1);
2822 remaining_words -= len + 1;
2823 ses->serverOS[2 * len] = 0;
2824 ses->serverOS[1 + (2 * len)] = 0;
2825 if (remaining_words > 0) {
2826 len = UniStrnlen((wchar_t *)
2827 bcc_ptr,
2828 remaining_words
2829 - 1);
2830 kfree(ses->serverNOS);
2831 ses->serverNOS =
2832 kzalloc(2 * (len + 1),
2833 GFP_KERNEL);
2834 cifs_strfromUCS_le(ses->
2835 serverNOS,
2836 (__le16 *)
2837 bcc_ptr,
2838 len,
2839 nls_codepage);
2840 bcc_ptr += 2 * (len + 1);
2841 ses->serverNOS[2 * len] = 0;
2842 ses->serverNOS[1 +
2843 (2 * len)] = 0;
2844 remaining_words -= len + 1;
2845 if (remaining_words > 0) {
2846 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
2847 /* last string not always null terminated
2848 (for e.g. for Windows XP & 2000) */
2849 kfree(ses->serverDomain);
2850 ses->serverDomain =
2851 kzalloc(2 *
2852 (len +
2853 1),
2854 GFP_KERNEL);
2855 cifs_strfromUCS_le
2856 (ses->serverDomain,
2857 (__le16 *)bcc_ptr,
2858 len, nls_codepage);
2859 bcc_ptr +=
2860 2 * (len + 1);
2861 ses->serverDomain[2*len]
2862 = 0;
2863 ses->serverDomain
2864 [1 + (2 * len)]
2865 = 0;
2866 } /* else no more room so create dummy domain string */
2867 else {
2868 kfree(ses->serverDomain);
2869 ses->serverDomain =
2870 kzalloc(2,
2871 GFP_KERNEL);
2872 }
2873 } else { /* no room so create dummy domain and NOS string */
2874 kfree(ses->serverDomain);
2875 ses->serverDomain =
2876 kzalloc(2, GFP_KERNEL);
2877 kfree(ses->serverNOS);
2878 ses->serverNOS =
2879 kzalloc(2, GFP_KERNEL);
2880 }
2881 } else { /* ASCII */
2882 len = strnlen(bcc_ptr, 1024);
2883 if (((long) bcc_ptr + len) - (long)
2884 pByteArea(smb_buffer_response)
2885 <= BCC(smb_buffer_response)) {
2886 kfree(ses->serverOS);
2887 ses->serverOS =
2888 kzalloc(len + 1,
2889 GFP_KERNEL);
2890 strncpy(ses->serverOS,
2891 bcc_ptr, len);
2892
2893 bcc_ptr += len;
2894 bcc_ptr[0] = 0; /* null terminate string */
2895 bcc_ptr++;
2896
2897 len = strnlen(bcc_ptr, 1024);
2898 kfree(ses->serverNOS);
2899 ses->serverNOS =
2900 kzalloc(len + 1,
2901 GFP_KERNEL);
2902 strncpy(ses->serverNOS, bcc_ptr, len);
2903 bcc_ptr += len;
2904 bcc_ptr[0] = 0;
2905 bcc_ptr++;
2906
2907 len = strnlen(bcc_ptr, 1024);
2908 kfree(ses->serverDomain);
2909 ses->serverDomain =
2910 kzalloc(len + 1,
2911 GFP_KERNEL);
2912 strncpy(ses->serverDomain,
2913 bcc_ptr, len);
2914 bcc_ptr += len;
2915 bcc_ptr[0] = 0;
2916 bcc_ptr++;
2917 } else
2918 cFYI(1,
2919 ("field of length %d "
2920 "extends beyond end of smb",
2921 len));
2922 }
2923 } else {
2924 cERROR(1, ("Security Blob Length extends beyond"
2925 " end of SMB"));
2926 }
2927 } else {
2928 cERROR(1, ("No session structure passed in."));
2929 }
2930 } else {
2931 cERROR(1, ("Invalid Word count %d:",
2932 smb_buffer_response->WordCount));
2933 rc = -EIO;
2934 }
2935
2936 cifs_buf_release(smb_buffer);
2937
2938 return rc;
2939}
2940
2941static int
2942CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
2943 char *ntlm_session_key, bool ntlmv2_flag,
2944 const struct nls_table *nls_codepage)
2945{
2946 struct smb_hdr *smb_buffer;
2947 struct smb_hdr *smb_buffer_response;
2948 SESSION_SETUP_ANDX *pSMB;
2949 SESSION_SETUP_ANDX *pSMBr;
2950 char *bcc_ptr;
2951 char *user;
2952 char *domain;
2953 int rc = 0;
2954 int remaining_words = 0;
2955 int bytes_returned = 0;
2956 int len;
2957 int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
2958 PAUTHENTICATE_MESSAGE SecurityBlob;
2959 __u32 negotiate_flags, capabilities;
2960 __u16 count;
2961
2962 cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
2963 if (ses == NULL)
2964 return -EINVAL;
2965 user = ses->userName;
2966 domain = ses->domainName;
2967 smb_buffer = cifs_buf_get();
2968 if (smb_buffer == NULL) {
2969 return -ENOMEM;
2970 }
2971 smb_buffer_response = smb_buffer;
2972 pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
2973 pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
2974
2975 /* send SMBsessionSetup here */
2976 header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
2977 NULL /* no tCon exists yet */ , 12 /* wct */ );
2978
2979 smb_buffer->Mid = GetNextMid(ses->server);
2980 pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
2981 pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
2982 pSMB->req.AndXCommand = 0xFF;
2983 pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
2984 pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
2985
2986 pSMB->req.hdr.Uid = ses->Suid;
2987
2988 if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
2989 smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
2990
2991 capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
2992 CAP_EXTENDED_SECURITY;
2993 if (ses->capabilities & CAP_UNICODE) {
2994 smb_buffer->Flags2 |= SMBFLG2_UNICODE;
2995 capabilities |= CAP_UNICODE;
2996 }
2997 if (ses->capabilities & CAP_STATUS32) {
2998 smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
2999 capabilities |= CAP_STATUS32;
3000 }
3001 if (ses->capabilities & CAP_DFS) {
3002 smb_buffer->Flags2 |= SMBFLG2_DFS;
3003 capabilities |= CAP_DFS;
3004 }
3005 pSMB->req.Capabilities = cpu_to_le32(capabilities);
3006
3007 bcc_ptr = (char *)&pSMB->req.SecurityBlob;
3008 SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
3009 strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
3010 SecurityBlob->MessageType = NtLmAuthenticate;
3011 bcc_ptr += SecurityBlobLength;
3012 negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
3013 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
3014 NTLMSSP_NEGOTIATE_56 | NTLMSSP_NEGOTIATE_128 |
3015 NTLMSSP_NEGOTIATE_EXTENDED_SEC;
3016 if (sign_CIFS_PDUs)
3017 negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
3018
3019/* setup pointers to domain name and workstation name */
3020
3021 SecurityBlob->WorkstationName.BufferOffset = 0;
3022 SecurityBlob->WorkstationName.Length = 0;
3023 SecurityBlob->WorkstationName.MaximumLength = 0;
3024 SecurityBlob->SessionKey.Length = 0;
3025 SecurityBlob->SessionKey.MaximumLength = 0;
3026 SecurityBlob->SessionKey.BufferOffset = 0;
3027
3028 SecurityBlob->LmChallengeResponse.Length = 0;
3029 SecurityBlob->LmChallengeResponse.MaximumLength = 0;
3030 SecurityBlob->LmChallengeResponse.BufferOffset = 0;
3031
3032 SecurityBlob->NtChallengeResponse.Length =
3033 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3034 SecurityBlob->NtChallengeResponse.MaximumLength =
3035 cpu_to_le16(CIFS_SESS_KEY_SIZE);
3036 memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
3037 SecurityBlob->NtChallengeResponse.BufferOffset =
3038 cpu_to_le32(SecurityBlobLength);
3039 SecurityBlobLength += CIFS_SESS_KEY_SIZE;
3040 bcc_ptr += CIFS_SESS_KEY_SIZE;
3041
3042 if (ses->capabilities & CAP_UNICODE) {
3043 if (domain == NULL) {
3044 SecurityBlob->DomainName.BufferOffset = 0;
3045 SecurityBlob->DomainName.Length = 0;
3046 SecurityBlob->DomainName.MaximumLength = 0;
3047 } else {
3048 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
3049 nls_codepage);
3050 ln *= 2;
3051 SecurityBlob->DomainName.MaximumLength =
3052 cpu_to_le16(ln);
3053 SecurityBlob->DomainName.BufferOffset =
3054 cpu_to_le32(SecurityBlobLength);
3055 bcc_ptr += ln;
3056 SecurityBlobLength += ln;
3057 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3058 }
3059 if (user == NULL) {
3060 SecurityBlob->UserName.BufferOffset = 0;
3061 SecurityBlob->UserName.Length = 0;
3062 SecurityBlob->UserName.MaximumLength = 0;
3063 } else {
3064 __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
3065 nls_codepage);
3066 ln *= 2;
3067 SecurityBlob->UserName.MaximumLength =
3068 cpu_to_le16(ln);
3069 SecurityBlob->UserName.BufferOffset =
3070 cpu_to_le32(SecurityBlobLength);
3071 bcc_ptr += ln;
3072 SecurityBlobLength += ln;
3073 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3074 }
3075
3076 /* SecurityBlob->WorkstationName.Length =
3077 cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
3078 SecurityBlob->WorkstationName.Length *= 2;
3079 SecurityBlob->WorkstationName.MaximumLength =
3080 cpu_to_le16(SecurityBlob->WorkstationName.Length);
3081 SecurityBlob->WorkstationName.BufferOffset =
3082 cpu_to_le32(SecurityBlobLength);
3083 bcc_ptr += SecurityBlob->WorkstationName.Length;
3084 SecurityBlobLength += SecurityBlob->WorkstationName.Length;
3085 SecurityBlob->WorkstationName.Length =
3086 cpu_to_le16(SecurityBlob->WorkstationName.Length); */
3087
3088 if ((long) bcc_ptr % 2) {
3089 *bcc_ptr = 0;
3090 bcc_ptr++;
3091 }
3092 bytes_returned =
3093 cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
3094 32, nls_codepage);
3095 bcc_ptr += 2 * bytes_returned;
3096 bytes_returned =
3097 cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
3098 nls_codepage);
3099 bcc_ptr += 2 * bytes_returned;
3100 bcc_ptr += 2; /* null term version string */
3101 bytes_returned =
3102 cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
3103 64, nls_codepage);
3104 bcc_ptr += 2 * bytes_returned;
3105 *(bcc_ptr + 1) = 0;
3106 *(bcc_ptr + 2) = 0;
3107 bcc_ptr += 2; /* null terminate network opsys string */
3108 *(bcc_ptr + 1) = 0;
3109 *(bcc_ptr + 2) = 0;
3110 bcc_ptr += 2; /* null domain */
3111 } else { /* ASCII */
3112 if (domain == NULL) {
3113 SecurityBlob->DomainName.BufferOffset = 0;
3114 SecurityBlob->DomainName.Length = 0;
3115 SecurityBlob->DomainName.MaximumLength = 0;
3116 } else {
3117 __u16 ln;
3118 negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
3119 strncpy(bcc_ptr, domain, 63);
3120 ln = strnlen(domain, 64);
3121 SecurityBlob->DomainName.MaximumLength =
3122 cpu_to_le16(ln);
3123 SecurityBlob->DomainName.BufferOffset =
3124 cpu_to_le32(SecurityBlobLength);
3125 bcc_ptr += ln;
3126 SecurityBlobLength += ln;
3127 SecurityBlob->DomainName.Length = cpu_to_le16(ln);
3128 }
3129 if (user == NULL) {
3130 SecurityBlob->UserName.BufferOffset = 0;
3131 SecurityBlob->UserName.Length = 0;
3132 SecurityBlob->UserName.MaximumLength = 0;
3133 } else {
3134 __u16 ln;
3135 strncpy(bcc_ptr, user, 63);
3136 ln = strnlen(user, 64);
3137 SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
3138 SecurityBlob->UserName.BufferOffset =
3139 cpu_to_le32(SecurityBlobLength);
3140 bcc_ptr += ln;
3141 SecurityBlobLength += ln;
3142 SecurityBlob->UserName.Length = cpu_to_le16(ln);
3143 }
3144 /* BB fill in our workstation name if known BB */
3145
3146 strcpy(bcc_ptr, "Linux version ");
3147 bcc_ptr += strlen("Linux version ");
3148 strcpy(bcc_ptr, utsname()->release);
3149 bcc_ptr += strlen(utsname()->release) + 1;
3150 strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
3151 bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
3152 bcc_ptr++; /* null domain */
3153 *bcc_ptr = 0;
3154 }
3155 SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
3156 pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
3157 count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
3158 smb_buffer->smb_buf_length += count;
3159 pSMB->req.ByteCount = cpu_to_le16(count);
3160
3161 rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
3162 &bytes_returned, CIFS_LONG_OP);
3163 if (rc) {
3164/* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
3165 } else if ((smb_buffer_response->WordCount == 3) ||
3166 (smb_buffer_response->WordCount == 4)) {
3167 __u16 action = le16_to_cpu(pSMBr->resp.Action);
3168 __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
3169 if (action & GUEST_LOGIN)
3170 cFYI(1, ("Guest login")); /* BB Should we set anything
3171 in SesInfo struct ? */
3172/* if (SecurityBlob2->MessageType != NtLm??) {
3173 cFYI("Unexpected message type on auth response is %d"));
3174 } */
3175
3176 if (ses) {
3177 cFYI(1,
3178 ("Check challenge UID %d vs auth response UID %d",
3179 ses->Suid, smb_buffer_response->Uid));
3180 /* UID left in wire format */
3181 ses->Suid = smb_buffer_response->Uid;
3182 bcc_ptr = pByteArea(smb_buffer_response);
3183 /* response can have either 3 or 4 word count - Samba sends 3 */
3184 if ((pSMBr->resp.hdr.WordCount == 3)
3185 || ((pSMBr->resp.hdr.WordCount == 4)
3186 && (blob_len <
3187 pSMBr->resp.ByteCount))) {
3188 if (pSMBr->resp.hdr.WordCount == 4) {
3189 bcc_ptr +=
3190 blob_len;
3191 cFYI(1,
3192 ("Security Blob Length %d ",
3193 blob_len));
3194 }
3195
3196 cFYI(1,
3197 ("NTLMSSP response to Authenticate "));
3198
3199 if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
3200 if ((long) (bcc_ptr) % 2) {
3201 remaining_words =
3202 (BCC(smb_buffer_response)
3203 - 1) / 2;
3204 bcc_ptr++; /* Unicode strings must be word aligned */
3205 } else {
3206 remaining_words = BCC(smb_buffer_response) / 2;
3207 }
3208 len = UniStrnlen((wchar_t *) bcc_ptr,
3209 remaining_words - 1);
3210/* We look for obvious messed up bcc or strings in response so we do not go off
3211 the end since (at least) WIN2K and Windows XP have a major bug in not null
3212 terminating last Unicode string in response */
3213 kfree(ses->serverOS);
3214 ses->serverOS =
3215 kzalloc(2 * (len + 1), GFP_KERNEL);
3216 cifs_strfromUCS_le(ses->serverOS,
3217 (__le16 *)
3218 bcc_ptr, len,
3219 nls_codepage);
3220 bcc_ptr += 2 * (len + 1);
3221 remaining_words -= len + 1;
3222 ses->serverOS[2 * len] = 0;
3223 ses->serverOS[1 + (2 * len)] = 0;
3224 if (remaining_words > 0) {
3225 len = UniStrnlen((wchar_t *)
3226 bcc_ptr,
3227 remaining_words
3228 - 1);
3229 kfree(ses->serverNOS);
3230 ses->serverNOS =
3231 kzalloc(2 * (len + 1),
3232 GFP_KERNEL);
3233 cifs_strfromUCS_le(ses->
3234 serverNOS,
3235 (__le16 *)
3236 bcc_ptr,
3237 len,
3238 nls_codepage);
3239 bcc_ptr += 2 * (len + 1);
3240 ses->serverNOS[2 * len] = 0;
3241 ses->serverNOS[1+(2*len)] = 0;
3242 remaining_words -= len + 1;
3243 if (remaining_words > 0) {
3244 len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
3245 /* last string not always null terminated (e.g. for Windows XP & 2000) */
3246 kfree(ses->serverDomain);
3247 ses->serverDomain =
3248 kzalloc(2 *
3249 (len +
3250 1),
3251 GFP_KERNEL);
3252 cifs_strfromUCS_le
3253 (ses->
3254 serverDomain,
3255 (__le16 *)
3256 bcc_ptr, len,
3257 nls_codepage);
3258 bcc_ptr +=
3259 2 * (len + 1);
3260 ses->
3261 serverDomain[2
3262 * len]
3263 = 0;
3264 ses->
3265 serverDomain[1
3266 +
3267 (2
3268 *
3269 len)]
3270 = 0;
3271 } /* else no more room so create dummy domain string */
3272 else {
3273 kfree(ses->serverDomain);
3274 ses->serverDomain = kzalloc(2,GFP_KERNEL);
3275 }
3276 } else { /* no room so create dummy domain and NOS string */
3277 kfree(ses->serverDomain);
3278 ses->serverDomain = kzalloc(2, GFP_KERNEL);
3279 kfree(ses->serverNOS);
3280 ses->serverNOS = kzalloc(2, GFP_KERNEL);
3281 }
3282 } else { /* ASCII */
3283 len = strnlen(bcc_ptr, 1024);
3284 if (((long) bcc_ptr + len) -
3285 (long) pByteArea(smb_buffer_response)
3286 <= BCC(smb_buffer_response)) {
3287 kfree(ses->serverOS);
3288 ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
3289 strncpy(ses->serverOS,bcc_ptr, len);
3290
3291 bcc_ptr += len;
3292 bcc_ptr[0] = 0; /* null terminate the string */
3293 bcc_ptr++;
3294
3295 len = strnlen(bcc_ptr, 1024);
3296 kfree(ses->serverNOS);
3297 ses->serverNOS = kzalloc(len+1,
3298 GFP_KERNEL);
3299 strncpy(ses->serverNOS,
3300 bcc_ptr, len);
3301 bcc_ptr += len;
3302 bcc_ptr[0] = 0;
3303 bcc_ptr++;
3304
3305 len = strnlen(bcc_ptr, 1024);
3306 kfree(ses->serverDomain);
3307 ses->serverDomain =
3308 kzalloc(len+1,
3309 GFP_KERNEL);
3310 strncpy(ses->serverDomain,
3311 bcc_ptr, len);
3312 bcc_ptr += len;
3313 bcc_ptr[0] = 0;
3314 bcc_ptr++;
3315 } else
3316 cFYI(1, ("field of length %d "
3317 "extends beyond end of smb ",
3318 len));
3319 }
3320 } else {
3321 cERROR(1, ("Security Blob extends beyond end "
3322 "of SMB"));
3323 }
3324 } else {
3325 cERROR(1, ("No session structure passed in."));
3326 }
3327 } else {
3328 cERROR(1, ("Invalid Word count %d: ",
3329 smb_buffer_response->WordCount));
3330 rc = -EIO;
3331 }
3332
3333 cifs_buf_release(smb_buffer);
3334
3335 return rc;
3336}
3337
3338int 2608int
3339CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, 2609CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
3340 const char *tree, struct cifsTconInfo *tcon, 2610 const char *tree, struct cifsTconInfo *tcon,