Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef NET_BASE_NTLM_BUFFER_READER_H_ | |
| 6 #define NET_BASE_NTLM_BUFFER_READER_H_ | |
| 7 | |
| 8 #include <stddef.h> | |
| 9 #include <stdint.h> | |
| 10 | |
| 11 #include <string> | |
| 12 | |
| 13 #include "base/strings/string_piece.h" | |
| 14 #include "net/base/net_export.h" | |
| 15 #include "net/http/ntlm_message.h" | |
| 16 | |
| 17 namespace net { | |
| 18 | |
| 19 // Supports various bounds checked low level buffer | |
| 20 // operations required by an NTLM implementation. | |
| 21 // | |
| 22 // The class supports sequential read of a provided | |
| 23 // buffer. All reads perform bounds checking to ensure | |
| 24 // enough space is remaining in the buffer. | |
| 25 // | |
| 26 // | |
| 27 // Read* methods read from the buffer at the current cursor | |
| 28 // position and perform any necessary type conversion and | |
| 29 // provide the data in out params. After a successful read | |
| 30 // the cursor position is advanced past the read field. | |
| 31 // | |
| 32 // Failed reads leave the internal cursor at the same | |
| 33 // position as before the call. | |
| 34 // | |
| 35 // | |
| 36 // Read*Payload methods first read a security buffer see | |
| 37 // |ReadSecurityBuffer| then read the requested payload | |
| 38 // from the offset and length stated in the security buffer. | |
| 39 // | |
| 40 // If the length and offset in the security buffer would | |
| 41 // cause a read outside the message buffer the payload will | |
| 42 // not be read and the function will return false. | |
| 43 // | |
| 44 // The cursor will remain as it was before the call as if | |
| 45 // the security buffer had not been read. | |
| 46 // | |
| 47 // | |
| 48 // Skip* methods skip the cursor over that same number | |
| 49 // of bytes that the equivalent Read method would without | |
| 50 // reading or returning the values. | |
| 51 // | |
| 52 // | |
| 53 // Match* methods are used to validate fields in the | |
| 54 // buffer that should have expected values, such as | |
| 55 // signatures or message identifiers. | |
|
Ryan Sleevi
2017/05/30 19:02:22
I can't tell - are these aligned to the maximal us
zentaro
2017/06/05 17:28:44
Done.
| |
| 56 // | |
| 57 // | |
| 58 // Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication | |
| 59 // Protocol specification version 28.0 [1] | |
| 60 // | |
| 61 // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx | |
| 62 class NET_EXPORT NtlmBufferReader { | |
| 63 public: | |
| 64 NtlmBufferReader(const base::StringPiece buffer); | |
|
Ryan Sleevi
2017/05/30 19:02:22
style: you can drop the const since you're passing
Ryan Sleevi
2017/05/30 19:02:22
style: "explicit" - https://google.github.io/style
zentaro
2017/06/05 17:28:44
Done. I previously was passing by const-ref then s
zentaro
2017/06/05 17:28:44
Done.
| |
| 65 NtlmBufferReader(const uint8_t* ptr, size_t len); | |
|
Ryan Sleevi
2017/05/30 19:02:22
Since you accept a base::StringPiece, is this over
zentaro
2017/06/05 17:28:44
I could I guess try and convert all the callers to
| |
| 66 ~NtlmBufferReader(); | |
| 67 | |
| 68 size_t GetLength() const { return buffer_.length(); } | |
| 69 size_t GetCursor() const { return cursor_; } | |
| 70 bool IsEndOfBuffer() const { return cursor_ >= GetLength(); } | |
| 71 | |
| 72 const uint8_t* GetBufferPtr() const { | |
| 73 return reinterpret_cast<const uint8_t*>(buffer_.data()); | |
| 74 } | |
| 75 | |
| 76 // Returns a pointer to the underlying buffer at the current cursor | |
| 77 // position. | |
| 78 const uint8_t* GetBufferAtCursor() const { return GetBufferPtr() + cursor_; } | |
|
Ryan Sleevi
2017/05/30 19:02:22
Both this and the function on line 72 seem like th
zentaro
2017/06/05 17:28:44
I managed to refactor out all the public uses of t
| |
| 79 | |
| 80 // Returns true if there are |len| more bytes between the | |
| 81 // current cursor position and the end of the buffer. | |
| 82 bool CanRead(size_t len) const; | |
| 83 | |
| 84 // Returns true if there are |len| more bytes between |offset| | |
| 85 // and the end of the buffer. The cursor position is not used | |
| 86 // or modified. | |
| 87 bool CanReadFrom(size_t offset, size_t len) const; | |
| 88 | |
| 89 bool ReadUInt16(uint16_t* value); | |
|
Ryan Sleevi
2017/05/30 19:02:22
Document a bit more - for example, what's the endi
zentaro
2017/06/05 17:28:44
Done.
| |
| 90 bool ReadUInt32(uint32_t* value); | |
| 91 bool ReadUInt64(uint64_t* value); | |
| 92 | |
| 93 bool ReadBytes(uint8_t* buffer, size_t len); | |
| 94 | |
| 95 // A security buffer is an 8 byte structure that defines the | |
| 96 // offset and length of a payload (string, struct or byte array) | |
| 97 // that appears after the fixed part of the message. | |
| 98 // | |
| 99 // The structure is (little endian fields): | |
| 100 // uint16 - |length| Length of payload | |
| 101 // uint16 - Allocation (this is always ignored and not returned) | |
| 102 // uint32 - |offset| Offset from start of message | |
| 103 bool ReadSecurityBuffer(uint16_t* length, uint32_t* offset); | |
| 104 | |
| 105 bool ReadAsciiString(std::string* value, size_t len); | |
| 106 bool ReadUnicodeString(base::string16* value, size_t len); | |
|
Ryan Sleevi
2017/05/30 19:02:22
I suspect you're borrowing from the NTLM language,
| |
| 107 | |
| 108 // There are 3 message types Negotiate (sent by client), | |
| 109 // Challenge (sent by server), and Authenticate (sent by client). | |
| 110 // | |
| 111 // This reads the message type from the header and will return | |
| 112 // false if the value is invalid. | |
| 113 bool ReadMessageType(NtlmMessage::MessageType* message_type); | |
| 114 | |
| 115 bool ReadAsciiPayload(std::string* value); | |
| 116 bool ReadUnicodePayload(base::string16* value); | |
| 117 bool ReadBytesPayload(uint8_t* buffer, size_t buffer_len); | |
|
Ryan Sleevi
2017/05/30 19:02:22
How are the *Payload functions different from the
zentaro
2017/06/05 17:28:44
Added some additional docs to clarify. But the 'pa
| |
| 118 | |
| 119 bool SkipSecurityBuffer(); | |
| 120 | |
| 121 // Skips over the security buffer without returning the values | |
|
Ryan Sleevi
2017/05/30 19:02:22
grammar: "returning the values, " (add a comma)
zentaro
2017/06/05 17:28:44
Done.
| |
| 122 // but fails if the values would cause a read outside the buffer | |
| 123 // if the payload was actually read. | |
| 124 bool SkipSecurityBufferWithValidation(); | |
| 125 | |
| 126 // Skips over |count| bytes in the buffer. Returns false if there | |
| 127 // is not |count| bytes left in the buffer. | |
| 128 bool SkipBytes(size_t count); | |
| 129 | |
| 130 // Reads and returns true if the next 8 bytes matches the signature in | |
| 131 // an NTLM message "NTLMSSP\0" | |
| 132 bool MatchSignature(); | |
| 133 | |
| 134 // Reads the message type from the cursor and returns true | |
| 135 // if it is |message_type|. | |
| 136 bool MatchMessageType(NtlmMessage::MessageType message_type); | |
| 137 | |
| 138 // Performs |MatchSignature| then |MatchMessageType|. | |
| 139 bool MatchMessageHeader(NtlmMessage::MessageType message_type); | |
| 140 | |
| 141 // Reads and returns true if there are |count| bytes of zeros. | |
| 142 bool MatchZeros(size_t count); | |
| 143 | |
| 144 // Reads and returns true if the next 8 bytes contain an empty | |
| 145 // ie. all zero security buffer. | |
| 146 bool MatchEmptySecurityBuffer(); | |
| 147 | |
| 148 private: | |
| 149 // Reads |sizeof(T)| bytes of an integer type from a little-endian | |
| 150 // buffer. | |
| 151 template <typename T> | |
| 152 bool ReadUInt(T* value); | |
| 153 | |
| 154 // Sets the cursor position. This is used when reading payloads to | |
| 155 // move the cursor to the start of the payload indicated by the | |
| 156 // security buffer. | |
| 157 bool SetCursor(size_t cursor); | |
| 158 | |
| 159 uint8_t GetByteAtCursor() const { | |
| 160 DCHECK(!IsEndOfBuffer()); | |
| 161 return *(GetBufferAtCursor()); | |
| 162 } | |
| 163 | |
| 164 const base::StringPiece buffer_; | |
| 165 size_t cursor_; | |
| 166 | |
| 167 DISALLOW_COPY_AND_ASSIGN(NtlmBufferReader); | |
| 168 }; | |
| 169 | |
| 170 } // namespace net | |
| 171 | |
| 172 #endif // NET_BASE_NTLM_BUFFER_READER_H_ | |
| OLD | NEW |