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 #include "net/ntlm/ntlm_client.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <string.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_math.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/ntlm/ntlm.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/ntlm/ntlm_buffer_reader.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/ntlm/ntlm_buffer_writer.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/ntlm/ntlm_constants.h"
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker namespace net::ntlm {
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace {
22*6777b538SAndroid Build Coastguard Worker // Parses the challenge message and returns the |challenge_flags| and
23*6777b538SAndroid Build Coastguard Worker // |server_challenge| into the supplied buffer.
ParseChallengeMessage(base::span<const uint8_t> challenge_message,NegotiateFlags * challenge_flags,base::span<uint8_t,kChallengeLen> server_challenge)24*6777b538SAndroid Build Coastguard Worker bool ParseChallengeMessage(
25*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> challenge_message,
26*6777b538SAndroid Build Coastguard Worker NegotiateFlags* challenge_flags,
27*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kChallengeLen> server_challenge) {
28*6777b538SAndroid Build Coastguard Worker NtlmBufferReader challenge_reader(challenge_message);
29*6777b538SAndroid Build Coastguard Worker
30*6777b538SAndroid Build Coastguard Worker return challenge_reader.MatchMessageHeader(MessageType::kChallenge) &&
31*6777b538SAndroid Build Coastguard Worker challenge_reader.SkipSecurityBufferWithValidation() &&
32*6777b538SAndroid Build Coastguard Worker challenge_reader.ReadFlags(challenge_flags) &&
33*6777b538SAndroid Build Coastguard Worker challenge_reader.ReadBytes(server_challenge);
34*6777b538SAndroid Build Coastguard Worker }
35*6777b538SAndroid Build Coastguard Worker
36*6777b538SAndroid Build Coastguard Worker // Parses the challenge message and extracts the information necessary to
37*6777b538SAndroid Build Coastguard Worker // make an NTLMv2 response.
ParseChallengeMessageV2(base::span<const uint8_t> challenge_message,NegotiateFlags * challenge_flags,base::span<uint8_t,kChallengeLen> server_challenge,std::vector<AvPair> * av_pairs)38*6777b538SAndroid Build Coastguard Worker bool ParseChallengeMessageV2(
39*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> challenge_message,
40*6777b538SAndroid Build Coastguard Worker NegotiateFlags* challenge_flags,
41*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kChallengeLen> server_challenge,
42*6777b538SAndroid Build Coastguard Worker std::vector<AvPair>* av_pairs) {
43*6777b538SAndroid Build Coastguard Worker NtlmBufferReader challenge_reader(challenge_message);
44*6777b538SAndroid Build Coastguard Worker
45*6777b538SAndroid Build Coastguard Worker return challenge_reader.MatchMessageHeader(MessageType::kChallenge) &&
46*6777b538SAndroid Build Coastguard Worker challenge_reader.SkipSecurityBufferWithValidation() &&
47*6777b538SAndroid Build Coastguard Worker challenge_reader.ReadFlags(challenge_flags) &&
48*6777b538SAndroid Build Coastguard Worker challenge_reader.ReadBytes(server_challenge) &&
49*6777b538SAndroid Build Coastguard Worker challenge_reader.SkipBytes(8) &&
50*6777b538SAndroid Build Coastguard Worker // challenge_reader.ReadTargetInfoPayload(av_pairs);
51*6777b538SAndroid Build Coastguard Worker (((*challenge_flags & NegotiateFlags::kTargetInfo) ==
52*6777b538SAndroid Build Coastguard Worker NegotiateFlags::kTargetInfo)
53*6777b538SAndroid Build Coastguard Worker ? challenge_reader.ReadTargetInfoPayload(av_pairs)
54*6777b538SAndroid Build Coastguard Worker : true);
55*6777b538SAndroid Build Coastguard Worker }
56*6777b538SAndroid Build Coastguard Worker
WriteAuthenticateMessage(NtlmBufferWriter * authenticate_writer,SecurityBuffer lm_payload,SecurityBuffer ntlm_payload,SecurityBuffer domain_payload,SecurityBuffer username_payload,SecurityBuffer hostname_payload,SecurityBuffer session_key_payload,NegotiateFlags authenticate_flags)57*6777b538SAndroid Build Coastguard Worker bool WriteAuthenticateMessage(NtlmBufferWriter* authenticate_writer,
58*6777b538SAndroid Build Coastguard Worker SecurityBuffer lm_payload,
59*6777b538SAndroid Build Coastguard Worker SecurityBuffer ntlm_payload,
60*6777b538SAndroid Build Coastguard Worker SecurityBuffer domain_payload,
61*6777b538SAndroid Build Coastguard Worker SecurityBuffer username_payload,
62*6777b538SAndroid Build Coastguard Worker SecurityBuffer hostname_payload,
63*6777b538SAndroid Build Coastguard Worker SecurityBuffer session_key_payload,
64*6777b538SAndroid Build Coastguard Worker NegotiateFlags authenticate_flags) {
65*6777b538SAndroid Build Coastguard Worker return authenticate_writer->WriteMessageHeader(MessageType::kAuthenticate) &&
66*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteSecurityBuffer(lm_payload) &&
67*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteSecurityBuffer(ntlm_payload) &&
68*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteSecurityBuffer(domain_payload) &&
69*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteSecurityBuffer(username_payload) &&
70*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteSecurityBuffer(hostname_payload) &&
71*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteSecurityBuffer(session_key_payload) &&
72*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteFlags(authenticate_flags);
73*6777b538SAndroid Build Coastguard Worker }
74*6777b538SAndroid Build Coastguard Worker
75*6777b538SAndroid Build Coastguard Worker // Writes the NTLMv1 LM Response and NTLM Response.
WriteResponsePayloads(NtlmBufferWriter * authenticate_writer,base::span<const uint8_t,kResponseLenV1> lm_response,base::span<const uint8_t,kResponseLenV1> ntlm_response)76*6777b538SAndroid Build Coastguard Worker bool WriteResponsePayloads(
77*6777b538SAndroid Build Coastguard Worker NtlmBufferWriter* authenticate_writer,
78*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kResponseLenV1> lm_response,
79*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kResponseLenV1> ntlm_response) {
80*6777b538SAndroid Build Coastguard Worker return authenticate_writer->WriteBytes(lm_response) &&
81*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteBytes(ntlm_response);
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker
84*6777b538SAndroid Build Coastguard Worker // Writes the |lm_response| and writes the NTLMv2 response by concatenating
85*6777b538SAndroid Build Coastguard Worker // |v2_proof|, |v2_proof_input|, |updated_target_info| and 4 zero bytes.
WriteResponsePayloadsV2(NtlmBufferWriter * authenticate_writer,base::span<const uint8_t,kResponseLenV1> lm_response,base::span<const uint8_t,kNtlmProofLenV2> v2_proof,base::span<const uint8_t> v2_proof_input,base::span<const uint8_t> updated_target_info)86*6777b538SAndroid Build Coastguard Worker bool WriteResponsePayloadsV2(
87*6777b538SAndroid Build Coastguard Worker NtlmBufferWriter* authenticate_writer,
88*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kResponseLenV1> lm_response,
89*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kNtlmProofLenV2> v2_proof,
90*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> v2_proof_input,
91*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> updated_target_info) {
92*6777b538SAndroid Build Coastguard Worker return authenticate_writer->WriteBytes(lm_response) &&
93*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteBytes(v2_proof) &&
94*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteBytes(v2_proof_input) &&
95*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteBytes(updated_target_info) &&
96*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteUInt32(0);
97*6777b538SAndroid Build Coastguard Worker }
98*6777b538SAndroid Build Coastguard Worker
WriteStringPayloads(NtlmBufferWriter * authenticate_writer,bool is_unicode,const std::u16string & domain,const std::u16string & username,const std::string & hostname)99*6777b538SAndroid Build Coastguard Worker bool WriteStringPayloads(NtlmBufferWriter* authenticate_writer,
100*6777b538SAndroid Build Coastguard Worker bool is_unicode,
101*6777b538SAndroid Build Coastguard Worker const std::u16string& domain,
102*6777b538SAndroid Build Coastguard Worker const std::u16string& username,
103*6777b538SAndroid Build Coastguard Worker const std::string& hostname) {
104*6777b538SAndroid Build Coastguard Worker if (is_unicode) {
105*6777b538SAndroid Build Coastguard Worker return authenticate_writer->WriteUtf16String(domain) &&
106*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteUtf16String(username) &&
107*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteUtf8AsUtf16String(hostname);
108*6777b538SAndroid Build Coastguard Worker } else {
109*6777b538SAndroid Build Coastguard Worker return authenticate_writer->WriteUtf16AsUtf8String(domain) &&
110*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteUtf16AsUtf8String(username) &&
111*6777b538SAndroid Build Coastguard Worker authenticate_writer->WriteUtf8String(hostname);
112*6777b538SAndroid Build Coastguard Worker }
113*6777b538SAndroid Build Coastguard Worker }
114*6777b538SAndroid Build Coastguard Worker
115*6777b538SAndroid Build Coastguard Worker // Returns the size in bytes of a string16 depending whether unicode
116*6777b538SAndroid Build Coastguard Worker // was negotiated.
GetStringPayloadLength(const std::u16string & str,bool is_unicode)117*6777b538SAndroid Build Coastguard Worker size_t GetStringPayloadLength(const std::u16string& str, bool is_unicode) {
118*6777b538SAndroid Build Coastguard Worker if (is_unicode)
119*6777b538SAndroid Build Coastguard Worker return str.length() * 2;
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Worker // When |WriteUtf16AsUtf8String| is called with a |std::u16string|, the string
122*6777b538SAndroid Build Coastguard Worker // is converted to UTF8. Do the conversion to ensure that the character
123*6777b538SAndroid Build Coastguard Worker // count is correct.
124*6777b538SAndroid Build Coastguard Worker return base::UTF16ToUTF8(str).length();
125*6777b538SAndroid Build Coastguard Worker }
126*6777b538SAndroid Build Coastguard Worker
127*6777b538SAndroid Build Coastguard Worker // Returns the size in bytes of a std::string depending whether unicode
128*6777b538SAndroid Build Coastguard Worker // was negotiated.
GetStringPayloadLength(const std::string & str,bool is_unicode)129*6777b538SAndroid Build Coastguard Worker size_t GetStringPayloadLength(const std::string& str, bool is_unicode) {
130*6777b538SAndroid Build Coastguard Worker if (!is_unicode)
131*6777b538SAndroid Build Coastguard Worker return str.length();
132*6777b538SAndroid Build Coastguard Worker
133*6777b538SAndroid Build Coastguard Worker return base::UTF8ToUTF16(str).length() * 2;
134*6777b538SAndroid Build Coastguard Worker }
135*6777b538SAndroid Build Coastguard Worker
136*6777b538SAndroid Build Coastguard Worker // Sets |buffer| to point to |length| bytes from |offset| and updates |offset|
137*6777b538SAndroid Build Coastguard Worker // past those bytes. In case of overflow, returns false.
ComputeSecurityBuffer(uint32_t * offset,size_t length,SecurityBuffer * buffer)138*6777b538SAndroid Build Coastguard Worker bool ComputeSecurityBuffer(uint32_t* offset,
139*6777b538SAndroid Build Coastguard Worker size_t length,
140*6777b538SAndroid Build Coastguard Worker SecurityBuffer* buffer) {
141*6777b538SAndroid Build Coastguard Worker base::CheckedNumeric<uint16_t> length_checked = length;
142*6777b538SAndroid Build Coastguard Worker if (!length_checked.IsValid()) {
143*6777b538SAndroid Build Coastguard Worker return false;
144*6777b538SAndroid Build Coastguard Worker }
145*6777b538SAndroid Build Coastguard Worker base::CheckedNumeric<uint32_t> new_offset = *offset + length_checked;
146*6777b538SAndroid Build Coastguard Worker if (!new_offset.IsValid()) {
147*6777b538SAndroid Build Coastguard Worker return false;
148*6777b538SAndroid Build Coastguard Worker }
149*6777b538SAndroid Build Coastguard Worker buffer->offset = *offset;
150*6777b538SAndroid Build Coastguard Worker buffer->length = length_checked.ValueOrDie();
151*6777b538SAndroid Build Coastguard Worker *offset = new_offset.ValueOrDie();
152*6777b538SAndroid Build Coastguard Worker return true;
153*6777b538SAndroid Build Coastguard Worker }
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker } // namespace
156*6777b538SAndroid Build Coastguard Worker
NtlmClient(NtlmFeatures features)157*6777b538SAndroid Build Coastguard Worker NtlmClient::NtlmClient(NtlmFeatures features)
158*6777b538SAndroid Build Coastguard Worker : features_(features), negotiate_flags_(kNegotiateMessageFlags) {
159*6777b538SAndroid Build Coastguard Worker // Just generate the negotiate message once and hold on to it. It never
160*6777b538SAndroid Build Coastguard Worker // changes and in NTLMv2 it's used as an input to the Message Integrity
161*6777b538SAndroid Build Coastguard Worker // Check (MIC) in the Authenticate message.
162*6777b538SAndroid Build Coastguard Worker GenerateNegotiateMessage();
163*6777b538SAndroid Build Coastguard Worker }
164*6777b538SAndroid Build Coastguard Worker
165*6777b538SAndroid Build Coastguard Worker NtlmClient::~NtlmClient() = default;
166*6777b538SAndroid Build Coastguard Worker
GetNegotiateMessage() const167*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> NtlmClient::GetNegotiateMessage() const {
168*6777b538SAndroid Build Coastguard Worker return negotiate_message_;
169*6777b538SAndroid Build Coastguard Worker }
170*6777b538SAndroid Build Coastguard Worker
GenerateNegotiateMessage()171*6777b538SAndroid Build Coastguard Worker void NtlmClient::GenerateNegotiateMessage() {
172*6777b538SAndroid Build Coastguard Worker NtlmBufferWriter writer(kNegotiateMessageLen);
173*6777b538SAndroid Build Coastguard Worker bool result =
174*6777b538SAndroid Build Coastguard Worker writer.WriteMessageHeader(MessageType::kNegotiate) &&
175*6777b538SAndroid Build Coastguard Worker writer.WriteFlags(negotiate_flags_) &&
176*6777b538SAndroid Build Coastguard Worker writer.WriteSecurityBuffer(SecurityBuffer(kNegotiateMessageLen, 0)) &&
177*6777b538SAndroid Build Coastguard Worker writer.WriteSecurityBuffer(SecurityBuffer(kNegotiateMessageLen, 0)) &&
178*6777b538SAndroid Build Coastguard Worker writer.IsEndOfBuffer();
179*6777b538SAndroid Build Coastguard Worker
180*6777b538SAndroid Build Coastguard Worker DCHECK(result);
181*6777b538SAndroid Build Coastguard Worker
182*6777b538SAndroid Build Coastguard Worker negotiate_message_ = writer.Pass();
183*6777b538SAndroid Build Coastguard Worker }
184*6777b538SAndroid Build Coastguard Worker
GenerateAuthenticateMessage(const std::u16string & domain,const std::u16string & username,const std::u16string & password,const std::string & hostname,const std::string & channel_bindings,const std::string & spn,uint64_t client_time,base::span<const uint8_t,kChallengeLen> client_challenge,base::span<const uint8_t> server_challenge_message) const185*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> NtlmClient::GenerateAuthenticateMessage(
186*6777b538SAndroid Build Coastguard Worker const std::u16string& domain,
187*6777b538SAndroid Build Coastguard Worker const std::u16string& username,
188*6777b538SAndroid Build Coastguard Worker const std::u16string& password,
189*6777b538SAndroid Build Coastguard Worker const std::string& hostname,
190*6777b538SAndroid Build Coastguard Worker const std::string& channel_bindings,
191*6777b538SAndroid Build Coastguard Worker const std::string& spn,
192*6777b538SAndroid Build Coastguard Worker uint64_t client_time,
193*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t, kChallengeLen> client_challenge,
194*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> server_challenge_message) const {
195*6777b538SAndroid Build Coastguard Worker // Limit the size of strings that are accepted. As an absolute limit any
196*6777b538SAndroid Build Coastguard Worker // field represented by a |SecurityBuffer| or |AvPair| must be less than
197*6777b538SAndroid Build Coastguard Worker // UINT16_MAX bytes long. The strings are restricted to the maximum sizes
198*6777b538SAndroid Build Coastguard Worker // without regard to encoding. As such this isn't intended to restrict all
199*6777b538SAndroid Build Coastguard Worker // invalid inputs, only to allow all possible valid inputs.
200*6777b538SAndroid Build Coastguard Worker //
201*6777b538SAndroid Build Coastguard Worker // |domain| and |hostname| can be no longer than 255 characters.
202*6777b538SAndroid Build Coastguard Worker // |username| can be no longer than 104 characters. See [1].
203*6777b538SAndroid Build Coastguard Worker // |password| can be no longer than 256 characters. See [2].
204*6777b538SAndroid Build Coastguard Worker //
205*6777b538SAndroid Build Coastguard Worker // [1] - https://technet.microsoft.com/en-us/library/bb726984.aspx
206*6777b538SAndroid Build Coastguard Worker // [2] - https://technet.microsoft.com/en-us/library/cc512606.aspx
207*6777b538SAndroid Build Coastguard Worker if (hostname.length() > kMaxFqdnLen || domain.length() > kMaxFqdnLen ||
208*6777b538SAndroid Build Coastguard Worker username.length() > kMaxUsernameLen ||
209*6777b538SAndroid Build Coastguard Worker password.length() > kMaxPasswordLen) {
210*6777b538SAndroid Build Coastguard Worker return {};
211*6777b538SAndroid Build Coastguard Worker }
212*6777b538SAndroid Build Coastguard Worker
213*6777b538SAndroid Build Coastguard Worker NegotiateFlags challenge_flags;
214*6777b538SAndroid Build Coastguard Worker uint8_t server_challenge[kChallengeLen];
215*6777b538SAndroid Build Coastguard Worker uint8_t lm_response[kResponseLenV1];
216*6777b538SAndroid Build Coastguard Worker uint8_t ntlm_response[kResponseLenV1];
217*6777b538SAndroid Build Coastguard Worker
218*6777b538SAndroid Build Coastguard Worker // Response fields only for NTLMv2
219*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> updated_target_info;
220*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> v2_proof_input;
221*6777b538SAndroid Build Coastguard Worker uint8_t v2_proof[kNtlmProofLenV2];
222*6777b538SAndroid Build Coastguard Worker uint8_t v2_session_key[kSessionKeyLenV2];
223*6777b538SAndroid Build Coastguard Worker
224*6777b538SAndroid Build Coastguard Worker if (IsNtlmV2()) {
225*6777b538SAndroid Build Coastguard Worker std::vector<AvPair> av_pairs;
226*6777b538SAndroid Build Coastguard Worker if (!ParseChallengeMessageV2(server_challenge_message, &challenge_flags,
227*6777b538SAndroid Build Coastguard Worker server_challenge, &av_pairs)) {
228*6777b538SAndroid Build Coastguard Worker return {};
229*6777b538SAndroid Build Coastguard Worker }
230*6777b538SAndroid Build Coastguard Worker
231*6777b538SAndroid Build Coastguard Worker uint64_t timestamp;
232*6777b538SAndroid Build Coastguard Worker updated_target_info =
233*6777b538SAndroid Build Coastguard Worker GenerateUpdatedTargetInfo(IsMicEnabled(), IsEpaEnabled(),
234*6777b538SAndroid Build Coastguard Worker channel_bindings, spn, av_pairs, ×tamp);
235*6777b538SAndroid Build Coastguard Worker
236*6777b538SAndroid Build Coastguard Worker memset(lm_response, 0, kResponseLenV1);
237*6777b538SAndroid Build Coastguard Worker if (timestamp == UINT64_MAX) {
238*6777b538SAndroid Build Coastguard Worker // If the server didn't send a time, then use the clients time.
239*6777b538SAndroid Build Coastguard Worker timestamp = client_time;
240*6777b538SAndroid Build Coastguard Worker }
241*6777b538SAndroid Build Coastguard Worker
242*6777b538SAndroid Build Coastguard Worker uint8_t v2_hash[kNtlmHashLen];
243*6777b538SAndroid Build Coastguard Worker GenerateNtlmHashV2(domain, username, password, v2_hash);
244*6777b538SAndroid Build Coastguard Worker v2_proof_input = GenerateProofInputV2(timestamp, client_challenge);
245*6777b538SAndroid Build Coastguard Worker GenerateNtlmProofV2(v2_hash, server_challenge,
246*6777b538SAndroid Build Coastguard Worker base::make_span<kProofInputLenV2>(v2_proof_input),
247*6777b538SAndroid Build Coastguard Worker updated_target_info, v2_proof);
248*6777b538SAndroid Build Coastguard Worker GenerateSessionBaseKeyV2(v2_hash, v2_proof, v2_session_key);
249*6777b538SAndroid Build Coastguard Worker } else {
250*6777b538SAndroid Build Coastguard Worker if (!ParseChallengeMessage(server_challenge_message, &challenge_flags,
251*6777b538SAndroid Build Coastguard Worker server_challenge)) {
252*6777b538SAndroid Build Coastguard Worker return {};
253*6777b538SAndroid Build Coastguard Worker }
254*6777b538SAndroid Build Coastguard Worker
255*6777b538SAndroid Build Coastguard Worker // Calculate the responses for the authenticate message.
256*6777b538SAndroid Build Coastguard Worker GenerateResponsesV1WithSessionSecurity(password, server_challenge,
257*6777b538SAndroid Build Coastguard Worker client_challenge, lm_response,
258*6777b538SAndroid Build Coastguard Worker ntlm_response);
259*6777b538SAndroid Build Coastguard Worker }
260*6777b538SAndroid Build Coastguard Worker
261*6777b538SAndroid Build Coastguard Worker // Always use extended session security even if the server tries to downgrade.
262*6777b538SAndroid Build Coastguard Worker NegotiateFlags authenticate_flags = (challenge_flags & negotiate_flags_) |
263*6777b538SAndroid Build Coastguard Worker NegotiateFlags::kExtendedSessionSecurity;
264*6777b538SAndroid Build Coastguard Worker
265*6777b538SAndroid Build Coastguard Worker // Calculate all the payload lengths and offsets.
266*6777b538SAndroid Build Coastguard Worker bool is_unicode = (authenticate_flags & NegotiateFlags::kUnicode) ==
267*6777b538SAndroid Build Coastguard Worker NegotiateFlags::kUnicode;
268*6777b538SAndroid Build Coastguard Worker
269*6777b538SAndroid Build Coastguard Worker SecurityBuffer lm_info;
270*6777b538SAndroid Build Coastguard Worker SecurityBuffer ntlm_info;
271*6777b538SAndroid Build Coastguard Worker SecurityBuffer domain_info;
272*6777b538SAndroid Build Coastguard Worker SecurityBuffer username_info;
273*6777b538SAndroid Build Coastguard Worker SecurityBuffer hostname_info;
274*6777b538SAndroid Build Coastguard Worker SecurityBuffer session_key_info;
275*6777b538SAndroid Build Coastguard Worker size_t authenticate_message_len;
276*6777b538SAndroid Build Coastguard Worker
277*6777b538SAndroid Build Coastguard Worker if (!CalculatePayloadLayout(is_unicode, domain, username, hostname,
278*6777b538SAndroid Build Coastguard Worker updated_target_info.size(), &lm_info, &ntlm_info,
279*6777b538SAndroid Build Coastguard Worker &domain_info, &username_info, &hostname_info,
280*6777b538SAndroid Build Coastguard Worker &session_key_info, &authenticate_message_len)) {
281*6777b538SAndroid Build Coastguard Worker return {};
282*6777b538SAndroid Build Coastguard Worker }
283*6777b538SAndroid Build Coastguard Worker
284*6777b538SAndroid Build Coastguard Worker NtlmBufferWriter authenticate_writer(authenticate_message_len);
285*6777b538SAndroid Build Coastguard Worker bool writer_result = WriteAuthenticateMessage(
286*6777b538SAndroid Build Coastguard Worker &authenticate_writer, lm_info, ntlm_info, domain_info, username_info,
287*6777b538SAndroid Build Coastguard Worker hostname_info, session_key_info, authenticate_flags);
288*6777b538SAndroid Build Coastguard Worker DCHECK(writer_result);
289*6777b538SAndroid Build Coastguard Worker
290*6777b538SAndroid Build Coastguard Worker if (IsNtlmV2()) {
291*6777b538SAndroid Build Coastguard Worker // Write the optional (for V1) Version and MIC fields. Note that they
292*6777b538SAndroid Build Coastguard Worker // could also safely be sent in V1. However, the server should never try to
293*6777b538SAndroid Build Coastguard Worker // read them, because neither the version negotiate flag nor the
294*6777b538SAndroid Build Coastguard Worker // |TargetInfoAvFlags::kMicPresent| in the target info are set.
295*6777b538SAndroid Build Coastguard Worker //
296*6777b538SAndroid Build Coastguard Worker // Version is never supported so it is filled with zeros. MIC is a hash
297*6777b538SAndroid Build Coastguard Worker // calculated over all 3 messages while the MIC is set to zeros then
298*6777b538SAndroid Build Coastguard Worker // backfilled at the end if the MIC feature is enabled.
299*6777b538SAndroid Build Coastguard Worker writer_result = authenticate_writer.WriteZeros(kVersionFieldLen) &&
300*6777b538SAndroid Build Coastguard Worker authenticate_writer.WriteZeros(kMicLenV2);
301*6777b538SAndroid Build Coastguard Worker
302*6777b538SAndroid Build Coastguard Worker DCHECK(writer_result);
303*6777b538SAndroid Build Coastguard Worker }
304*6777b538SAndroid Build Coastguard Worker
305*6777b538SAndroid Build Coastguard Worker // Verify the location in the payload buffer.
306*6777b538SAndroid Build Coastguard Worker DCHECK(authenticate_writer.GetCursor() == GetAuthenticateHeaderLength());
307*6777b538SAndroid Build Coastguard Worker DCHECK(GetAuthenticateHeaderLength() == lm_info.offset);
308*6777b538SAndroid Build Coastguard Worker
309*6777b538SAndroid Build Coastguard Worker if (IsNtlmV2()) {
310*6777b538SAndroid Build Coastguard Worker // Write the response payloads for V2.
311*6777b538SAndroid Build Coastguard Worker writer_result =
312*6777b538SAndroid Build Coastguard Worker WriteResponsePayloadsV2(&authenticate_writer, lm_response, v2_proof,
313*6777b538SAndroid Build Coastguard Worker v2_proof_input, updated_target_info);
314*6777b538SAndroid Build Coastguard Worker } else {
315*6777b538SAndroid Build Coastguard Worker // Write the response payloads.
316*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(kResponseLenV1, lm_info.length);
317*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(kResponseLenV1, ntlm_info.length);
318*6777b538SAndroid Build Coastguard Worker writer_result =
319*6777b538SAndroid Build Coastguard Worker WriteResponsePayloads(&authenticate_writer, lm_response, ntlm_response);
320*6777b538SAndroid Build Coastguard Worker }
321*6777b538SAndroid Build Coastguard Worker
322*6777b538SAndroid Build Coastguard Worker DCHECK(writer_result);
323*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(authenticate_writer.GetCursor(), domain_info.offset);
324*6777b538SAndroid Build Coastguard Worker
325*6777b538SAndroid Build Coastguard Worker writer_result = WriteStringPayloads(&authenticate_writer, is_unicode, domain,
326*6777b538SAndroid Build Coastguard Worker username, hostname);
327*6777b538SAndroid Build Coastguard Worker DCHECK(writer_result);
328*6777b538SAndroid Build Coastguard Worker DCHECK(authenticate_writer.IsEndOfBuffer());
329*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(authenticate_message_len, authenticate_writer.GetLength());
330*6777b538SAndroid Build Coastguard Worker
331*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> auth_msg = authenticate_writer.Pass();
332*6777b538SAndroid Build Coastguard Worker
333*6777b538SAndroid Build Coastguard Worker // Backfill the MIC if enabled.
334*6777b538SAndroid Build Coastguard Worker if (IsMicEnabled()) {
335*6777b538SAndroid Build Coastguard Worker // The MIC has to be generated over all 3 completed messages with the MIC
336*6777b538SAndroid Build Coastguard Worker // set to zeros.
337*6777b538SAndroid Build Coastguard Worker DCHECK_LT(kMicOffsetV2 + kMicLenV2, authenticate_message_len);
338*6777b538SAndroid Build Coastguard Worker
339*6777b538SAndroid Build Coastguard Worker base::span<uint8_t, kMicLenV2> mic(
340*6777b538SAndroid Build Coastguard Worker const_cast<uint8_t*>(auth_msg.data()) + kMicOffsetV2, kMicLenV2);
341*6777b538SAndroid Build Coastguard Worker GenerateMicV2(v2_session_key, negotiate_message_, server_challenge_message,
342*6777b538SAndroid Build Coastguard Worker auth_msg, mic);
343*6777b538SAndroid Build Coastguard Worker }
344*6777b538SAndroid Build Coastguard Worker
345*6777b538SAndroid Build Coastguard Worker return auth_msg;
346*6777b538SAndroid Build Coastguard Worker }
347*6777b538SAndroid Build Coastguard Worker
CalculatePayloadLayout(bool is_unicode,const std::u16string & domain,const std::u16string & username,const std::string & hostname,size_t updated_target_info_len,SecurityBuffer * lm_info,SecurityBuffer * ntlm_info,SecurityBuffer * domain_info,SecurityBuffer * username_info,SecurityBuffer * hostname_info,SecurityBuffer * session_key_info,size_t * authenticate_message_len) const348*6777b538SAndroid Build Coastguard Worker bool NtlmClient::CalculatePayloadLayout(
349*6777b538SAndroid Build Coastguard Worker bool is_unicode,
350*6777b538SAndroid Build Coastguard Worker const std::u16string& domain,
351*6777b538SAndroid Build Coastguard Worker const std::u16string& username,
352*6777b538SAndroid Build Coastguard Worker const std::string& hostname,
353*6777b538SAndroid Build Coastguard Worker size_t updated_target_info_len,
354*6777b538SAndroid Build Coastguard Worker SecurityBuffer* lm_info,
355*6777b538SAndroid Build Coastguard Worker SecurityBuffer* ntlm_info,
356*6777b538SAndroid Build Coastguard Worker SecurityBuffer* domain_info,
357*6777b538SAndroid Build Coastguard Worker SecurityBuffer* username_info,
358*6777b538SAndroid Build Coastguard Worker SecurityBuffer* hostname_info,
359*6777b538SAndroid Build Coastguard Worker SecurityBuffer* session_key_info,
360*6777b538SAndroid Build Coastguard Worker size_t* authenticate_message_len) const {
361*6777b538SAndroid Build Coastguard Worker uint32_t offset = GetAuthenticateHeaderLength();
362*6777b538SAndroid Build Coastguard Worker if (!ComputeSecurityBuffer(&offset, 0, session_key_info) ||
363*6777b538SAndroid Build Coastguard Worker !ComputeSecurityBuffer(&offset, kResponseLenV1, lm_info) ||
364*6777b538SAndroid Build Coastguard Worker !ComputeSecurityBuffer(
365*6777b538SAndroid Build Coastguard Worker &offset, GetNtlmResponseLength(updated_target_info_len), ntlm_info) ||
366*6777b538SAndroid Build Coastguard Worker !ComputeSecurityBuffer(
367*6777b538SAndroid Build Coastguard Worker &offset, GetStringPayloadLength(domain, is_unicode), domain_info) ||
368*6777b538SAndroid Build Coastguard Worker !ComputeSecurityBuffer(&offset,
369*6777b538SAndroid Build Coastguard Worker GetStringPayloadLength(username, is_unicode),
370*6777b538SAndroid Build Coastguard Worker username_info) ||
371*6777b538SAndroid Build Coastguard Worker !ComputeSecurityBuffer(&offset,
372*6777b538SAndroid Build Coastguard Worker GetStringPayloadLength(hostname, is_unicode),
373*6777b538SAndroid Build Coastguard Worker hostname_info)) {
374*6777b538SAndroid Build Coastguard Worker return false;
375*6777b538SAndroid Build Coastguard Worker }
376*6777b538SAndroid Build Coastguard Worker
377*6777b538SAndroid Build Coastguard Worker *authenticate_message_len = offset;
378*6777b538SAndroid Build Coastguard Worker return true;
379*6777b538SAndroid Build Coastguard Worker }
380*6777b538SAndroid Build Coastguard Worker
GetAuthenticateHeaderLength() const381*6777b538SAndroid Build Coastguard Worker size_t NtlmClient::GetAuthenticateHeaderLength() const {
382*6777b538SAndroid Build Coastguard Worker if (IsNtlmV2()) {
383*6777b538SAndroid Build Coastguard Worker return kAuthenticateHeaderLenV2;
384*6777b538SAndroid Build Coastguard Worker }
385*6777b538SAndroid Build Coastguard Worker
386*6777b538SAndroid Build Coastguard Worker return kAuthenticateHeaderLenV1;
387*6777b538SAndroid Build Coastguard Worker }
388*6777b538SAndroid Build Coastguard Worker
GetNtlmResponseLength(size_t updated_target_info_len) const389*6777b538SAndroid Build Coastguard Worker size_t NtlmClient::GetNtlmResponseLength(size_t updated_target_info_len) const {
390*6777b538SAndroid Build Coastguard Worker if (IsNtlmV2()) {
391*6777b538SAndroid Build Coastguard Worker return kNtlmResponseHeaderLenV2 + updated_target_info_len + 4;
392*6777b538SAndroid Build Coastguard Worker }
393*6777b538SAndroid Build Coastguard Worker
394*6777b538SAndroid Build Coastguard Worker return kResponseLenV1;
395*6777b538SAndroid Build Coastguard Worker }
396*6777b538SAndroid Build Coastguard Worker
397*6777b538SAndroid Build Coastguard Worker } // namespace net::ntlm
398