Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(554)

Side by Side Diff: net/http/ntlm_buffer_reader.h

Issue 2879353002: Add a buffer reader/writer for NTLM. (Closed)
Patch Set: Add a buffer reader/writer for NTLM. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698