1 // Copyright 2017 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol 6 // Specification version 28.0 [1], an unofficial NTLM reference [2], and a 7 // blog post describing Extended Protection for Authentication [3]. 8 // 9 // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx 10 // [2] http://davenport.sourceforge.net/ntlm.html 11 // [3] 12 // https://blogs.msdn.microsoft.com/openspecification/2013/03/26/ntlm-and-channel-binding-hash-aka-extended-protection-for-authentication/ 13 14 #ifndef NET_NTLM_NTLM_CLIENT_H_ 15 #define NET_NTLM_NTLM_CLIENT_H_ 16 17 #include <stddef.h> 18 #include <stdint.h> 19 20 #include <memory> 21 #include <string> 22 23 #include "base/check.h" 24 #include "base/containers/span.h" 25 #include "base/strings/string_piece.h" 26 #include "net/base/net_export.h" 27 #include "net/ntlm/ntlm_constants.h" 28 29 namespace net::ntlm { 30 31 // Provides an implementation of an NTLMv1 or NTLMv2 Client with support 32 // for MIC and EPA [1]. This implementation does not support the key exchange, 33 // signing or sealing feature as the NTLMSSP_NEGOTIATE_KEY_EXCH flag is never 34 // negotiated. 35 // 36 // [1] - 37 // https://support.microsoft.com/en-us/help/968389/extended-protection-for-authentication 38 class NET_EXPORT_PRIVATE NtlmClient { 39 public: 40 // Pass feature flags to enable/disable NTLMv2 and additional NTLMv2 41 // features such as Extended Protection for Authentication (EPA) and Message 42 // Integrity Check (MIC). 43 explicit NtlmClient(NtlmFeatures features); 44 45 NtlmClient(const NtlmClient&) = delete; 46 NtlmClient& operator=(const NtlmClient&) = delete; 47 48 ~NtlmClient(); 49 IsNtlmV2()50 bool IsNtlmV2() const { return features_.enable_NTLMv2; } 51 IsMicEnabled()52 bool IsMicEnabled() const { return IsNtlmV2() && features_.enable_MIC; } 53 IsEpaEnabled()54 bool IsEpaEnabled() const { return IsNtlmV2() && features_.enable_EPA; } 55 56 // Returns the Negotiate message. 57 std::vector<uint8_t> GetNegotiateMessage() const; 58 59 // Returns a the Authenticate message. If the method fails an empty vector 60 // is returned. 61 // 62 // |username| is treated case insensitively by NTLM however the mechanism 63 // to uppercase is not clearly defined. In this implementation the default 64 // locale is used. Additionally for names longer than 20 characters, the 65 // fully qualified name in the new '@' format must be used. 66 // eg. very_long_name@domain.com. Names shorter than 20 characters can 67 // optionally omit the '@domain.com' part. 68 // |hostname| can be a short NetBIOS name or an FQDN, however the server will 69 // only inspect this field if the default domain policy is to restrict NTLM. 70 // In this case the hostname will be compared to an allowlist stored in this 71 // group policy [1]. 72 // |channel_bindings| is a string supplied out of band (usually from a web 73 // browser) and is a (21+sizeof(hash)) byte ASCII string, where 'hash' is 74 // usually a SHA-256 of the servers certificate, but may be another hash 75 // algorithm. The format as defined by RFC 5929 Section 4 is shown below; 76 // 77 // [0-20] - "tls-server-end-point:" (Literal string) 78 // [21-(20+sizeof(hash)] - HASH(server_certificate) (Certificate hash) 79 // 80 // |spn| is a string supplied out of band (usually from a web browser) and 81 // is a Service Principal Name [2]. For NTLM over HTTP the value of this 82 // string will usually be "HTTP/<hostname>". 83 // |client_time| 64 bit Windows timestamp defined as the number of 84 // 100 nanosecond ticks since midnight Jan 01, 1601 (UTC). If the server does 85 // not send a timestamp, the client timestamp is used in the Proof Input 86 // instead. 87 // |server_challenge_message| is the full content of the challenge message 88 // sent by the server. 89 // 90 // [1] - https://technet.microsoft.com/en-us/library/jj852267(v=ws.11).aspx 91 std::vector<uint8_t> GenerateAuthenticateMessage( 92 const std::u16string& domain, 93 const std::u16string& username, 94 const std::u16string& password, 95 const std::string& hostname, 96 const std::string& channel_bindings, 97 const std::string& spn, 98 uint64_t client_time, 99 base::span<const uint8_t, kChallengeLen> client_challenge, 100 base::span<const uint8_t> server_challenge_message) const; 101 102 // Simplified method for NTLMv1 which does not require |channel_bindings|, 103 // |spn|, or |client_time|. See |GenerateAuthenticateMessage| for more 104 // details. GenerateAuthenticateMessageV1(const std::u16string & domain,const std::u16string & username,const std::u16string & password,const std::string & hostname,base::span<const uint8_t,8> client_challenge,base::span<const uint8_t> server_challenge_message)105 std::vector<uint8_t> GenerateAuthenticateMessageV1( 106 const std::u16string& domain, 107 const std::u16string& username, 108 const std::u16string& password, 109 const std::string& hostname, 110 base::span<const uint8_t, 8> client_challenge, 111 base::span<const uint8_t> server_challenge_message) const { 112 DCHECK(!IsNtlmV2()); 113 114 return GenerateAuthenticateMessage( 115 domain, username, password, hostname, std::string(), std::string(), 0, 116 client_challenge, server_challenge_message); 117 } 118 119 private: 120 // Returns the length of the Authenticate message based on the length of the 121 // variable length parts of the message and whether Unicode support was 122 // negotiated. 123 size_t CalculateAuthenticateMessageLength( 124 bool is_unicode, 125 const std::u16string& domain, 126 const std::u16string& username, 127 const std::string& hostname, 128 size_t updated_target_info_len) const; 129 130 bool CalculatePayloadLayout(bool is_unicode, 131 const std::u16string& domain, 132 const std::u16string& username, 133 const std::string& hostname, 134 size_t updated_target_info_len, 135 SecurityBuffer* lm_info, 136 SecurityBuffer* ntlm_info, 137 SecurityBuffer* domain_info, 138 SecurityBuffer* username_info, 139 SecurityBuffer* hostname_info, 140 SecurityBuffer* session_key_info, 141 size_t* authenticate_message_len) const; 142 143 // Returns the length of the header part of the Authenticate message. 144 size_t GetAuthenticateHeaderLength() const; 145 146 // Returns the length of the NTLM response. 147 size_t GetNtlmResponseLength(size_t updated_target_info_len) const; 148 149 // Generates the negotiate message (which is always the same) into 150 // |negotiate_message_|. 151 void GenerateNegotiateMessage(); 152 153 const NtlmFeatures features_; 154 NegotiateFlags negotiate_flags_; 155 std::vector<uint8_t> negotiate_message_; 156 }; 157 158 } // namespace net::ntlm 159 160 #endif // NET_NTLM_NTLM_CLIENT_H_ 161