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

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

Issue 2879353002: Add a buffer reader/writer for NTLM. (Closed)
Patch Set: Rebase 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 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 // Read* methods read from the buffer at the current cursor position and
26 // perform any necessary type conversion and provide the data in out params.
27 // After a successful read the cursor position is advanced past the read
28 // field.
29 //
30 // Failed reads leave the internal cursor at the same position as before the
31 // call.
32 //
33 // Read*Payload methods first reads a security buffer (see
34 // |ReadSecurityBuffer|), then reads the requested payload from the offset
35 // and length stated in the security buffer.
36 //
37 // If the length and offset in the security buffer would cause a read outside
38 // the message buffer the payload will not be read and the function will
39 // return false.
40 //
41 // Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol
42 // Specification version 28.0 [1]
43 //
44 // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
45 class NET_EXPORT_PRIVATE NtlmBufferReader {
46 public:
47 explicit NtlmBufferReader(base::StringPiece buffer);
48
49 // This class does not take ownership of |ptr| so the caller must ensure
50 // that the buffer outlives the |NtlmBufferReader|.
51 NtlmBufferReader(const uint8_t* ptr, size_t len);
52 ~NtlmBufferReader();
53
54 size_t GetLength() const { return buffer_.length(); }
55 size_t GetCursor() const { return cursor_; }
56 bool IsEndOfBuffer() const { return cursor_ >= GetLength(); }
57
58 // Returns true if there are |len| more bytes between the current cursor
59 // position and the end of the buffer.
60 bool CanRead(size_t len) const;
61
62 // Returns true if there are |len| more bytes between |offset| and the end
63 // of the buffer. The cursor position is not used or modified.
64 bool CanReadFrom(size_t offset, size_t len) const;
65
66 // Returns true if it would be possible to read the payload described by the
67 // security buffer.
68 bool CanReadFrom(ntlm::SecurityBuffer sec_buf) const {
69 return CanReadFrom(sec_buf.offset, sec_buf.length);
70 }
71
72 // Reads a 16 bit value (little endian) as a uint16_t. If there are not 16
73 // more bits available it returns false.
74 bool ReadUInt16(uint16_t* value);
asanka 2017/06/16 03:21:29 To be pedantic, the Read*s, Skip*s, and Write*s sh
zentaro 2017/06/21 00:38:47 Done.
75
76 // Reads a 32 bit value (little endian) as a uint32_t. If there are not 32
77 // more bits available it returns false.
78 bool ReadUInt32(uint32_t* value);
79
80 // Reads a 64 bit value (little endian) as a uint64_t. If there are not 64
81 // more bits available it returns false.
82 bool ReadUInt64(uint64_t* value);
83
84 // Calls |ReadUInt32| and returns it cast as |NegotiateFlags|. No
85 // validation of the value takes place.
86 bool ReadFlags(ntlm::NegotiateFlags* flags);
87
88 // Reads |len| bytes and copies them into |buffer|.
89 bool ReadBytes(uint8_t* buffer, size_t len);
90
91 // A security buffer is an 8 byte structure that defines the offset and
92 // length of a payload (string, struct or byte array) that appears after the
93 // fixed part of the message.
94 //
95 // The structure is (little endian fields):
96 // uint16 - |length| Length of payload
97 // uint16 - Allocation (this is always ignored and not returned)
98 // uint32 - |offset| Offset from start of message
99 bool ReadSecurityBuffer(ntlm::SecurityBuffer* sec_buf);
100
101 // Reads |len| bytes into the std::string value. Technically these are
102 // actually in the OEM character set. In practice the implementation
103 // just treats any of these strings as an opaque byte sequence.
104 bool ReadUtf8String(std::string* value, size_t len);
105
106 // Reads |len| bytes as a UTF-16 string with little-endian byte order.
107 bool ReadUtf16String(base::string16* value, size_t len);
108
109 // There are 3 message types Negotiate (sent by client), Challenge (sent by
110 // server), and Authenticate (sent by client).
111 //
112 // This reads the message type from the header and will return false if the
113 // value is invalid.
114 bool ReadMessageType(ntlm::MessageType* message_type);
115
116 // First reads a security buffer (see |ReadSecurityBuffer|), then verifies
117 // that the offset and length it states are within the message, then
118 // reads those bytes from the payload part of the message into a
119 // std::string.
120 //
121 // If the security buffer can't be read or the values in the security buffer
122 // are outside the bounds of the message then false will be returned.
123 //
124 // In the case of failure the cursor will remain as if it never read the
125 // security buffer. In the case of success the cursor will point after the
126 // security buffer.
127 //
128 // NOTE: Technically in NTLM 8-bit strings are in the OEM character set,
129 // however we never try to interpret these strings as anything other than
130 // a sequence of bytes, so the actual encoding is not relevant.
131 bool ReadUtf8Payload(std::string* value);
asanka 2017/06/16 03:21:29 Yeah, I was only referring to the Write* cases whe
zentaro 2017/06/21 00:38:47 Read*String and Read*StringPayload methods were on
132
133 // Reads a security buffer (see |ReadSecurityBuffer|), then verifies
134 // that the offset and length it states are within the message, then
135 // reads those bytes from the payload part of the message into a
136 // base::string16. The 16 bit characters within the string are read
137 // little endian.
138 //
139 // If the security buffer can't be read or the values in the security buffer
140 // are outside the bounds of the message then false will be returned.
141 //
142 // In the case of failure the cursor will remain as if it never read the
143 // security buffer. In the case of success the cursor will point after the
144 // security buffer.
145 bool ReadUtf16Payload(base::string16* value);
146
147 // First reads a security buffer (see |ReadSecurityBuffer|), then verifies
148 // that the offset and length it states are within the message, then
149 // reads those bytes from the payload and copies them into the provided
150 // |buffer|.
151 //
152 // If the security buffer can't be read or the values in the security buffer
153 // are outside the bounds of the message or |buffer_len| is less than the
154 // size of the payload then false will be returned.
155 //
156 // In the case of failure the cursor will remain as if it never read the
157 // security buffer. In the case of success the cursor will point after the
158 // security buffer.
159 bool ReadBytesPayload(uint8_t* buffer, size_t buffer_len);
160
161 // Skips over a security buffer field without reading the fields. This is
162 // the equivalent of advancing the cursor 8 bytes. Returns false if there
163 // are less than 8 bytes left in the buffer.
164 bool SkipSecurityBuffer();
165
166 // Skips over the security buffer without returning the values, but fails if
167 // the values would cause a read outside the buffer if the payload was
168 // actually read.
169 bool SkipSecurityBufferWithValidation();
170
171 // Skips over |count| bytes in the buffer. Returns false if there is not
172 // |count| bytes left in the buffer.
173 bool SkipBytes(size_t count);
174
175 // Reads and returns true if the next 8 bytes matches the signature in an
176 // NTLM message "NTLMSSP\0". The cursor advances if the the signature
177 // is matched.
178 bool MatchSignature();
179
180 // Performs |ReadMessageType| and returns true if the value is
181 // |message_type|. If the read fails or the message type does not match
182 // the cursor does not move.
183 bool MatchMessageType(ntlm::MessageType message_type);
184
185 // Performs |MatchSignature| then |MatchMessageType|.
186 bool MatchMessageHeader(ntlm::MessageType message_type);
187
188 // Performs |ReadBytes(count)| and returns true if the contents is all
189 // zero.
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. If the read fails or the message type does not match
194 // the cursor does not move.
195 bool MatchEmptySecurityBuffer();
196
197 private:
198 // Reads |sizeof(T)| bytes of an integer type from a little-endian buffer.
199 template <typename T>
200 bool ReadUInt(T* value);
201
202 // Sets the cursor position. This is used when reading payloads to move the
203 // cursor to the start of the payload indicated by the security buffer.
204 // The caller should use |GetLength|, |CanRead|, or |CanReadFrom| to verify
205 // the bounds before calling this method.
206 void SetCursor(size_t cursor);
207
208 // Advances the cursor by |count| bytes. The caller should use|GetLength|,
209 // |CanRead|, or |CanReadFrom| to verify the bounds before calling this
210 // method.
211 void AdvanceCursor(size_t count) { SetCursor(GetCursor() + count); }
212
213 // Returns a constant pointer to the start of the buffer.
214 const uint8_t* GetBufferPtr() const {
215 return reinterpret_cast<const uint8_t*>(buffer_.data());
216 }
217
218 // Returns a pointer to the underlying buffer at the current cursor
219 // position.
220 const uint8_t* GetBufferAtCursor() const { return GetBufferPtr() + cursor_; }
221
222 // Returns the byte at the current cursor position.
223 uint8_t GetByteAtCursor() const {
224 DCHECK(!IsEndOfBuffer());
225 return *(GetBufferAtCursor());
226 }
227
228 const base::StringPiece buffer_;
229 size_t cursor_;
230
231 DISALLOW_COPY_AND_ASSIGN(NtlmBufferReader);
232 };
233
234 } // namespace net
235
236 #endif // NET_BASE_NTLM_BUFFER_READER_H_
OLDNEW
« no previous file with comments | « net/http/ntlm.h ('k') | net/http/ntlm_buffer_reader.cc » ('j') | net/http/ntlm_buffer_reader.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698