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