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

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

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 #include "net/http/ntlm_buffer_reader.h"
6
7 #include <string.h>
8
9 #include "base/logging.h"
10
11 namespace net {
12
13 #if defined(ARCH_CPU_LITTLE_ENDIAN)
14 #define IS_LITTLE_ENDIAN 1
15 #undef IS_BIG_ENDIAN
16 #elif defined(ARCH_CPU_BIG_ENDIAN)
17 #define IS_BIG_ENDIAN 1
18 #undef IS_LITTLE_ENDIAN
19 #else
20 #error "Unknown endianness"
21 #endif
22
23 NtlmBufferReader::NtlmBufferReader(const base::StringPiece buffer)
24 : buffer_(buffer), cursor_(0) {
25 DCHECK(buffer.data() != nullptr);
26 }
27
28 NtlmBufferReader::NtlmBufferReader(const uint8_t* ptr, size_t len)
29 : NtlmBufferReader(
30 base::StringPiece(reinterpret_cast<const char*>(ptr), len)) {}
31
32 NtlmBufferReader::~NtlmBufferReader() {}
33
34 bool NtlmBufferReader::CanRead(size_t len) const {
35 return CanReadFrom(cursor_, len);
36 }
37
38 bool NtlmBufferReader::CanReadFrom(size_t offset, size_t len) const {
39 if (len == 0)
40 return true;
41
42 return (offset + len > offset) && (offset + len <= GetLength());
43 }
44
45 bool NtlmBufferReader::SetCursor(size_t cursor) {
46 if (cursor > GetLength())
47 return false;
48
49 cursor_ = cursor;
50 return true;
51 }
52
53 bool NtlmBufferReader::ReadUInt16(uint16_t* value) {
54 return ReadUInt<uint16_t>(value);
55 }
56
57 bool NtlmBufferReader::ReadUInt32(uint32_t* value) {
58 return ReadUInt<uint32_t>(value);
59 }
60
61 bool NtlmBufferReader::ReadUInt64(uint64_t* value) {
62 return ReadUInt<uint64_t>(value);
63 }
64
65 template <typename T>
66 bool NtlmBufferReader::ReadUInt(T* value) {
67 size_t int_size = sizeof(T);
68 if (!CanRead(int_size))
69 return false;
70
71 *value = 0;
72 for (size_t i = 0; i < int_size; i++) {
73 *value += static_cast<T>(GetByteAtCursor()) << (i * 8);
74 cursor_++;
75 }
76
77 return true;
78 }
79
80 bool NtlmBufferReader::ReadBytes(uint8_t* buffer, size_t len) {
81 if (!CanRead(len))
82 return false;
83
84 memcpy(reinterpret_cast<void*>(buffer),
85 reinterpret_cast<const void*>(GetBufferAtCursor()), len);
86
87 cursor_ += len;
88 return true;
89 }
90
91 bool NtlmBufferReader::ReadSecurityBuffer(uint16_t* length, uint32_t* offset) {
92 if (!CanRead(NtlmMessage::SECURITY_BUFFER_LEN))
93 return false;
94
95 uint16_t ignored;
96
97 if (ReadUInt16(length) && ReadUInt16(&ignored) && ReadUInt32(offset))
98 return true;
99
100 NOTREACHED();
101 return false;
102 }
103
104 bool NtlmBufferReader::ReadAsciiString(std::string* value, size_t num_bytes) {
105 if (!CanRead(num_bytes))
106 return false;
107
108 value->assign(reinterpret_cast<const char*>(GetBufferAtCursor()), num_bytes);
109 cursor_ += num_bytes;
110 return true;
111 }
112
113 bool NtlmBufferReader::ReadUnicodeString(base::string16* value,
114 size_t num_bytes) {
115 if (!CanRead(num_bytes) || (num_bytes % 2 != 0))
116 return false;
117
118 value->assign(reinterpret_cast<const base::char16*>(GetBufferAtCursor()),
119 num_bytes / 2);
120 #if IS_BIG_ENDIAN
Ryan Sleevi 2017/05/30 19:02:22 Is this right? That you swap the string based on t
zentaro 2017/06/05 17:28:44 I think so. I added a comment. Do we ever run unit
121 uint8_t* ptr = reinterpret_cast<uint8_t*>(value->c_str());
122 for (int i = 0; i < num_bytes; i += 2) {
123 std::swap(ptr[i], ptr[i + 1]);
124 }
125 #endif
126 cursor_ += num_bytes;
127 return true;
128 }
129
130 bool NtlmBufferReader::ReadUnicodePayload(base::string16* value) {
131 uint16_t length;
132 uint32_t offset;
133 // First read the security buffer.
134 if (!ReadSecurityBuffer(&length, &offset))
135 return false;
136
137 if (!CanReadFrom(offset, length)) {
138 cursor_ -= NtlmMessage::SECURITY_BUFFER_LEN;
139 return false;
140 }
141
142 size_t old_cursor = GetCursor();
143 DCHECK(SetCursor(offset));
144 DCHECK(ReadUnicodeString(value, length));
145 DCHECK(SetCursor(old_cursor));
Ryan Sleevi 2017/05/30 19:02:22 Anything inside a DCHECK() can be optimized out -
zentaro 2017/06/05 17:28:44 Oops. Done.
146 return true;
147 }
148
149 bool NtlmBufferReader::ReadBytesPayload(uint8_t* buffer, size_t buffer_len) {
150 uint16_t length;
151 uint32_t offset;
152 // First read the security buffer.
153 if (!ReadSecurityBuffer(&length, &offset))
154 return false;
155
156 if (!CanReadFrom(offset, length) || length > buffer_len) {
157 cursor_ -= NtlmMessage::SECURITY_BUFFER_LEN;
158 return false;
159 }
160
161 size_t old_cursor = GetCursor();
162 DCHECK(SetCursor(offset));
163 DCHECK(ReadBytes(buffer, length));
164 DCHECK(SetCursor(old_cursor));
165 return true;
166 }
167
168 bool NtlmBufferReader::ReadAsciiPayload(std::string* value) {
169 uint16_t length;
170 uint32_t offset;
171 // First read the security buffer.
172 if (!ReadSecurityBuffer(&length, &offset))
173 return false;
174
175 if (!CanReadFrom(offset, length)) {
176 cursor_ -= NtlmMessage::SECURITY_BUFFER_LEN;
177 return false;
178 }
179
180 size_t old_cursor = GetCursor();
181 DCHECK(SetCursor(offset));
182 DCHECK(ReadAsciiString(value, length));
183 DCHECK(SetCursor(old_cursor));
184 return true;
185 }
186
187 bool NtlmBufferReader::ReadMessageType(NtlmMessage::MessageType* message_type) {
188 uint32_t temp;
189 if (!ReadUInt32(&temp))
190 return false;
191
192 if (temp != NtlmMessage::MESSAGE_NEGOTIATE &&
193 temp != NtlmMessage::MESSAGE_CHALLENGE &&
194 temp != NtlmMessage::MESSAGE_AUTHENTICATE) {
195 cursor_ -= sizeof(uint32_t);
196 return false;
197 }
198
199 *message_type = static_cast<NtlmMessage::MessageType>(temp);
200 return true;
201 }
202
203 bool NtlmBufferReader::SkipSecurityBuffer() {
204 return SkipBytes(NtlmMessage::SECURITY_BUFFER_LEN);
205 }
206
207 bool NtlmBufferReader::SkipSecurityBufferWithValidation() {
208 uint16_t length;
209 uint32_t offset;
210 if (!ReadSecurityBuffer(&length, &offset)) {
211 return false;
212 }
213
214 // If the security buffer indicates to read outside
215 // the message buffer then fail.
216 if (!CanReadFrom(offset, length)) {
217 cursor_ -= NtlmMessage::SECURITY_BUFFER_LEN;
218 return false;
219 }
220
221 return true;
222 }
223
224 bool NtlmBufferReader::SkipBytes(size_t count) {
225 if (!CanRead(count))
226 return false;
227
228 cursor_ += count;
229 return true;
230 }
231
232 bool NtlmBufferReader::MatchSignature() {
233 if (!CanRead(NtlmMessage::SIGNATURE_LEN))
234 return false;
235
236 if (memcmp(NtlmMessage::SIGNATURE, GetBufferAtCursor(),
237 NtlmMessage::SIGNATURE_LEN) != 0)
238 return false;
239
240 cursor_ += NtlmMessage::SIGNATURE_LEN;
241 return true;
242 }
243
244 bool NtlmBufferReader::MatchMessageType(NtlmMessage::MessageType message_type) {
245 size_t old_cursor = cursor_;
246 NtlmMessage::MessageType actual_message_type;
247 if (!ReadMessageType(&actual_message_type))
248 return false;
249
250 if (actual_message_type != message_type) {
251 cursor_ = old_cursor;
252 return false;
253 }
254
255 return true;
256 }
257
258 bool NtlmBufferReader::MatchMessageHeader(
259 NtlmMessage::MessageType message_type) {
260 size_t old_cursor = cursor_;
261 if (MatchSignature() && MatchMessageType(message_type))
262 return true;
263
264 cursor_ = old_cursor;
265 return false;
266 }
267
268 bool NtlmBufferReader::MatchZeros(size_t count) {
269 if (!CanRead(count))
270 return false;
271
272 for (size_t i = 0; i < count; i++) {
273 if (GetBufferAtCursor()[i] != 0)
274 return false;
275 }
276
277 cursor_ += count;
278 return true;
279 }
280
281 bool NtlmBufferReader::MatchEmptySecurityBuffer() {
282 return MatchZeros(NtlmMessage::SECURITY_BUFFER_LEN);
283 }
284
285 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698