• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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