| // Copyright 2017 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef NET_BASE_NTLM_BUFFER_WRITER_H_ | 
 | #define NET_BASE_NTLM_BUFFER_WRITER_H_ | 
 |  | 
 | #include <memory> | 
 | #include <string> | 
 |  | 
 | #include "base/containers/span.h" | 
 | #include "base/strings/string16.h" | 
 | #include "base/strings/string_piece.h" | 
 | #include "net/base/net_export.h" | 
 | #include "net/ntlm/ntlm_constants.h" | 
 | #include "starboard/types.h" | 
 |  | 
 | namespace net { | 
 | namespace ntlm { | 
 |  | 
 | // Supports various bounds checked low level buffer operations required by an | 
 | // NTLM implementation. | 
 | // | 
 | // The class supports sequential write to an internally managed buffer. All | 
 | // writes perform bounds checking to ensure enough space is remaining in the | 
 | // buffer. | 
 | // | 
 | // The internal buffer is allocated in the constructor with size |buffer_len| | 
 | // and owned by the class. | 
 | // | 
 | // Write* methods write the buffer at the current cursor position and perform | 
 | // any necessary type conversion and provide the data in out params. After a | 
 | // successful write the cursor position is advanced past the written field. | 
 | // | 
 | // Failed writes leave the internal cursor at the same position as before the | 
 | // call. | 
 | // | 
 | // Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol | 
 | // Specification version 28.0 [1]. Additional NTLM reference [2]. | 
 | // | 
 | // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx | 
 | // [2] http://davenport.sourceforge.net/ntlm.html | 
 | class NET_EXPORT_PRIVATE NtlmBufferWriter { | 
 |  public: | 
 |   explicit NtlmBufferWriter(size_t buffer_len); | 
 |   ~NtlmBufferWriter(); | 
 |  | 
 |   size_t GetLength() const { return buffer_.size(); } | 
 |   size_t GetCursor() const { return cursor_; } | 
 |   bool IsEndOfBuffer() const { return cursor_ >= GetLength(); } | 
 | #if defined(STARBOARD) | 
 |   base::span<const uint8_t> GetBuffer() const { | 
 |     return base::span<const uint8_t>(buffer_.data(), buffer_.size()); | 
 |   } | 
 | #else | 
 |   base::span<const uint8_t> GetBuffer() const { return buffer_; } | 
 | #endif | 
 |   std::vector<uint8_t> Pass() const { return std::move(buffer_); } | 
 |  | 
 |   // Returns true if there are |len| more bytes between the current cursor | 
 |   // position and the end of the buffer. | 
 |   bool CanWrite(size_t len) const; | 
 |  | 
 |   // Writes a 16 bit unsigned value (little endian). If there are not 16 | 
 |   // more bits available in the buffer, it returns false. | 
 |   bool WriteUInt16(uint16_t value) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Writes a 32 bit unsigned value (little endian). If there are not 32 | 
 |   // more bits available in the buffer, it returns false. | 
 |   bool WriteUInt32(uint32_t value) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Writes a 64 bit unsigned value (little endian). If there are not 64 | 
 |   // more bits available in the buffer, it returns false. | 
 |   bool WriteUInt64(uint64_t value) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Writes flags as a 32 bit unsigned value (little endian). | 
 |   bool WriteFlags(NegotiateFlags flags) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Writes the bytes from the |buffer|. If there are not enough | 
 |   // bytes in the buffer, it returns false. | 
 |   bool WriteBytes(base::span<const uint8_t> buffer) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Writes |count| bytes of zeros to the buffer. If there are not |count| | 
 |   // more bytes in available in the buffer, it returns false. | 
 |   bool WriteZeros(size_t count) WARN_UNUSED_RESULT; | 
 |  | 
 |   // A security buffer is an 8 byte structure that defines the offset and | 
 |   // length of a payload (string, struct, or byte array) that appears after | 
 |   // the fixed part of the message. | 
 |   // | 
 |   // The structure in the NTLM message is (little endian fields): | 
 |   //     uint16 - |length| Length of payload | 
 |   //     uint16 - Allocation (ignored and always set to |length|) | 
 |   //     uint32 - |offset| Offset from start of message | 
 |   bool WriteSecurityBuffer(SecurityBuffer sec_buf) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Writes an AvPair header. See [MS-NLMP] Section 2.2.2.1. | 
 |   // | 
 |   // The header has the following structure: | 
 |   //    uint16 - |avid| The identifier of the following payload. | 
 |   //    uint16 - |avlen| The length of the following payload. | 
 |   bool WriteAvPairHeader(TargetInfoAvId avid, | 
 |                          uint16_t avlen) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Writes an AvPair header for an |AvPair|. See [MS-NLMP] Section 2.2.2.1. | 
 |   bool WriteAvPairHeader(const AvPair& pair) WARN_UNUSED_RESULT { | 
 |     return WriteAvPairHeader(pair.avid, pair.avlen); | 
 |   } | 
 |  | 
 |   // Writes a special AvPair header with both fields equal to 0. This zero | 
 |   // length AvPair signals the end of the AvPair list. | 
 |   bool WriteAvPairTerminator() WARN_UNUSED_RESULT; | 
 |  | 
 |   // Writes an |AvPair| header and its payload to the buffer. If the |avid| | 
 |   // is of type |TargetInfoAvId::kFlags| the |flags| field of |pair| will be | 
 |   // used as the payload and the |buffer| field is ignored. In all other cases | 
 |   // |buffer| is used as the payload. See also | 
 |   // |NtlmBufferReader::ReadTargetInfo|. | 
 |   bool WriteAvPair(const AvPair& pair) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Writes a string of 8 bit characters to the buffer. | 
 |   // | 
 |   // When Unicode was not negotiated only the hostname string will go through | 
 |   // this code path. The 8 bit bytes of the hostname are written to the buffer. | 
 |   // The encoding is not relevant. | 
 |   bool WriteUtf8String(const std::string& str) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Converts the 16 bit characters to UTF8 and writes the resulting 8 bit | 
 |   // characters. | 
 |   // | 
 |   // If Unicode was not negotiated, the username and domain get converted to | 
 |   // UTF8 in the message. Since they are just treated as additional bytes | 
 |   // input to hash the encoding doesn't matter. In practice, only a very old or | 
 |   // non-Windows server might trigger this code path since we always attempt | 
 |   // to negotiate Unicode and servers are supposed to honor that request. | 
 |   bool WriteUtf16AsUtf8String(const base::string16& str) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Treats |str| as UTF8, converts to UTF-16 and writes it with little-endian | 
 |   // byte order to the buffer. | 
 |   // | 
 |   // Two specific strings go through this code path. | 
 |   // | 
 |   // One case is the hostname. When the the Unicode flag has been set during | 
 |   // negotiation, the hostname needs to appear in the message with 16-bit | 
 |   // characters. | 
 |   // | 
 |   // The other case is the Service Principal Name (SPN). With Extended | 
 |   // Protection for Authentication (EPA) enabled, it appears in the target info | 
 |   // inside an AV Pair, where strings always have 16-bit characters. | 
 |   bool WriteUtf8AsUtf16String(const std::string& str) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Writes UTF-16 LE characters to the buffer. For these strings, such as | 
 |   // username and the domain the actual encoding isn't important; they are just | 
 |   // treated as additional bytes of input to the hash. | 
 |   bool WriteUtf16String(const base::string16& str) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Writes the 8 byte NTLM signature "NTLMSSP\0" into the buffer. | 
 |   bool WriteSignature() WARN_UNUSED_RESULT; | 
 |  | 
 |   // There are 3 message types Negotiate (sent by client), Challenge (sent by | 
 |   // server), and Authenticate (sent by client). | 
 |   // | 
 |   // This writes |message_type| as a uint32_t into the buffer. | 
 |   bool WriteMessageType(MessageType message_type) WARN_UNUSED_RESULT; | 
 |  | 
 |   // Performs |WriteSignature| then |WriteMessageType|. | 
 |   bool WriteMessageHeader(MessageType message_type) WARN_UNUSED_RESULT; | 
 |  | 
 |  private: | 
 |   // Writes |sizeof(T)| bytes little-endian of an integer type to the buffer. | 
 |   template <typename T> | 
 |   bool WriteUInt(T value); | 
 |  | 
 |   // Sets the cursor position. The caller should use |GetLength| or | 
 |   // |CanWrite| to verify the bounds before calling this method. | 
 |   void SetCursor(size_t cursor); | 
 |  | 
 |   // Advances the cursor by |count|. The caller should use |GetLength| or | 
 |   // |CanWrite| to verify the bounds before calling this method. | 
 |   void AdvanceCursor(size_t count) { SetCursor(GetCursor() + count); } | 
 |  | 
 |   // Returns a pointer to the start of the buffer. | 
 |   const uint8_t* GetBufferPtr() const { return buffer_.data(); } | 
 |   uint8_t* GetBufferPtr() { return buffer_.data(); } | 
 |  | 
 |   // Returns pointer into the buffer at the current cursor location. | 
 |   const uint8_t* GetBufferPtrAtCursor() const { | 
 |     return GetBufferPtr() + GetCursor(); | 
 |   } | 
 |   uint8_t* GetBufferPtrAtCursor() { return GetBufferPtr() + GetCursor(); } | 
 |  | 
 |   std::vector<uint8_t> buffer_; | 
 |   size_t cursor_; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(NtlmBufferWriter); | 
 | }; | 
 |  | 
 | }  // namespace ntlm | 
 | }  // namespace net | 
 |  | 
 | #endif  // NET_BASE_NTLM_BUFFER_WRITER_H_ |