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_READER_H_ 6*6777b538SAndroid Build Coastguard Worker #define NET_NTLM_NTLM_BUFFER_READER_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 <vector> 12*6777b538SAndroid Build Coastguard Worker 13*6777b538SAndroid Build Coastguard Worker #include "base/check.h" 14*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h" 15*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h" 16*6777b538SAndroid Build Coastguard Worker #include "net/ntlm/ntlm_constants.h" 17*6777b538SAndroid Build Coastguard Worker 18*6777b538SAndroid Build Coastguard Worker namespace net::ntlm { 19*6777b538SAndroid Build Coastguard Worker 20*6777b538SAndroid Build Coastguard Worker // Supports various bounds-checked low level buffer operations required by an 21*6777b538SAndroid Build Coastguard Worker // NTLM implementation. 22*6777b538SAndroid Build Coastguard Worker // 23*6777b538SAndroid Build Coastguard Worker // The class supports the sequential read of a provided buffer. All reads 24*6777b538SAndroid Build Coastguard Worker // perform bounds checking to ensure enough space is remaining in the buffer. 25*6777b538SAndroid Build Coastguard Worker // 26*6777b538SAndroid Build Coastguard Worker // Read* methods read from the buffer at the current cursor position and 27*6777b538SAndroid Build Coastguard Worker // perform any necessary type conversion and provide the data in out params. 28*6777b538SAndroid Build Coastguard Worker // After a successful read the cursor position is advanced past the read 29*6777b538SAndroid Build Coastguard Worker // field. 30*6777b538SAndroid Build Coastguard Worker // 31*6777b538SAndroid Build Coastguard Worker // Failed Read*s or Match*s leave the cursor in an undefined position and the 32*6777b538SAndroid Build Coastguard Worker // buffer MUST be discarded with no further operations performed. 33*6777b538SAndroid Build Coastguard Worker // 34*6777b538SAndroid Build Coastguard Worker // Read*Payload methods first reads a security buffer (see 35*6777b538SAndroid Build Coastguard Worker // |ReadSecurityBuffer|), then reads the requested payload from the offset 36*6777b538SAndroid Build Coastguard Worker // and length stated in the security buffer. 37*6777b538SAndroid Build Coastguard Worker // 38*6777b538SAndroid Build Coastguard Worker // If the length and offset in the security buffer would cause a read outside 39*6777b538SAndroid Build Coastguard Worker // the message buffer the payload will not be read and the function will 40*6777b538SAndroid Build Coastguard Worker // return false. 41*6777b538SAndroid Build Coastguard Worker // 42*6777b538SAndroid Build Coastguard Worker // Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol 43*6777b538SAndroid Build Coastguard Worker // Specification version 28.0 [1]. Additional NTLM reference [2]. 44*6777b538SAndroid Build Coastguard Worker // 45*6777b538SAndroid Build Coastguard Worker // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx 46*6777b538SAndroid Build Coastguard Worker // [2] http://davenport.sourceforge.net/ntlm.html 47*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE NtlmBufferReader { 48*6777b538SAndroid Build Coastguard Worker public: 49*6777b538SAndroid Build Coastguard Worker NtlmBufferReader(); 50*6777b538SAndroid Build Coastguard Worker // |buffer| is not copied and must outlive the |NtlmBufferReader|. 51*6777b538SAndroid Build Coastguard Worker explicit NtlmBufferReader(base::span<const uint8_t> buffer); 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard Worker ~NtlmBufferReader(); 54*6777b538SAndroid Build Coastguard Worker GetLength()55*6777b538SAndroid Build Coastguard Worker size_t GetLength() const { return buffer_.size(); } GetCursor()56*6777b538SAndroid Build Coastguard Worker size_t GetCursor() const { return cursor_; } IsEndOfBuffer()57*6777b538SAndroid Build Coastguard Worker bool IsEndOfBuffer() const { return cursor_ >= GetLength(); } 58*6777b538SAndroid Build Coastguard Worker 59*6777b538SAndroid Build Coastguard Worker // Returns true if there are |len| more bytes between the current cursor 60*6777b538SAndroid Build Coastguard Worker // position and the end of the buffer. 61*6777b538SAndroid Build Coastguard Worker bool CanRead(size_t len) const; 62*6777b538SAndroid Build Coastguard Worker 63*6777b538SAndroid Build Coastguard Worker // Returns true if there are |len| more bytes between |offset| and the end 64*6777b538SAndroid Build Coastguard Worker // of the buffer. The cursor position is not used or modified. 65*6777b538SAndroid Build Coastguard Worker bool CanReadFrom(size_t offset, size_t len) const; 66*6777b538SAndroid Build Coastguard Worker 67*6777b538SAndroid Build Coastguard Worker // Returns true if it would be possible to read the payload described by the 68*6777b538SAndroid Build Coastguard Worker // security buffer. CanReadFrom(SecurityBuffer sec_buf)69*6777b538SAndroid Build Coastguard Worker bool CanReadFrom(SecurityBuffer sec_buf) const { 70*6777b538SAndroid Build Coastguard Worker return CanReadFrom(sec_buf.offset, sec_buf.length); 71*6777b538SAndroid Build Coastguard Worker } 72*6777b538SAndroid Build Coastguard Worker 73*6777b538SAndroid Build Coastguard Worker // Reads a 16 bit value (little endian) as a uint16_t. If there are not 16 74*6777b538SAndroid Build Coastguard Worker // more bits available, it returns false. 75*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool ReadUInt16(uint16_t* value); 76*6777b538SAndroid Build Coastguard Worker 77*6777b538SAndroid Build Coastguard Worker // Reads a 32 bit value (little endian) as a uint32_t. If there are not 32 78*6777b538SAndroid Build Coastguard Worker // more bits available, it returns false. 79*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool ReadUInt32(uint32_t* value); 80*6777b538SAndroid Build Coastguard Worker 81*6777b538SAndroid Build Coastguard Worker // Reads a 64 bit value (little endian) as a uint64_t. If there are not 64 82*6777b538SAndroid Build Coastguard Worker // more bits available, it returns false. 83*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool ReadUInt64(uint64_t* value); 84*6777b538SAndroid Build Coastguard Worker 85*6777b538SAndroid Build Coastguard Worker // Calls |ReadUInt32| and returns it cast as |NegotiateFlags|. No 86*6777b538SAndroid Build Coastguard Worker // validation of the value takes place. 87*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool ReadFlags(NegotiateFlags* flags); 88*6777b538SAndroid Build Coastguard Worker 89*6777b538SAndroid Build Coastguard Worker // Reads |len| bytes and copies them into |buffer|. 90*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool ReadBytes(base::span<uint8_t> buffer); 91*6777b538SAndroid Build Coastguard Worker 92*6777b538SAndroid Build Coastguard Worker // Reads |sec_buf.length| bytes from offset |sec_buf.offset| and copies them 93*6777b538SAndroid Build Coastguard Worker // into |buffer|. If the security buffer specifies a payload outside the 94*6777b538SAndroid Build Coastguard Worker // buffer, then the call fails. Unlike the other Read* methods, this does 95*6777b538SAndroid Build Coastguard Worker // not move the cursor. 96*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool ReadBytesFrom(const SecurityBuffer& sec_buf, 97*6777b538SAndroid Build Coastguard Worker base::span<uint8_t> buffer); 98*6777b538SAndroid Build Coastguard Worker 99*6777b538SAndroid Build Coastguard Worker // Reads |sec_buf.length| bytes from offset |sec_buf.offset| and assigns 100*6777b538SAndroid Build Coastguard Worker // |reader| an |NtlmBufferReader| representing the payload. If the security 101*6777b538SAndroid Build Coastguard Worker // buffer specifies a payload outside the buffer, then the call fails, and 102*6777b538SAndroid Build Coastguard Worker // the state of |reader| is undefined. Unlike the other Read* methods, this 103*6777b538SAndroid Build Coastguard Worker // does not move the cursor. 104*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool ReadPayloadAsBufferReader(const SecurityBuffer& sec_buf, 105*6777b538SAndroid Build Coastguard Worker NtlmBufferReader* reader); 106*6777b538SAndroid Build Coastguard Worker 107*6777b538SAndroid Build Coastguard Worker // A security buffer is an 8 byte structure that defines the offset and 108*6777b538SAndroid Build Coastguard Worker // length of a payload (string, struct or byte array) that appears after the 109*6777b538SAndroid Build Coastguard Worker // fixed part of the message. 110*6777b538SAndroid Build Coastguard Worker // 111*6777b538SAndroid Build Coastguard Worker // The structure is (little endian fields): 112*6777b538SAndroid Build Coastguard Worker // uint16 - |length| Length of payload 113*6777b538SAndroid Build Coastguard Worker // uint16 - Allocation (this is always ignored and not returned) 114*6777b538SAndroid Build Coastguard Worker // uint32 - |offset| Offset from start of message 115*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool ReadSecurityBuffer(SecurityBuffer* sec_buf); 116*6777b538SAndroid Build Coastguard Worker 117*6777b538SAndroid Build Coastguard Worker // Reads an AvPair header. AvPairs appear sequentially, terminated by a 118*6777b538SAndroid Build Coastguard Worker // special EOL AvPair, in the target info payload of the Challenge message. 119*6777b538SAndroid Build Coastguard Worker // See [MS-NLMP] Section 2.2.2.1. 120*6777b538SAndroid Build Coastguard Worker // 121*6777b538SAndroid Build Coastguard Worker // An AvPair contains an inline payload, and has the structure below ( 122*6777b538SAndroid Build Coastguard Worker // little endian fields): 123*6777b538SAndroid Build Coastguard Worker // uint16 - AvID: Identifies the type of the payload. 124*6777b538SAndroid Build Coastguard Worker // uint16 - AvLen: The length of the following payload. 125*6777b538SAndroid Build Coastguard Worker // (variable) - Payload: Variable length payload. The content and 126*6777b538SAndroid Build Coastguard Worker // format are determined by the AvId. 127*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool ReadAvPairHeader(TargetInfoAvId* avid, uint16_t* avlen); 128*6777b538SAndroid Build Coastguard Worker 129*6777b538SAndroid Build Coastguard Worker // There are 3 message types Negotiate (sent by client), Challenge (sent by 130*6777b538SAndroid Build Coastguard Worker // server), and Authenticate (sent by client). 131*6777b538SAndroid Build Coastguard Worker // 132*6777b538SAndroid Build Coastguard Worker // This reads the message type from the header and will return false if the 133*6777b538SAndroid Build Coastguard Worker // value is invalid. 134*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool ReadMessageType(MessageType* message_type); 135*6777b538SAndroid Build Coastguard Worker 136*6777b538SAndroid Build Coastguard Worker // Reads |target_info_len| bytes and parses them as a sequence of Av Pairs. 137*6777b538SAndroid Build Coastguard Worker // |av_pairs| should be empty on entry to this function. If |ReadTargetInfo| 138*6777b538SAndroid Build Coastguard Worker // returns false, the content of |av_pairs| is in an undefined state and 139*6777b538SAndroid Build Coastguard Worker // should be discarded. 140*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool ReadTargetInfo(size_t target_info_len, 141*6777b538SAndroid Build Coastguard Worker std::vector<AvPair>* av_pairs); 142*6777b538SAndroid Build Coastguard Worker 143*6777b538SAndroid Build Coastguard Worker // Reads a security buffer, then parses the security buffer payload as a 144*6777b538SAndroid Build Coastguard Worker // target info. The target info is returned as a sequence of AvPairs, with 145*6777b538SAndroid Build Coastguard Worker // the terminating AvPair omitted. A zero length payload is valid and will 146*6777b538SAndroid Build Coastguard Worker // result in an empty list in |av_pairs|. Any non-zero length payload must 147*6777b538SAndroid Build Coastguard Worker // have a terminating AvPair. 148*6777b538SAndroid Build Coastguard Worker // |av_pairs| should be empty on entry to this function. If |ReadTargetInfo| 149*6777b538SAndroid Build Coastguard Worker // returns false, the content of |av_pairs| is in an undefined state and 150*6777b538SAndroid Build Coastguard Worker // should be discarded. 151*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool ReadTargetInfoPayload(std::vector<AvPair>* av_pairs); 152*6777b538SAndroid Build Coastguard Worker 153*6777b538SAndroid Build Coastguard Worker // Skips over a security buffer field without reading the fields. This is 154*6777b538SAndroid Build Coastguard Worker // the equivalent of advancing the cursor 8 bytes. Returns false if there 155*6777b538SAndroid Build Coastguard Worker // are less than 8 bytes left in the buffer. 156*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool SkipSecurityBuffer(); 157*6777b538SAndroid Build Coastguard Worker 158*6777b538SAndroid Build Coastguard Worker // Skips over the security buffer without returning the values, but fails if 159*6777b538SAndroid Build Coastguard Worker // the values would cause a read outside the buffer if the payload was 160*6777b538SAndroid Build Coastguard Worker // actually read. 161*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool SkipSecurityBufferWithValidation(); 162*6777b538SAndroid Build Coastguard Worker 163*6777b538SAndroid Build Coastguard Worker // Skips over |count| bytes in the buffer. Returns false if there are not 164*6777b538SAndroid Build Coastguard Worker // |count| bytes left in the buffer. 165*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool SkipBytes(size_t count); 166*6777b538SAndroid Build Coastguard Worker 167*6777b538SAndroid Build Coastguard Worker // Reads and returns true if the next 8 bytes matches the signature in an 168*6777b538SAndroid Build Coastguard Worker // NTLM message "NTLMSSP\0". The cursor advances if the the signature 169*6777b538SAndroid Build Coastguard Worker // is matched. 170*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool MatchSignature(); 171*6777b538SAndroid Build Coastguard Worker 172*6777b538SAndroid Build Coastguard Worker // Performs |ReadMessageType| and returns true if the value is 173*6777b538SAndroid Build Coastguard Worker // |message_type|. If the read fails or the message type does not match, 174*6777b538SAndroid Build Coastguard Worker // the buffer is invalid and MUST be discarded. 175*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool MatchMessageType(MessageType message_type); 176*6777b538SAndroid Build Coastguard Worker 177*6777b538SAndroid Build Coastguard Worker // Performs |MatchSignature| then |MatchMessageType|. 178*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool MatchMessageHeader(MessageType message_type); 179*6777b538SAndroid Build Coastguard Worker 180*6777b538SAndroid Build Coastguard Worker // Performs |ReadBytes(count)| and returns true if the contents is all 181*6777b538SAndroid Build Coastguard Worker // zero. 182*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool MatchZeros(size_t count); 183*6777b538SAndroid Build Coastguard Worker 184*6777b538SAndroid Build Coastguard Worker // Reads the security buffer and returns true if the length is 0 and 185*6777b538SAndroid Build Coastguard Worker // the offset is within the message. On failure, the buffer is invalid 186*6777b538SAndroid Build Coastguard Worker // and MUST be discarded. 187*6777b538SAndroid Build Coastguard Worker [[nodiscard]] bool MatchEmptySecurityBuffer(); 188*6777b538SAndroid Build Coastguard Worker 189*6777b538SAndroid Build Coastguard Worker private: 190*6777b538SAndroid Build Coastguard Worker // Reads |sizeof(T)| bytes of an integer type from a little-endian buffer. 191*6777b538SAndroid Build Coastguard Worker template <typename T> 192*6777b538SAndroid Build Coastguard Worker bool ReadUInt(T* value); 193*6777b538SAndroid Build Coastguard Worker 194*6777b538SAndroid Build Coastguard Worker // Sets the cursor position. The caller should use |GetLength|, |CanRead|, 195*6777b538SAndroid Build Coastguard Worker // or |CanReadFrom| to verify the bounds before calling this method. 196*6777b538SAndroid Build Coastguard Worker void SetCursor(size_t cursor); 197*6777b538SAndroid Build Coastguard Worker 198*6777b538SAndroid Build Coastguard Worker // Advances the cursor by |count| bytes. The caller should use |GetLength|, 199*6777b538SAndroid Build Coastguard Worker // |CanRead|, or |CanReadFrom| to verify the bounds before calling this 200*6777b538SAndroid Build Coastguard Worker // method. AdvanceCursor(size_t count)201*6777b538SAndroid Build Coastguard Worker void AdvanceCursor(size_t count) { SetCursor(GetCursor() + count); } 202*6777b538SAndroid Build Coastguard Worker 203*6777b538SAndroid Build Coastguard Worker // Returns a constant pointer to the start of the buffer. GetBufferPtr()204*6777b538SAndroid Build Coastguard Worker const uint8_t* GetBufferPtr() const { return buffer_.data(); } 205*6777b538SAndroid Build Coastguard Worker 206*6777b538SAndroid Build Coastguard Worker // Returns a pointer to the underlying buffer at the current cursor 207*6777b538SAndroid Build Coastguard Worker // position. GetBufferAtCursor()208*6777b538SAndroid Build Coastguard Worker const uint8_t* GetBufferAtCursor() const { return GetBufferPtr() + cursor_; } 209*6777b538SAndroid Build Coastguard Worker 210*6777b538SAndroid Build Coastguard Worker // Returns the byte at the current cursor position. GetByteAtCursor()211*6777b538SAndroid Build Coastguard Worker uint8_t GetByteAtCursor() const { 212*6777b538SAndroid Build Coastguard Worker DCHECK(!IsEndOfBuffer()); 213*6777b538SAndroid Build Coastguard Worker return *(GetBufferAtCursor()); 214*6777b538SAndroid Build Coastguard Worker } 215*6777b538SAndroid Build Coastguard Worker 216*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> buffer_; 217*6777b538SAndroid Build Coastguard Worker size_t cursor_ = 0; 218*6777b538SAndroid Build Coastguard Worker }; 219*6777b538SAndroid Build Coastguard Worker 220*6777b538SAndroid Build Coastguard Worker } // namespace net::ntlm 221*6777b538SAndroid Build Coastguard Worker 222*6777b538SAndroid Build Coastguard Worker #endif // NET_NTLM_NTLM_BUFFER_READER_H_ 223