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