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