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.h" | |
16 | |
17 namespace net { | |
18 | |
19 // Supports various bounds-checked low level buffer operations required by an | |
20 // NTLM implementation. | |
21 // | |
22 // The class supports sequential read of a provided buffer. All reads perform | |
23 // bounds checking to ensure enough space is remaining in the buffer. | |
24 // | |
25 // | |
Ryan Sleevi
2017/06/08 18:36:34
Delete newline?
zentaro
2017/06/12 23:12:06
Done.
| |
26 // Read* methods read from the buffer at the current cursor position and | |
27 // perform any necessary type conversion and provide the data in out params. | |
28 // After a successful read the cursor position is advanced past the read | |
29 // field. | |
30 // | |
31 // Failed reads leave the internal cursor at the same position as before the | |
32 // call. | |
33 // | |
34 // | |
Ryan Sleevi
2017/06/08 18:36:33
Delete newline?
zentaro
2017/06/12 23:12:06
Done.
| |
35 // Read*Payload methods first read a security buffer see |ReadSecurityBuffer| | |
Ryan Sleevi
2017/06/08 18:36:34
nit:
s/see |ReadSecurityBuffer|/(see ReadSecurityB
zentaro
2017/06/12 23:12:06
Done.
| |
36 // then read the requested payload from the offset and length stated in the | |
37 // security buffer. | |
38 // | |
39 // If the length and offset in the security buffer would cause a read outside | |
40 // the message buffer the payload will not be read and the function will | |
41 // return false. | |
42 // | |
43 // The cursor will remain as it was before the call as if the security buffer | |
44 // had not been read. | |
Ryan Sleevi
2017/06/08 18:36:34
From looking at your documentatino for Read*Payloa
zentaro
2017/06/12 23:12:05
Done.
| |
45 // | |
Ryan Sleevi
2017/06/08 18:36:33
Delete newline?
zentaro
2017/06/12 23:12:05
Done.
| |
46 // | |
47 // Skip* methods skip the cursor over that same number of bytes that the | |
48 // equivalent Read method would without reading or returning the values. | |
Ryan Sleevi
2017/06/08 18:36:33
Deletable? :)
zentaro
2017/06/12 23:12:06
Done.
| |
49 // | |
50 // | |
Ryan Sleevi
2017/06/08 18:36:33
Delete newline?
zentaro
2017/06/12 23:12:06
Done.
| |
51 // Match* methods are used to validate fields in the buffer that should have | |
52 // expected values, such as signatures or message identifiers. | |
Ryan Sleevi
2017/06/08 18:36:34
Deletable?
zentaro
2017/06/12 23:12:06
Done.
| |
53 // | |
54 // | |
Ryan Sleevi
2017/06/08 18:36:33
Delete newline?
zentaro
2017/06/12 23:12:05
Done.
| |
55 // Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol | |
56 // Specification version 28.0 [1] | |
57 // | |
58 // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx | |
59 class NET_EXPORT_PRIVATE NtlmBufferReader { | |
60 public: | |
61 explicit NtlmBufferReader(base::StringPiece buffer); | |
asanka
2017/06/08 18:44:58
Obvious, but add a short note here and below that
zentaro
2017/06/12 23:12:05
Done.
| |
62 NtlmBufferReader(const uint8_t* ptr, size_t len); | |
63 ~NtlmBufferReader(); | |
64 | |
65 size_t GetLength() const { return buffer_.length(); } | |
66 size_t GetCursor() const { return cursor_; } | |
67 bool IsEndOfBuffer() const { return cursor_ >= GetLength(); } | |
68 | |
69 // Returns true if there are |len| more bytes between the current cursor | |
70 // position and the end of the buffer. | |
71 bool CanRead(size_t len) const; | |
72 | |
73 // Returns true if there are |len| more bytes between |offset| and the end | |
74 // of the buffer. The cursor position is not used or modified. | |
75 bool CanReadFrom(size_t offset, size_t len) const; | |
76 | |
77 // Returns true if it would be possible to read the payload described by the | |
78 // security buffer. | |
79 bool CanReadFrom(ntlm::SecurityBuffer sec_buf) const { | |
80 return CanReadFrom(sec_buf.offset, sec_buf.length); | |
81 } | |
82 | |
83 // Reads a 16 bit value (little endian) as a uint16_t. If there are not 16 | |
84 // more bits available it returns false. | |
85 bool ReadUInt16(uint16_t* value); | |
86 | |
87 // Reads a 32 bit value (little endian) as a uint32_t. If there are not 32 | |
88 // more bits available it returns false. | |
89 bool ReadUInt32(uint32_t* value); | |
90 | |
91 // Reads a 64 bit value (little endian) as a uint64_t. If there are not 64 | |
92 // more bits available it returns false. | |
93 bool ReadUInt64(uint64_t* value); | |
94 | |
95 // Reads |len| bytes and copies them into |buffer|. | |
96 bool ReadBytes(uint8_t* buffer, size_t len); | |
97 | |
98 // A security buffer is an 8 byte structure that defines the offset and | |
99 // length of a payload (string, struct or byte array) that appears after the | |
100 // fixed part of the message. | |
101 // | |
102 // The structure is (little endian fields): | |
103 // uint16 - |length| Length of payload | |
104 // uint16 - Allocation (this is always ignored and not returned) | |
105 // uint32 - |offset| Offset from start of message | |
106 bool ReadSecurityBuffer(ntlm::SecurityBuffer* sec_buf); | |
107 | |
108 // Reads |len| bytes into the std::string value. Technically these are | |
109 // actually in the OEM character set. In practice the implementation | |
110 // just treats any of these strings as an opaque byte sequence. | |
111 bool ReadAsciiString(std::string* value, size_t len); | |
112 | |
113 // Reads |len| bytes as a UTF-16 string with little-endian byte order. | |
114 bool ReadUnicodeString(base::string16* value, size_t len); | |
115 | |
116 // There are 3 message types Negotiate (sent by client), Challenge (sent by | |
117 // server), and Authenticate (sent by client). | |
118 // | |
119 // This reads the message type from the header and will return false if the | |
120 // value is invalid. | |
121 bool ReadMessageType(ntlm::MessageType* message_type); | |
122 | |
123 // First reads a security buffer (see |ReadSecurityBuffer|), then verifies | |
Ryan Sleevi
2017/06/08 18:36:33
s/First reads/Reads/
zentaro
2017/06/12 23:12:06
Done.
| |
124 // that the offset and length it states are within the message, then | |
125 // reads those bytes from the payload part of the message into a | |
126 // std::string. | |
127 // | |
128 // If the security buffer can't be read or the values in the security buffer | |
129 // are outside the bounds of the message then false will be returned. | |
130 // | |
131 // In the case of failure the cursor will remain as if it never read the | |
132 // security buffer. In the case of success the cursor will point after the | |
133 // security buffer. | |
134 bool ReadAsciiPayload(std::string* value); | |
135 | |
136 // First reads a security buffer (see |ReadSecurityBuffer|), then verifies | |
137 // that the offset and length it states are within the message, then | |
138 // reads those bytes from the payload part of the message into a | |
139 // base::string16. The 16 bit characters within the string are read | |
140 // little endian. | |
141 // | |
142 // If the security buffer can't be read or the values in the security buffer | |
143 // are outside the bounds of the message then false will be returned. | |
144 // | |
145 // In the case of failure the cursor will remain as if it never read the | |
146 // security buffer. In the case of success the cursor will point after the | |
147 // security buffer. | |
148 bool ReadUnicodePayload(base::string16* value); | |
149 | |
150 // First reads a security buffer (see |ReadSecurityBuffer|), then verifies | |
151 // that the offset and length it states are within the message, then | |
152 // reads those bytes from the payload and copies them into the provided | |
153 // |buffer|. | |
154 // | |
155 // If the security buffer can't be read or the values in the security buffer | |
156 // are outside the bounds of the message or |buffer_len| is less than the | |
157 // size of the payload then false will be returned. | |
158 // | |
159 // In the case of failure the cursor will remain as if it never read the | |
160 // security buffer. In the case of success the cursor will point after the | |
161 // security buffer. | |
162 bool ReadBytesPayload(uint8_t* buffer, size_t buffer_len); | |
163 | |
164 // Skips over a security buffer field without reading the fields. This is | |
165 // the equivalent of advancing the cursor 8 bytes. Returns false if there | |
166 // are less than 8 bytes left in the buffer. | |
167 bool SkipSecurityBuffer(); | |
168 | |
169 // Skips over the security buffer without returning the values, but fails if | |
170 // the values would cause a read outside the buffer if the payload was | |
171 // actually read. | |
172 bool SkipSecurityBufferWithValidation(); | |
173 | |
174 // Skips over |count| bytes in the buffer. Returns false if there is not | |
175 // |count| bytes left in the buffer. | |
176 bool SkipBytes(size_t count); | |
177 | |
178 // Reads and returns true if the next 8 bytes matches the signature in an | |
179 // NTLM message "NTLMSSP\0" | |
180 bool MatchSignature(); | |
Ryan Sleevi
2017/06/08 18:36:33
Do Match() methods update the cursor or not? From
zentaro
2017/06/12 23:12:06
They do. Made more explicit.
| |
181 | |
182 // Reads the message type from the cursor and returns true if it is | |
183 // |message_type|. | |
184 bool MatchMessageType(ntlm::MessageType message_type); | |
185 | |
186 // Performs |MatchSignature| then |MatchMessageType|. | |
187 bool MatchMessageHeader(ntlm::MessageType message_type); | |
188 | |
189 // Reads and returns true if there are |count| bytes of zeros. | |
190 bool MatchZeros(size_t count); | |
191 | |
192 // Reads and returns true if the next 8 bytes contain an empty ie. all zero | |
193 // security buffer. | |
asanka
2017/06/08 18:44:58
It's not clear to me whether the an empty security
zentaro
2017/06/12 23:12:06
I've seen the part of the spec that says that but
asanka
2017/06/16 03:21:28
It seems the spec if pretty consistent about requi
zentaro
2017/06/21 00:38:46
Well it says the length MUST be zero but the offse
| |
194 bool MatchEmptySecurityBuffer(); | |
195 | |
196 private: | |
197 // Reads |sizeof(T)| bytes of an integer type from a little-endian buffer. | |
198 template <typename T> | |
199 bool ReadUInt(T* value); | |
200 | |
201 // Sets the cursor position. This is used when reading payloads to move the | |
202 // cursor to the start of the payload indicated by the security buffer. | |
203 bool SetCursor(size_t cursor); | |
204 | |
205 // Returns a constant pointer to the start of the buffer. | |
206 const uint8_t* GetBufferPtr() const { | |
207 return reinterpret_cast<const uint8_t*>(buffer_.data()); | |
208 } | |
209 | |
210 // Returns a pointer to the underlying buffer at the current cursor | |
211 // position. | |
212 const uint8_t* GetBufferAtCursor() const { return GetBufferPtr() + cursor_; } | |
213 | |
214 // Returns the byte at the current cursor position. | |
215 uint8_t GetByteAtCursor() const { | |
216 DCHECK(!IsEndOfBuffer()); | |
217 return *(GetBufferAtCursor()); | |
218 } | |
219 | |
220 const base::StringPiece buffer_; | |
221 size_t cursor_; | |
222 | |
223 DISALLOW_COPY_AND_ASSIGN(NtlmBufferReader); | |
224 }; | |
225 | |
226 } // namespace net | |
227 | |
228 #endif // NET_BASE_NTLM_BUFFER_READER_H_ | |
OLD | NEW |