diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/connect.c | 730 |
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 | ||
2608 | static int | ||
2609 | CIFSNTLMSSPNegotiateSessSetup(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 | |||
2941 | static int | ||
2942 | CIFSNTLMSSPAuthSessSetup(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 | |||
3338 | int | 2608 | int |
3339 | CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | 2609 | CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, |
3340 | const char *tree, struct cifsTconInfo *tcon, | 2610 | const char *tree, struct cifsTconInfo *tcon, |