1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9
10 #include "net/ntlm/ntlm_buffer_reader.h"
11
12 #include "base/strings/utf_string_conversions.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace net::ntlm {
16
TEST(NtlmBufferReaderTest,Initialization)17 TEST(NtlmBufferReaderTest, Initialization) {
18 const uint8_t buf[1] = {0};
19 NtlmBufferReader reader(buf);
20
21 ASSERT_EQ(std::size(buf), reader.GetLength());
22 ASSERT_EQ(0u, reader.GetCursor());
23 ASSERT_FALSE(reader.IsEndOfBuffer());
24 ASSERT_TRUE(reader.CanRead(1));
25 ASSERT_FALSE(reader.CanRead(2));
26 ASSERT_TRUE(reader.CanReadFrom(0, 1));
27 ASSERT_TRUE(reader.CanReadFrom(SecurityBuffer(0, 1)));
28 ASSERT_FALSE(reader.CanReadFrom(1, 1));
29 ASSERT_FALSE(reader.CanReadFrom(SecurityBuffer(1, 1)));
30 ASSERT_FALSE(reader.CanReadFrom(0, 2));
31 ASSERT_FALSE(reader.CanReadFrom(SecurityBuffer(0, 2)));
32
33 // With length=0 the offset can be out of bounds.
34 ASSERT_TRUE(reader.CanReadFrom(99, 0));
35 ASSERT_TRUE(reader.CanReadFrom(SecurityBuffer(99, 0)));
36 }
37
TEST(NtlmBufferReaderTest,EmptyBuffer)38 TEST(NtlmBufferReaderTest, EmptyBuffer) {
39 std::vector<uint8_t> b;
40 NtlmBufferReader reader(b);
41
42 ASSERT_EQ(0u, reader.GetCursor());
43 ASSERT_EQ(0u, reader.GetLength());
44 ASSERT_TRUE(reader.CanRead(0));
45 ASSERT_FALSE(reader.CanRead(1));
46 ASSERT_TRUE(reader.IsEndOfBuffer());
47
48 // A read from an empty (zero-byte) source into an empty (zero-byte)
49 // destination buffer should succeed as a no-op.
50 std::vector<uint8_t> dest;
51 ASSERT_TRUE(reader.ReadBytes(dest));
52
53 // A read from a non-empty source into an empty (zero-byte) destination
54 // buffer should succeed as a no-op.
55 std::vector<uint8_t> b2{0x01};
56 NtlmBufferReader reader2(b2);
57 ASSERT_EQ(0u, reader2.GetCursor());
58 ASSERT_EQ(1u, reader2.GetLength());
59
60 ASSERT_TRUE(reader2.CanRead(0));
61 ASSERT_TRUE(reader2.ReadBytes(dest));
62
63 ASSERT_EQ(0u, reader2.GetCursor());
64 ASSERT_EQ(1u, reader2.GetLength());
65 }
66
TEST(NtlmBufferReaderTest,NullBuffer)67 TEST(NtlmBufferReaderTest, NullBuffer) {
68 NtlmBufferReader reader;
69
70 ASSERT_EQ(0u, reader.GetCursor());
71 ASSERT_EQ(0u, reader.GetLength());
72 ASSERT_TRUE(reader.CanRead(0));
73 ASSERT_FALSE(reader.CanRead(1));
74 ASSERT_TRUE(reader.IsEndOfBuffer());
75
76 // A read from a null source into an empty (zero-byte) destination buffer
77 // should succeed as a no-op.
78 std::vector<uint8_t> dest;
79 ASSERT_TRUE(reader.ReadBytes(dest));
80 }
81
TEST(NtlmBufferReaderTest,Read16)82 TEST(NtlmBufferReaderTest, Read16) {
83 const uint8_t buf[2] = {0x22, 0x11};
84 const uint16_t expected = 0x1122;
85
86 NtlmBufferReader reader(buf);
87
88 uint16_t actual;
89 ASSERT_TRUE(reader.ReadUInt16(&actual));
90 ASSERT_EQ(expected, actual);
91 ASSERT_TRUE(reader.IsEndOfBuffer());
92 ASSERT_FALSE(reader.ReadUInt16(&actual));
93 }
94
TEST(NtlmBufferReaderTest,Read32)95 TEST(NtlmBufferReaderTest, Read32) {
96 const uint8_t buf[4] = {0x44, 0x33, 0x22, 0x11};
97 const uint32_t expected = 0x11223344;
98
99 NtlmBufferReader reader(buf);
100
101 uint32_t actual;
102 ASSERT_TRUE(reader.ReadUInt32(&actual));
103 ASSERT_EQ(expected, actual);
104 ASSERT_TRUE(reader.IsEndOfBuffer());
105 ASSERT_FALSE(reader.ReadUInt32(&actual));
106 }
107
TEST(NtlmBufferReaderTest,Read64)108 TEST(NtlmBufferReaderTest, Read64) {
109 const uint8_t buf[8] = {0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
110 const uint64_t expected = 0x1122334455667788;
111
112 NtlmBufferReader reader(buf);
113
114 uint64_t actual;
115 ASSERT_TRUE(reader.ReadUInt64(&actual));
116 ASSERT_EQ(expected, actual);
117 ASSERT_TRUE(reader.IsEndOfBuffer());
118 ASSERT_FALSE(reader.ReadUInt64(&actual));
119 }
120
TEST(NtlmBufferReaderTest,ReadBytes)121 TEST(NtlmBufferReaderTest, ReadBytes) {
122 const uint8_t expected[8] = {0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
123 uint8_t actual[8];
124
125 NtlmBufferReader reader(expected);
126
127 ASSERT_TRUE(reader.ReadBytes(actual));
128 ASSERT_EQ(0, memcmp(actual, expected, std::size(actual)));
129 ASSERT_TRUE(reader.IsEndOfBuffer());
130 ASSERT_FALSE(reader.ReadBytes(base::span(actual, 1u)));
131 }
132
TEST(NtlmBufferReaderTest,ReadSecurityBuffer)133 TEST(NtlmBufferReaderTest, ReadSecurityBuffer) {
134 const uint8_t buf[8] = {0x22, 0x11, 0xFF, 0xEE, 0x88, 0x77, 0x66, 0x55};
135 const uint16_t length = 0x1122;
136 const uint32_t offset = 0x55667788;
137
138 NtlmBufferReader reader(buf);
139
140 SecurityBuffer sec_buf;
141 ASSERT_TRUE(reader.ReadSecurityBuffer(&sec_buf));
142 ASSERT_EQ(length, sec_buf.length);
143 ASSERT_EQ(offset, sec_buf.offset);
144 ASSERT_TRUE(reader.IsEndOfBuffer());
145 ASSERT_FALSE(reader.ReadSecurityBuffer(&sec_buf));
146 }
147
TEST(NtlmBufferReaderTest,ReadSecurityBufferPastEob)148 TEST(NtlmBufferReaderTest, ReadSecurityBufferPastEob) {
149 const uint8_t buf[7] = {0};
150 NtlmBufferReader reader(buf);
151
152 SecurityBuffer sec_buf;
153 ASSERT_FALSE(reader.ReadSecurityBuffer(&sec_buf));
154 }
155
TEST(NtlmBufferReaderTest,ReadPayloadAsBufferReader)156 TEST(NtlmBufferReaderTest, ReadPayloadAsBufferReader) {
157 const uint8_t buf[8] = {0xff, 0xff, 0x11, 0x22, 0x33, 0x44, 0xff, 0xff};
158 const uint32_t expected = 0x44332211;
159 NtlmBufferReader reader(buf);
160 ASSERT_EQ(0u, reader.GetCursor());
161
162 // Create a security buffer with offset 2 and length 4.
163 SecurityBuffer sec_buf(2, 4);
164 NtlmBufferReader sub_reader;
165 ASSERT_EQ(0u, sub_reader.GetLength());
166 ASSERT_EQ(0u, sub_reader.GetCursor());
167
168 // Read the 4 non-0xff bytes from the middle of |buf|.
169 ASSERT_TRUE(reader.ReadPayloadAsBufferReader(sec_buf, &sub_reader));
170
171 // |reader| cursor should not move.
172 ASSERT_EQ(0u, reader.GetCursor());
173 ASSERT_EQ(sec_buf.length, sub_reader.GetLength());
174 ASSERT_EQ(0u, sub_reader.GetCursor());
175
176 // Read from the payload in |sub_reader|.
177 uint32_t actual;
178 ASSERT_TRUE(sub_reader.ReadUInt32(&actual));
179 ASSERT_EQ(expected, actual);
180 ASSERT_TRUE(sub_reader.IsEndOfBuffer());
181 }
182
TEST(NtlmBufferReaderTest,ReadPayloadBadOffset)183 TEST(NtlmBufferReaderTest, ReadPayloadBadOffset) {
184 const uint8_t buf[4] = {0};
185 NtlmBufferReader reader(buf);
186
187 NtlmBufferReader sub_reader;
188 ASSERT_FALSE(
189 reader.ReadPayloadAsBufferReader(SecurityBuffer(4, 1), &sub_reader));
190 }
191
TEST(NtlmBufferReaderTest,ReadPayloadBadLength)192 TEST(NtlmBufferReaderTest, ReadPayloadBadLength) {
193 const uint8_t buf[4] = {0};
194 NtlmBufferReader reader(buf);
195
196 NtlmBufferReader sub_reader;
197 ASSERT_FALSE(
198 reader.ReadPayloadAsBufferReader(SecurityBuffer(3, 2), &sub_reader));
199 }
200
TEST(NtlmBufferReaderTest,SkipSecurityBuffer)201 TEST(NtlmBufferReaderTest, SkipSecurityBuffer) {
202 const uint8_t buf[kSecurityBufferLen] = {0};
203
204 NtlmBufferReader reader(buf);
205 ASSERT_TRUE(reader.SkipSecurityBuffer());
206 ASSERT_TRUE(reader.IsEndOfBuffer());
207 ASSERT_FALSE(reader.SkipSecurityBuffer());
208 }
209
TEST(NtlmBufferReaderTest,SkipSecurityBufferPastEob)210 TEST(NtlmBufferReaderTest, SkipSecurityBufferPastEob) {
211 // The buffer is one byte shorter than security buffer.
212 const uint8_t buf[kSecurityBufferLen - 1] = {0};
213
214 NtlmBufferReader reader(buf);
215 ASSERT_FALSE(reader.SkipSecurityBuffer());
216 }
217
TEST(NtlmBufferReaderTest,SkipSecurityBufferWithValidationEmpty)218 TEST(NtlmBufferReaderTest, SkipSecurityBufferWithValidationEmpty) {
219 const uint8_t buf[kSecurityBufferLen] = {0, 0, 0, 0, 0, 0, 0, 0};
220
221 NtlmBufferReader reader(buf);
222 ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
223 ASSERT_TRUE(reader.IsEndOfBuffer());
224 ASSERT_FALSE(reader.SkipSecurityBufferWithValidation());
225 }
226
TEST(NtlmBufferReaderTest,SkipSecurityBufferWithValidationValid)227 TEST(NtlmBufferReaderTest, SkipSecurityBufferWithValidationValid) {
228 // A valid security buffer that points to the 1 payload byte.
229 const uint8_t buf[kSecurityBufferLen + 1] = {
230 0x01, 0, 0x01, 0, kSecurityBufferLen, 0, 0, 0, 0xFF};
231
232 NtlmBufferReader reader(buf);
233 ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
234 ASSERT_EQ(kSecurityBufferLen, reader.GetCursor());
235 ASSERT_FALSE(reader.SkipSecurityBufferWithValidation());
236 }
237
TEST(NtlmBufferReaderTest,SkipSecurityBufferWithValidationPayloadLengthPastEob)238 TEST(NtlmBufferReaderTest,
239 SkipSecurityBufferWithValidationPayloadLengthPastEob) {
240 // Security buffer with length that points past the end of buffer.
241 const uint8_t buf[kSecurityBufferLen + 1] = {
242 0x02, 0, 0x02, 0, kSecurityBufferLen, 0, 0, 0, 0xFF};
243
244 NtlmBufferReader reader(buf);
245 ASSERT_FALSE(reader.SkipSecurityBufferWithValidation());
246 }
247
TEST(NtlmBufferReaderTest,SkipSecurityBufferWithValidationPayloadOffsetPastEob)248 TEST(NtlmBufferReaderTest,
249 SkipSecurityBufferWithValidationPayloadOffsetPastEob) {
250 // Security buffer with offset that points past the end of buffer.
251 const uint8_t buf[kSecurityBufferLen + 1] = {
252 0x02, 0, 0x02, 0, kSecurityBufferLen + 1, 0, 0, 0, 0xFF};
253
254 NtlmBufferReader reader(buf);
255 ASSERT_FALSE(reader.SkipSecurityBufferWithValidation());
256 }
257
TEST(NtlmBufferReaderTest,SkipSecurityBufferWithValidationZeroLengthPayloadOffsetPastEob)258 TEST(NtlmBufferReaderTest,
259 SkipSecurityBufferWithValidationZeroLengthPayloadOffsetPastEob) {
260 // Security buffer with offset that points past the end of buffer but
261 // length is 0.
262 const uint8_t buf[kSecurityBufferLen] = {0, 0, 0, 0, kSecurityBufferLen + 1,
263 0, 0, 0};
264
265 NtlmBufferReader reader(buf);
266 ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
267 ASSERT_EQ(kSecurityBufferLen, reader.GetCursor());
268 }
269
TEST(NtlmBufferReaderTest,SkipBytes)270 TEST(NtlmBufferReaderTest, SkipBytes) {
271 const uint8_t buf[8] = {0};
272
273 NtlmBufferReader reader(buf);
274
275 ASSERT_TRUE(reader.SkipBytes(std::size(buf)));
276 ASSERT_TRUE(reader.IsEndOfBuffer());
277 ASSERT_FALSE(reader.SkipBytes(std::size(buf)));
278 }
279
TEST(NtlmBufferReaderTest,SkipBytesPastEob)280 TEST(NtlmBufferReaderTest, SkipBytesPastEob) {
281 const uint8_t buf[8] = {0};
282
283 NtlmBufferReader reader(buf);
284
285 ASSERT_FALSE(reader.SkipBytes(std::size(buf) + 1));
286 }
287
TEST(NtlmBufferReaderTest,MatchSignatureTooShort)288 TEST(NtlmBufferReaderTest, MatchSignatureTooShort) {
289 const uint8_t buf[7] = {0};
290
291 NtlmBufferReader reader(buf);
292
293 ASSERT_TRUE(reader.CanRead(7));
294 ASSERT_FALSE(reader.MatchSignature());
295 }
296
TEST(NtlmBufferReaderTest,MatchSignatureNoMatch)297 TEST(NtlmBufferReaderTest, MatchSignatureNoMatch) {
298 // The last byte should be a 0.
299 const uint8_t buf[8] = {'N', 'T', 'L', 'M', 'S', 'S', 'P', 0xff};
300 NtlmBufferReader reader(buf);
301
302 ASSERT_TRUE(reader.CanRead(8));
303 ASSERT_FALSE(reader.MatchSignature());
304 }
305
TEST(NtlmBufferReaderTest,MatchSignatureOk)306 TEST(NtlmBufferReaderTest, MatchSignatureOk) {
307 const uint8_t buf[8] = {'N', 'T', 'L', 'M', 'S', 'S', 'P', 0};
308 NtlmBufferReader reader(buf);
309
310 ASSERT_TRUE(reader.MatchSignature());
311 ASSERT_TRUE(reader.IsEndOfBuffer());
312 }
313
TEST(NtlmBufferReaderTest,ReadInvalidMessageType)314 TEST(NtlmBufferReaderTest, ReadInvalidMessageType) {
315 // Only 0x01, 0x02, and 0x03 are valid message types.
316 const uint8_t buf[4] = {0x04, 0, 0, 0};
317 NtlmBufferReader reader(buf);
318
319 MessageType message_type;
320 ASSERT_FALSE(reader.ReadMessageType(&message_type));
321 }
322
TEST(NtlmBufferReaderTest,ReadMessageTypeNegotiate)323 TEST(NtlmBufferReaderTest, ReadMessageTypeNegotiate) {
324 const uint8_t buf[4] = {static_cast<uint8_t>(MessageType::kNegotiate), 0, 0,
325 0};
326 NtlmBufferReader reader(buf);
327
328 MessageType message_type;
329 ASSERT_TRUE(reader.ReadMessageType(&message_type));
330 ASSERT_EQ(MessageType::kNegotiate, message_type);
331 ASSERT_TRUE(reader.IsEndOfBuffer());
332 }
333
TEST(NtlmBufferReaderTest,ReadMessageTypeChallenge)334 TEST(NtlmBufferReaderTest, ReadMessageTypeChallenge) {
335 const uint8_t buf[4] = {static_cast<uint8_t>(MessageType::kChallenge), 0, 0,
336 0};
337 NtlmBufferReader reader(buf);
338
339 MessageType message_type;
340 ASSERT_TRUE(reader.ReadMessageType(&message_type));
341 ASSERT_EQ(MessageType::kChallenge, message_type);
342 ASSERT_TRUE(reader.IsEndOfBuffer());
343 }
344
TEST(NtlmBufferReaderTest,ReadTargetInfoEolOnly)345 TEST(NtlmBufferReaderTest, ReadTargetInfoEolOnly) {
346 // Buffer contains only an EOL terminator.
347 const uint8_t buf[4] = {0, 0, 0, 0};
348
349 NtlmBufferReader reader(buf);
350
351 std::vector<AvPair> av_pairs;
352 ASSERT_TRUE(reader.ReadTargetInfo(std::size(buf), &av_pairs));
353 ASSERT_TRUE(reader.IsEndOfBuffer());
354 ASSERT_TRUE(av_pairs.empty());
355 }
356
TEST(NtlmBufferReaderTest,ReadTargetInfoEmpty)357 TEST(NtlmBufferReaderTest, ReadTargetInfoEmpty) {
358 NtlmBufferReader reader;
359
360 std::vector<AvPair> av_pairs;
361 ASSERT_TRUE(reader.ReadTargetInfo(0, &av_pairs));
362 ASSERT_TRUE(reader.IsEndOfBuffer());
363 ASSERT_TRUE(av_pairs.empty());
364 }
365
TEST(NtlmBufferReaderTest,ReadTargetInfoTimestampAndEolOnly)366 TEST(NtlmBufferReaderTest, ReadTargetInfoTimestampAndEolOnly) {
367 // Buffer contains a timestamp av pair and an EOL terminator.
368 const uint8_t buf[16] = {0x07, 0, 0x08, 0, 0x11, 0x22, 0x33, 0x44,
369 0x55, 0x66, 0x77, 0x88, 0, 0, 0, 0};
370 const uint64_t expected_timestamp = 0x8877665544332211;
371
372 NtlmBufferReader reader(buf);
373
374 std::vector<AvPair> av_pairs;
375 ASSERT_TRUE(reader.ReadTargetInfo(std::size(buf), &av_pairs));
376 ASSERT_TRUE(reader.IsEndOfBuffer());
377 ASSERT_EQ(1u, av_pairs.size());
378
379 // Verify the timestamp av pair.
380 ASSERT_EQ(TargetInfoAvId::kTimestamp, av_pairs[0].avid);
381 ASSERT_EQ(sizeof(uint64_t), av_pairs[0].avlen);
382 ASSERT_EQ(sizeof(uint64_t), av_pairs[0].buffer.size());
383 ASSERT_EQ(expected_timestamp, av_pairs[0].timestamp);
384 }
385
TEST(NtlmBufferReaderTest,ReadTargetInfoFlagsAndEolOnly)386 TEST(NtlmBufferReaderTest, ReadTargetInfoFlagsAndEolOnly) {
387 // Buffer contains a flags av pair with the MIC bit and an EOL terminator.
388 const uint8_t buf[12] = {0x06, 0, 0x04, 0, 0x02, 0, 0, 0, 0, 0, 0, 0};
389
390 NtlmBufferReader reader(buf);
391
392 std::vector<AvPair> av_pairs;
393 ASSERT_TRUE(reader.ReadTargetInfo(std::size(buf), &av_pairs));
394 ASSERT_TRUE(reader.IsEndOfBuffer());
395 ASSERT_EQ(1u, av_pairs.size());
396
397 // Verify the flags av pair.
398 ASSERT_EQ(TargetInfoAvId::kFlags, av_pairs[0].avid);
399 ASSERT_EQ(sizeof(TargetInfoAvFlags), av_pairs[0].avlen);
400 ASSERT_EQ(TargetInfoAvFlags::kMicPresent, av_pairs[0].flags);
401 }
402
TEST(NtlmBufferReaderTest,ReadTargetInfoTooSmall)403 TEST(NtlmBufferReaderTest, ReadTargetInfoTooSmall) {
404 // Target info must least contain enough space for a terminator pair.
405 const uint8_t buf[3] = {0};
406
407 NtlmBufferReader reader(buf);
408
409 std::vector<AvPair> av_pairs;
410 ASSERT_FALSE(reader.ReadTargetInfo(std::size(buf), &av_pairs));
411 }
412
TEST(NtlmBufferReaderTest,ReadTargetInfoInvalidTimestampSize)413 TEST(NtlmBufferReaderTest, ReadTargetInfoInvalidTimestampSize) {
414 // Timestamps must be 64 bits/8 bytes. A timestamp av pair with a
415 // different length is invalid.
416 const uint8_t buf[15] = {0x07, 0, 0x07, 0, 0x11, 0x22, 0x33, 0x44,
417 0x55, 0x66, 0x77, 0, 0, 0, 0};
418
419 NtlmBufferReader reader(buf);
420
421 std::vector<AvPair> av_pairs;
422 ASSERT_FALSE(reader.ReadTargetInfo(std::size(buf), &av_pairs));
423 }
424
TEST(NtlmBufferReaderTest,ReadTargetInfoInvalidTimestampPastEob)425 TEST(NtlmBufferReaderTest, ReadTargetInfoInvalidTimestampPastEob) {
426 // The timestamp avlen is correct but would read past the end of the buffer.
427 const uint8_t buf[11] = {0x07, 0, 0x08, 0, 0x11, 0x22,
428 0x33, 0x44, 0x55, 0x66, 0x77};
429
430 NtlmBufferReader reader(buf);
431
432 std::vector<AvPair> av_pairs;
433 ASSERT_FALSE(reader.ReadTargetInfo(std::size(buf), &av_pairs));
434 }
435
TEST(NtlmBufferReaderTest,ReadTargetInfoOtherField)436 TEST(NtlmBufferReaderTest, ReadTargetInfoOtherField) {
437 // A domain name AvPair containing the string L'ABCD' followed by
438 // a terminating AvPair.
439 const uint8_t buf[16] = {0x02, 0, 0x08, 0, 'A', 0, 'B', 0,
440 'C', 0, 'D', 0, 0, 0, 0, 0};
441
442 NtlmBufferReader reader(buf);
443
444 std::vector<AvPair> av_pairs;
445 ASSERT_TRUE(reader.ReadTargetInfo(std::size(buf), &av_pairs));
446 ASSERT_TRUE(reader.IsEndOfBuffer());
447 ASSERT_EQ(1u, av_pairs.size());
448
449 // Verify the domain name AvPair.
450 ASSERT_EQ(TargetInfoAvId::kDomainName, av_pairs[0].avid);
451 ASSERT_EQ(8, av_pairs[0].avlen);
452 ASSERT_EQ(0, memcmp(buf + 4, av_pairs[0].buffer.data(), 8));
453 }
454
TEST(NtlmBufferReaderTest,ReadTargetInfoNoTerminator)455 TEST(NtlmBufferReaderTest, ReadTargetInfoNoTerminator) {
456 // A domain name AvPair containing the string L'ABCD' but there is no
457 // terminating AvPair.
458 const uint8_t buf[12] = {0x02, 0, 0x08, 0, 'A', 0, 'B', 0, 'C', 0, 'D', 0};
459
460 NtlmBufferReader reader(buf);
461
462 std::vector<AvPair> av_pairs;
463 ASSERT_FALSE(reader.ReadTargetInfo(std::size(buf), &av_pairs));
464 }
465
TEST(NtlmBufferReaderTest,ReadTargetInfoTerminatorAtLocationOtherThanEnd)466 TEST(NtlmBufferReaderTest, ReadTargetInfoTerminatorAtLocationOtherThanEnd) {
467 // Target info contains [flags, terminator, domain, terminator]. This
468 // should fail because the terminator should only appear at the end.
469 const uint8_t buf[] = {0x06, 0, 0x04, 0, 0x02, 0, 0, 0, 0, 0,
470 0, 0, 0x02, 0, 0x08, 0, 'A', 0, 'B', 0,
471 'C', 0, 'D', 0, 0, 0, 0, 0};
472
473 NtlmBufferReader reader(buf);
474
475 std::vector<AvPair> av_pairs;
476 ASSERT_FALSE(reader.ReadTargetInfo(std::size(buf), &av_pairs));
477 }
478
TEST(NtlmBufferReaderTest,ReadTargetInfoTerminatorNonZeroLength)479 TEST(NtlmBufferReaderTest, ReadTargetInfoTerminatorNonZeroLength) {
480 // A flags Av Pair followed by a terminator pair with a non-zero length.
481 const uint8_t buf[] = {0x06, 0, 0x04, 0, 0x02, 0, 0, 0, 0, 0, 0x01, 0};
482
483 NtlmBufferReader reader(buf);
484
485 std::vector<AvPair> av_pairs;
486 ASSERT_FALSE(reader.ReadTargetInfo(std::size(buf), &av_pairs));
487 }
488
TEST(NtlmBufferReaderTest,ReadTargetInfoTerminatorNonZeroLength2)489 TEST(NtlmBufferReaderTest, ReadTargetInfoTerminatorNonZeroLength2) {
490 // A flags Av Pair followed by a terminator pair with a non-zero length,
491 // but otherwise in bounds payload. Terminator pairs must have zero
492 // length, so this is not valid.
493 const uint8_t buf[] = {0x06, 0, 0x04, 0, 0x02, 0, 0, 0, 0,
494 0, 0x01, 0, 0xff, 0, 0, 0, 0};
495
496 NtlmBufferReader reader(buf);
497
498 std::vector<AvPair> av_pairs;
499 ASSERT_FALSE(reader.ReadTargetInfo(std::size(buf), &av_pairs));
500 }
501
TEST(NtlmBufferReaderTest,ReadTargetInfoEmptyPayload)502 TEST(NtlmBufferReaderTest, ReadTargetInfoEmptyPayload) {
503 // Security buffer with no payload.
504 const uint8_t buf[] = {0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00};
505
506 NtlmBufferReader reader(buf);
507
508 std::vector<AvPair> av_pairs;
509 ASSERT_TRUE(reader.ReadTargetInfoPayload(&av_pairs));
510 ASSERT_TRUE(reader.IsEndOfBuffer());
511 ASSERT_TRUE(av_pairs.empty());
512 }
513
TEST(NtlmBufferReaderTest,ReadTargetInfoEolOnlyPayload)514 TEST(NtlmBufferReaderTest, ReadTargetInfoEolOnlyPayload) {
515 // Security buffer with an EOL payload
516 const uint8_t buf[] = {0x04, 0x00, 0x04, 0x00, 0x08, 0x00,
517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
518
519 NtlmBufferReader reader(buf);
520
521 std::vector<AvPair> av_pairs;
522 ASSERT_TRUE(reader.ReadTargetInfoPayload(&av_pairs));
523 ASSERT_FALSE(reader.IsEndOfBuffer());
524
525 // Should only have advanced over the security buffer.
526 ASSERT_EQ(kSecurityBufferLen, reader.GetCursor());
527 ASSERT_TRUE(av_pairs.empty());
528 }
529
TEST(NtlmBufferReaderTest,ReadTargetInfoTooShortPayload)530 TEST(NtlmBufferReaderTest, ReadTargetInfoTooShortPayload) {
531 // Security buffer with a payload too small to contain any pairs.
532 const uint8_t buf[] = {0x03, 0x00, 0x03, 0x00, 0x08, 0x00,
533 0x00, 0x00, 0x00, 0x00, 0x00};
534
535 NtlmBufferReader reader(buf);
536
537 std::vector<AvPair> av_pairs;
538 ASSERT_FALSE(reader.ReadTargetInfoPayload(&av_pairs));
539 }
540
TEST(NtlmBufferReaderTest,ReadTargetInfoFlagsPayload)541 TEST(NtlmBufferReaderTest, ReadTargetInfoFlagsPayload) {
542 // Security buffer followed by a 12 byte payload containing a flags AvPair
543 // with the MIC bit, followed by a terminator pair.
544 const uint8_t buf[] = {0x0c, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00,
545 0x00, 0x06, 0, 0x04, 0, 0x02, 0,
546 0, 0, 0, 0, 0, 0};
547
548 NtlmBufferReader reader(buf);
549
550 std::vector<AvPair> av_pairs;
551 ASSERT_TRUE(reader.ReadTargetInfoPayload(&av_pairs));
552 ASSERT_FALSE(reader.IsEndOfBuffer());
553
554 // Should only have advanced over the security buffer.
555 ASSERT_EQ(kSecurityBufferLen, reader.GetCursor());
556
557 // Contains a single flags AVPair containing the MIC bit.
558 ASSERT_EQ(1u, av_pairs.size());
559 ASSERT_EQ(TargetInfoAvFlags::kMicPresent, av_pairs[0].flags);
560 }
561
TEST(NtlmBufferReaderTest,ReadTargetInfoFlagsPayloadWithPaddingBetween)562 TEST(NtlmBufferReaderTest, ReadTargetInfoFlagsPayloadWithPaddingBetween) {
563 // Security buffer followed by a 12 byte payload containing a flags AvPair
564 // with the MIC bit, followed by a terminator pair. 5 bytes of 0xff padding
565 // are between the SecurityBuffer and the payload to test when the payload
566 // is not contiguous.
567 const uint8_t buf[] = {0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00,
568 0xff, 0xff, 0xff, 0xff, 0x06, 0, 0x04, 0,
569 0x02, 0, 0, 0, 0, 0, 0, 0};
570 NtlmBufferReader reader(buf);
571
572 std::vector<AvPair> av_pairs;
573 ASSERT_TRUE(reader.ReadTargetInfoPayload(&av_pairs));
574 ASSERT_FALSE(reader.IsEndOfBuffer());
575
576 // Should only have advanced over the security buffer.
577 ASSERT_EQ(kSecurityBufferLen, reader.GetCursor());
578
579 // Contains a single flags AVPair containing the MIC bit.
580 ASSERT_EQ(1u, av_pairs.size());
581 ASSERT_EQ(TargetInfoAvFlags::kMicPresent, av_pairs[0].flags);
582 }
583
TEST(NtlmBufferReaderTest,ReadMessageTypeAuthenticate)584 TEST(NtlmBufferReaderTest, ReadMessageTypeAuthenticate) {
585 const uint8_t buf[4] = {static_cast<uint8_t>(MessageType::kAuthenticate), 0,
586 0, 0};
587 NtlmBufferReader reader(buf);
588
589 MessageType message_type;
590 ASSERT_TRUE(reader.ReadMessageType(&message_type));
591 ASSERT_EQ(MessageType::kAuthenticate, message_type);
592 ASSERT_TRUE(reader.IsEndOfBuffer());
593 }
594
TEST(NtlmBufferReaderTest,MatchMessageTypeAuthenticate)595 TEST(NtlmBufferReaderTest, MatchMessageTypeAuthenticate) {
596 const uint8_t buf[4] = {static_cast<uint8_t>(MessageType::kAuthenticate), 0,
597 0, 0};
598 NtlmBufferReader reader(buf);
599
600 ASSERT_TRUE(reader.MatchMessageType(MessageType::kAuthenticate));
601 ASSERT_TRUE(reader.IsEndOfBuffer());
602 }
603
TEST(NtlmBufferReaderTest,MatchMessageTypeInvalid)604 TEST(NtlmBufferReaderTest, MatchMessageTypeInvalid) {
605 // Only 0x01, 0x02, and 0x03 are valid message types.
606 const uint8_t buf[4] = {0x04, 0, 0, 0};
607 NtlmBufferReader reader(buf);
608
609 ASSERT_FALSE(reader.MatchMessageType(MessageType::kAuthenticate));
610 }
611
TEST(NtlmBufferReaderTest,MatchMessageTypeMismatch)612 TEST(NtlmBufferReaderTest, MatchMessageTypeMismatch) {
613 const uint8_t buf[4] = {static_cast<uint8_t>(MessageType::kChallenge), 0, 0,
614 0};
615 NtlmBufferReader reader(buf);
616
617 ASSERT_FALSE(reader.MatchMessageType(MessageType::kAuthenticate));
618 }
619
TEST(NtlmBufferReaderTest,MatchAuthenticateHeader)620 TEST(NtlmBufferReaderTest, MatchAuthenticateHeader) {
621 const uint8_t buf[12] = {
622 'N', 'T', 'L',
623 'M', 'S', 'S',
624 'P', 0, static_cast<uint8_t>(MessageType::kAuthenticate),
625 0, 0, 0};
626 NtlmBufferReader reader(buf);
627
628 ASSERT_TRUE(reader.MatchMessageHeader(MessageType::kAuthenticate));
629 ASSERT_TRUE(reader.IsEndOfBuffer());
630 }
631
TEST(NtlmBufferReaderTest,MatchAuthenticateHeaderMisMatch)632 TEST(NtlmBufferReaderTest, MatchAuthenticateHeaderMisMatch) {
633 const uint8_t buf[12] = {
634 'N', 'T', 'L',
635 'M', 'S', 'S',
636 'P', 0, static_cast<uint8_t>(MessageType::kChallenge),
637 0, 0, 0};
638 NtlmBufferReader reader(buf);
639
640 ASSERT_FALSE(reader.MatchMessageType(MessageType::kAuthenticate));
641 }
642
TEST(NtlmBufferReaderTest,MatchZeros)643 TEST(NtlmBufferReaderTest, MatchZeros) {
644 const uint8_t buf[6] = {0, 0, 0, 0, 0, 0};
645
646 NtlmBufferReader reader(buf);
647
648 ASSERT_TRUE(reader.MatchZeros(std::size(buf)));
649 ASSERT_TRUE(reader.IsEndOfBuffer());
650 ASSERT_FALSE(reader.MatchZeros(1));
651 }
652
TEST(NtlmBufferReaderTest,MatchZerosFail)653 TEST(NtlmBufferReaderTest, MatchZerosFail) {
654 const uint8_t buf[6] = {0, 0, 0, 0, 0, 0xFF};
655
656 NtlmBufferReader reader(buf);
657
658 ASSERT_FALSE(reader.MatchZeros(std::size(buf)));
659 }
660
TEST(NtlmBufferReaderTest,MatchEmptySecurityBuffer)661 TEST(NtlmBufferReaderTest, MatchEmptySecurityBuffer) {
662 const uint8_t buf[kSecurityBufferLen] = {0, 0, 0, 0, 0, 0, 0, 0};
663
664 NtlmBufferReader reader(buf);
665
666 ASSERT_TRUE(reader.MatchEmptySecurityBuffer());
667 ASSERT_TRUE(reader.IsEndOfBuffer());
668 ASSERT_FALSE(reader.MatchEmptySecurityBuffer());
669 }
670
TEST(NtlmBufferReaderTest,MatchEmptySecurityBufferLengthZeroOffsetEnd)671 TEST(NtlmBufferReaderTest, MatchEmptySecurityBufferLengthZeroOffsetEnd) {
672 const uint8_t buf[kSecurityBufferLen] = {0, 0, 0, 0, 0x08, 0, 0, 0};
673
674 NtlmBufferReader reader(buf);
675
676 ASSERT_TRUE(reader.MatchEmptySecurityBuffer());
677 ASSERT_TRUE(reader.IsEndOfBuffer());
678 }
679
TEST(NtlmBufferReaderTest,MatchEmptySecurityBufferLengthZeroPastEob)680 TEST(NtlmBufferReaderTest, MatchEmptySecurityBufferLengthZeroPastEob) {
681 const uint8_t buf[kSecurityBufferLen] = {0, 0, 0, 0, 0x09, 0, 0, 0};
682
683 NtlmBufferReader reader(buf);
684
685 ASSERT_FALSE(reader.MatchEmptySecurityBuffer());
686 }
687
TEST(NtlmBufferReaderTest,MatchEmptySecurityBufferLengthNonZeroLength)688 TEST(NtlmBufferReaderTest, MatchEmptySecurityBufferLengthNonZeroLength) {
689 const uint8_t buf[kSecurityBufferLen + 1] = {0x01, 0, 0, 0, 0x08,
690 0, 0, 0, 0xff};
691
692 NtlmBufferReader reader(buf);
693
694 ASSERT_FALSE(reader.MatchEmptySecurityBuffer());
695 }
696
TEST(NtlmBufferReaderTest,ReadAvPairHeader)697 TEST(NtlmBufferReaderTest, ReadAvPairHeader) {
698 const uint8_t buf[4] = {0x06, 0x00, 0x11, 0x22};
699
700 NtlmBufferReader reader(buf);
701
702 TargetInfoAvId actual_avid;
703 uint16_t actual_avlen;
704 ASSERT_TRUE(reader.ReadAvPairHeader(&actual_avid, &actual_avlen));
705 ASSERT_EQ(TargetInfoAvId::kFlags, actual_avid);
706 ASSERT_EQ(0x2211, actual_avlen);
707 ASSERT_TRUE(reader.IsEndOfBuffer());
708 ASSERT_FALSE(reader.ReadAvPairHeader(&actual_avid, &actual_avlen));
709 }
710
TEST(NtlmBufferReaderTest,ReadAvPairHeaderPastEob)711 TEST(NtlmBufferReaderTest, ReadAvPairHeaderPastEob) {
712 const uint8_t buf[3] = {0x06, 0x00, 0x11};
713
714 NtlmBufferReader reader(buf);
715
716 TargetInfoAvId avid;
717 uint16_t avlen;
718 ASSERT_FALSE(reader.ReadAvPairHeader(&avid, &avlen));
719 }
720
721 } // namespace net::ntlm
722