xref: /aosp_15_r20/external/cronet/net/ntlm/ntlm_buffer_writer.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 #ifndef NET_NTLM_NTLM_BUFFER_WRITER_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_NTLM_NTLM_BUFFER_WRITER_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
9*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include <memory>
12*6777b538SAndroid Build Coastguard Worker #include <string>
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.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 // Supports various bounds checked low level buffer operations required by an
22*6777b538SAndroid Build Coastguard Worker // NTLM implementation.
23*6777b538SAndroid Build Coastguard Worker //
24*6777b538SAndroid Build Coastguard Worker // The class supports sequential write to an internally managed buffer. All
25*6777b538SAndroid Build Coastguard Worker // writes perform bounds checking to ensure enough space is remaining in the
26*6777b538SAndroid Build Coastguard Worker // buffer.
27*6777b538SAndroid Build Coastguard Worker //
28*6777b538SAndroid Build Coastguard Worker // The internal buffer is allocated in the constructor with size |buffer_len|
29*6777b538SAndroid Build Coastguard Worker // and owned by the class.
30*6777b538SAndroid Build Coastguard Worker //
31*6777b538SAndroid Build Coastguard Worker // Write* methods write the buffer at the current cursor position and perform
32*6777b538SAndroid Build Coastguard Worker // any necessary type conversion and provide the data in out params. After a
33*6777b538SAndroid Build Coastguard Worker // successful write the cursor position is advanced past the written field.
34*6777b538SAndroid Build Coastguard Worker //
35*6777b538SAndroid Build Coastguard Worker // Failed writes leave the internal cursor at the same position as before the
36*6777b538SAndroid Build Coastguard Worker // call.
37*6777b538SAndroid Build Coastguard Worker //
38*6777b538SAndroid Build Coastguard Worker // Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol
39*6777b538SAndroid Build Coastguard Worker // Specification version 28.0 [1]. Additional NTLM reference [2].
40*6777b538SAndroid Build Coastguard Worker //
41*6777b538SAndroid Build Coastguard Worker // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
42*6777b538SAndroid Build Coastguard Worker // [2] http://davenport.sourceforge.net/ntlm.html
43*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE NtlmBufferWriter {
44*6777b538SAndroid Build Coastguard Worker  public:
45*6777b538SAndroid Build Coastguard Worker   explicit NtlmBufferWriter(size_t buffer_len);
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker   NtlmBufferWriter(const NtlmBufferWriter&) = delete;
48*6777b538SAndroid Build Coastguard Worker   NtlmBufferWriter& operator=(const NtlmBufferWriter&) = delete;
49*6777b538SAndroid Build Coastguard Worker 
50*6777b538SAndroid Build Coastguard Worker   ~NtlmBufferWriter();
51*6777b538SAndroid Build Coastguard Worker 
GetLength()52*6777b538SAndroid Build Coastguard Worker   size_t GetLength() const { return buffer_.size(); }
GetCursor()53*6777b538SAndroid Build Coastguard Worker   size_t GetCursor() const { return cursor_; }
IsEndOfBuffer()54*6777b538SAndroid Build Coastguard Worker   bool IsEndOfBuffer() const { return cursor_ >= GetLength(); }
GetBuffer()55*6777b538SAndroid Build Coastguard Worker   base::span<const uint8_t> GetBuffer() const { return buffer_; }
Pass()56*6777b538SAndroid Build Coastguard Worker   std::vector<uint8_t> Pass() const { return std::move(buffer_); }
57*6777b538SAndroid Build Coastguard Worker 
58*6777b538SAndroid Build Coastguard Worker   // Returns true if there are |len| more bytes between the current cursor
59*6777b538SAndroid Build Coastguard Worker   // position and the end of the buffer.
60*6777b538SAndroid Build Coastguard Worker   bool CanWrite(size_t len) const;
61*6777b538SAndroid Build Coastguard Worker 
62*6777b538SAndroid Build Coastguard Worker   // Writes a 16 bit unsigned value (little endian). If there are not 16
63*6777b538SAndroid Build Coastguard Worker   // more bits available in the buffer, it returns false.
64*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteUInt16(uint16_t value);
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker   // Writes a 32 bit unsigned value (little endian). If there are not 32
67*6777b538SAndroid Build Coastguard Worker   // more bits available in the buffer, it returns false.
68*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteUInt32(uint32_t value);
69*6777b538SAndroid Build Coastguard Worker 
70*6777b538SAndroid Build Coastguard Worker   // Writes a 64 bit unsigned value (little endian). If there are not 64
71*6777b538SAndroid Build Coastguard Worker   // more bits available in the buffer, it returns false.
72*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteUInt64(uint64_t value);
73*6777b538SAndroid Build Coastguard Worker 
74*6777b538SAndroid Build Coastguard Worker   // Writes flags as a 32 bit unsigned value (little endian).
75*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteFlags(NegotiateFlags flags);
76*6777b538SAndroid Build Coastguard Worker 
77*6777b538SAndroid Build Coastguard Worker   // Writes the bytes from the |buffer|. If there are not enough
78*6777b538SAndroid Build Coastguard Worker   // bytes in the buffer, it returns false.
79*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteBytes(base::span<const uint8_t> buffer);
80*6777b538SAndroid Build Coastguard Worker 
81*6777b538SAndroid Build Coastguard Worker   // Writes |count| bytes of zeros to the buffer. If there are not |count|
82*6777b538SAndroid Build Coastguard Worker   // more bytes in available in the buffer, it returns false.
83*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteZeros(size_t count);
84*6777b538SAndroid Build Coastguard Worker 
85*6777b538SAndroid Build Coastguard Worker   // A security buffer is an 8 byte structure that defines the offset and
86*6777b538SAndroid Build Coastguard Worker   // length of a payload (string, struct, or byte array) that appears after
87*6777b538SAndroid Build Coastguard Worker   // the fixed part of the message.
88*6777b538SAndroid Build Coastguard Worker   //
89*6777b538SAndroid Build Coastguard Worker   // The structure in the NTLM message is (little endian fields):
90*6777b538SAndroid Build Coastguard Worker   //     uint16 - |length| Length of payload
91*6777b538SAndroid Build Coastguard Worker   //     uint16 - Allocation (ignored and always set to |length|)
92*6777b538SAndroid Build Coastguard Worker   //     uint32 - |offset| Offset from start of message
93*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteSecurityBuffer(SecurityBuffer sec_buf);
94*6777b538SAndroid Build Coastguard Worker 
95*6777b538SAndroid Build Coastguard Worker   // Writes an AvPair header. See [MS-NLMP] Section 2.2.2.1.
96*6777b538SAndroid Build Coastguard Worker   //
97*6777b538SAndroid Build Coastguard Worker   // The header has the following structure:
98*6777b538SAndroid Build Coastguard Worker   //    uint16 - |avid| The identifier of the following payload.
99*6777b538SAndroid Build Coastguard Worker   //    uint16 - |avlen| The length of the following payload.
100*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteAvPairHeader(TargetInfoAvId avid, uint16_t avlen);
101*6777b538SAndroid Build Coastguard Worker 
102*6777b538SAndroid Build Coastguard Worker   // Writes an AvPair header for an |AvPair|. See [MS-NLMP] Section 2.2.2.1.
WriteAvPairHeader(const AvPair & pair)103*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteAvPairHeader(const AvPair& pair) {
104*6777b538SAndroid Build Coastguard Worker     return WriteAvPairHeader(pair.avid, pair.avlen);
105*6777b538SAndroid Build Coastguard Worker   }
106*6777b538SAndroid Build Coastguard Worker 
107*6777b538SAndroid Build Coastguard Worker   // Writes a special AvPair header with both fields equal to 0. This zero
108*6777b538SAndroid Build Coastguard Worker   // length AvPair signals the end of the AvPair list.
109*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteAvPairTerminator();
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker   // Writes an |AvPair| header and its payload to the buffer. If the |avid|
112*6777b538SAndroid Build Coastguard Worker   // is of type |TargetInfoAvId::kFlags| the |flags| field of |pair| will be
113*6777b538SAndroid Build Coastguard Worker   // used as the payload and the |buffer| field is ignored. In all other cases
114*6777b538SAndroid Build Coastguard Worker   // |buffer| is used as the payload. See also
115*6777b538SAndroid Build Coastguard Worker   // |NtlmBufferReader::ReadTargetInfo|.
116*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteAvPair(const AvPair& pair);
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker   // Writes a string of 8 bit characters to the buffer.
119*6777b538SAndroid Build Coastguard Worker   //
120*6777b538SAndroid Build Coastguard Worker   // When Unicode was not negotiated only the hostname string will go through
121*6777b538SAndroid Build Coastguard Worker   // this code path. The 8 bit bytes of the hostname are written to the buffer.
122*6777b538SAndroid Build Coastguard Worker   // The encoding is not relevant.
123*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteUtf8String(const std::string& str);
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   // Converts the 16 bit characters to UTF8 and writes the resulting 8 bit
126*6777b538SAndroid Build Coastguard Worker   // characters.
127*6777b538SAndroid Build Coastguard Worker   //
128*6777b538SAndroid Build Coastguard Worker   // If Unicode was not negotiated, the username and domain get converted to
129*6777b538SAndroid Build Coastguard Worker   // UTF8 in the message. Since they are just treated as additional bytes
130*6777b538SAndroid Build Coastguard Worker   // input to hash the encoding doesn't matter. In practice, only a very old or
131*6777b538SAndroid Build Coastguard Worker   // non-Windows server might trigger this code path since we always attempt
132*6777b538SAndroid Build Coastguard Worker   // to negotiate Unicode and servers are supposed to honor that request.
133*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteUtf16AsUtf8String(const std::u16string& str);
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker   // Treats |str| as UTF8, converts to UTF-16 and writes it with little-endian
136*6777b538SAndroid Build Coastguard Worker   // byte order to the buffer.
137*6777b538SAndroid Build Coastguard Worker   //
138*6777b538SAndroid Build Coastguard Worker   // Two specific strings go through this code path.
139*6777b538SAndroid Build Coastguard Worker   //
140*6777b538SAndroid Build Coastguard Worker   // One case is the hostname. When the the Unicode flag has been set during
141*6777b538SAndroid Build Coastguard Worker   // negotiation, the hostname needs to appear in the message with 16-bit
142*6777b538SAndroid Build Coastguard Worker   // characters.
143*6777b538SAndroid Build Coastguard Worker   //
144*6777b538SAndroid Build Coastguard Worker   // The other case is the Service Principal Name (SPN). With Extended
145*6777b538SAndroid Build Coastguard Worker   // Protection for Authentication (EPA) enabled, it appears in the target info
146*6777b538SAndroid Build Coastguard Worker   // inside an AV Pair, where strings always have 16-bit characters.
147*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteUtf8AsUtf16String(const std::string& str);
148*6777b538SAndroid Build Coastguard Worker 
149*6777b538SAndroid Build Coastguard Worker   // Writes UTF-16 LE characters to the buffer. For these strings, such as
150*6777b538SAndroid Build Coastguard Worker   // username and the domain the actual encoding isn't important; they are just
151*6777b538SAndroid Build Coastguard Worker   // treated as additional bytes of input to the hash.
152*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteUtf16String(const std::u16string& str);
153*6777b538SAndroid Build Coastguard Worker 
154*6777b538SAndroid Build Coastguard Worker   // Writes the 8 byte NTLM signature "NTLMSSP\0" into the buffer.
155*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteSignature();
156*6777b538SAndroid Build Coastguard Worker 
157*6777b538SAndroid Build Coastguard Worker   // There are 3 message types Negotiate (sent by client), Challenge (sent by
158*6777b538SAndroid Build Coastguard Worker   // server), and Authenticate (sent by client).
159*6777b538SAndroid Build Coastguard Worker   //
160*6777b538SAndroid Build Coastguard Worker   // This writes |message_type| as a uint32_t into the buffer.
161*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteMessageType(MessageType message_type);
162*6777b538SAndroid Build Coastguard Worker 
163*6777b538SAndroid Build Coastguard Worker   // Performs |WriteSignature| then |WriteMessageType|.
164*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] bool WriteMessageHeader(MessageType message_type);
165*6777b538SAndroid Build Coastguard Worker 
166*6777b538SAndroid Build Coastguard Worker  private:
167*6777b538SAndroid Build Coastguard Worker   // Writes |sizeof(T)| bytes little-endian of an integer type to the buffer.
168*6777b538SAndroid Build Coastguard Worker   template <typename T>
169*6777b538SAndroid Build Coastguard Worker   bool WriteUInt(T value);
170*6777b538SAndroid Build Coastguard Worker 
171*6777b538SAndroid Build Coastguard Worker   // Sets the cursor position. The caller should use |GetLength| or
172*6777b538SAndroid Build Coastguard Worker   // |CanWrite| to verify the bounds before calling this method.
173*6777b538SAndroid Build Coastguard Worker   void SetCursor(size_t cursor);
174*6777b538SAndroid Build Coastguard Worker 
175*6777b538SAndroid Build Coastguard Worker   // Advances the cursor by |count|. The caller should use |GetLength| or
176*6777b538SAndroid Build Coastguard Worker   // |CanWrite| to verify the bounds before calling this method.
AdvanceCursor(size_t count)177*6777b538SAndroid Build Coastguard Worker   void AdvanceCursor(size_t count) { SetCursor(GetCursor() + count); }
178*6777b538SAndroid Build Coastguard Worker 
179*6777b538SAndroid Build Coastguard Worker   // Returns a pointer to the start of the buffer.
GetBufferPtr()180*6777b538SAndroid Build Coastguard Worker   const uint8_t* GetBufferPtr() const { return buffer_.data(); }
GetBufferPtr()181*6777b538SAndroid Build Coastguard Worker   uint8_t* GetBufferPtr() { return buffer_.data(); }
182*6777b538SAndroid Build Coastguard Worker 
183*6777b538SAndroid Build Coastguard Worker   // Returns pointer into the buffer at the current cursor location.
GetBufferPtrAtCursor()184*6777b538SAndroid Build Coastguard Worker   const uint8_t* GetBufferPtrAtCursor() const {
185*6777b538SAndroid Build Coastguard Worker     return GetBufferPtr() + GetCursor();
186*6777b538SAndroid Build Coastguard Worker   }
GetBufferPtrAtCursor()187*6777b538SAndroid Build Coastguard Worker   uint8_t* GetBufferPtrAtCursor() { return GetBufferPtr() + GetCursor(); }
188*6777b538SAndroid Build Coastguard Worker 
189*6777b538SAndroid Build Coastguard Worker   std::vector<uint8_t> buffer_;
190*6777b538SAndroid Build Coastguard Worker   size_t cursor_ = 0;
191*6777b538SAndroid Build Coastguard Worker };
192*6777b538SAndroid Build Coastguard Worker 
193*6777b538SAndroid Build Coastguard Worker }  // namespace net::ntlm
194*6777b538SAndroid Build Coastguard Worker 
195*6777b538SAndroid Build Coastguard Worker #endif  // NET_NTLM_NTLM_BUFFER_WRITER_H_
196