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_writer.h"
11
12 #include "base/strings/utf_string_conversions.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace net::ntlm {
16
17 namespace {
18
19 // Helper method to get a raw pointer to the buffer.
GetBufferPtr(const NtlmBufferWriter & writer)20 const uint8_t* GetBufferPtr(const NtlmBufferWriter& writer) {
21 return writer.GetBuffer().data();
22 }
23
24 // Helper method to get a byte at a specific index in the buffer.
GetByteFromBuffer(const NtlmBufferWriter & writer,size_t index)25 uint8_t GetByteFromBuffer(const NtlmBufferWriter& writer, size_t index) {
26 EXPECT_TRUE(index < writer.GetLength());
27 return writer.GetBuffer()[index];
28 }
29
30 } // namespace
31
TEST(NtlmBufferWriterTest,Initialization)32 TEST(NtlmBufferWriterTest, Initialization) {
33 NtlmBufferWriter writer(1);
34
35 ASSERT_EQ(1u, writer.GetLength());
36 ASSERT_EQ(1u, writer.GetBuffer().size());
37 ASSERT_EQ(0u, writer.GetCursor());
38 ASSERT_FALSE(writer.IsEndOfBuffer());
39 ASSERT_TRUE(writer.CanWrite(1));
40 ASSERT_FALSE(writer.CanWrite(2));
41 }
42
TEST(NtlmBufferWriterTest,EmptyWrite)43 TEST(NtlmBufferWriterTest, EmptyWrite) {
44 NtlmBufferWriter writer(0);
45
46 ASSERT_EQ(0u, writer.GetLength());
47 ASSERT_EQ(0u, writer.GetBuffer().size());
48 ASSERT_EQ(0u, writer.GetCursor());
49 ASSERT_EQ(nullptr, GetBufferPtr(writer));
50
51 // An empty (zero-byte) write into a zero-byte writer should succeed as a
52 // no-op.
53 std::vector<uint8_t> b;
54 ASSERT_TRUE(writer.CanWrite(0));
55 ASSERT_TRUE(writer.WriteBytes(b));
56
57 ASSERT_EQ(0u, writer.GetLength());
58 ASSERT_EQ(0u, writer.GetBuffer().size());
59 ASSERT_EQ(0u, writer.GetCursor());
60 ASSERT_EQ(nullptr, GetBufferPtr(writer));
61
62 // An empty (zero-byte) write into a non-zero-byte writer should succeed as
63 // a no-op.
64 NtlmBufferWriter writer2(1);
65 ASSERT_EQ(1u, writer2.GetLength());
66 ASSERT_EQ(1u, writer2.GetBuffer().size());
67 ASSERT_EQ(0u, writer2.GetCursor());
68 ASSERT_NE(nullptr, GetBufferPtr(writer2));
69
70 ASSERT_TRUE(writer2.CanWrite(0));
71 ASSERT_TRUE(writer2.WriteBytes(b));
72
73 ASSERT_EQ(1u, writer2.GetLength());
74 ASSERT_EQ(1u, writer2.GetBuffer().size());
75 ASSERT_EQ(0u, writer2.GetCursor());
76 ASSERT_NE(nullptr, GetBufferPtr(writer2));
77 }
78
TEST(NtlmBufferWriterTest,Write16)79 TEST(NtlmBufferWriterTest, Write16) {
80 uint8_t expected[2] = {0x22, 0x11};
81 const uint16_t value = 0x1122;
82
83 NtlmBufferWriter writer(sizeof(uint16_t));
84
85 ASSERT_TRUE(writer.WriteUInt16(value));
86 ASSERT_TRUE(writer.IsEndOfBuffer());
87 ASSERT_EQ(std::size(expected), writer.GetLength());
88 ASSERT_FALSE(writer.WriteUInt16(value));
89
90 ASSERT_EQ(0,
91 memcmp(expected, writer.GetBuffer().data(), std::size(expected)));
92 }
93
TEST(NtlmBufferWriterTest,Write16PastEob)94 TEST(NtlmBufferWriterTest, Write16PastEob) {
95 NtlmBufferWriter writer(sizeof(uint16_t) - 1);
96
97 ASSERT_FALSE(writer.WriteUInt16(0));
98 ASSERT_EQ(0u, writer.GetCursor());
99 }
100
TEST(NtlmBufferWriterTest,Write32)101 TEST(NtlmBufferWriterTest, Write32) {
102 uint8_t expected[4] = {0x44, 0x33, 0x22, 0x11};
103 const uint32_t value = 0x11223344;
104
105 NtlmBufferWriter writer(sizeof(uint32_t));
106
107 ASSERT_TRUE(writer.WriteUInt32(value));
108 ASSERT_TRUE(writer.IsEndOfBuffer());
109 ASSERT_FALSE(writer.WriteUInt32(value));
110
111 ASSERT_EQ(0, memcmp(expected, GetBufferPtr(writer), std::size(expected)));
112 }
113
TEST(NtlmBufferWriterTest,Write32PastEob)114 TEST(NtlmBufferWriterTest, Write32PastEob) {
115 NtlmBufferWriter writer(sizeof(uint32_t) - 1);
116
117 ASSERT_FALSE(writer.WriteUInt32(0));
118 ASSERT_EQ(0u, writer.GetCursor());
119 }
120
TEST(NtlmBufferWriterTest,Write64)121 TEST(NtlmBufferWriterTest, Write64) {
122 uint8_t expected[8] = {0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
123 const uint64_t value = 0x1122334455667788;
124
125 NtlmBufferWriter writer(sizeof(uint64_t));
126
127 ASSERT_TRUE(writer.WriteUInt64(value));
128 ASSERT_TRUE(writer.IsEndOfBuffer());
129 ASSERT_FALSE(writer.WriteUInt64(value));
130
131 ASSERT_EQ(0, memcmp(expected, GetBufferPtr(writer), std::size(expected)));
132 }
133
TEST(NtlmBufferWriterTest,Write64PastEob)134 TEST(NtlmBufferWriterTest, Write64PastEob) {
135 NtlmBufferWriter writer(sizeof(uint64_t) - 1);
136
137 ASSERT_FALSE(writer.WriteUInt64(0));
138 ASSERT_EQ(0u, writer.GetCursor());
139 }
140
TEST(NtlmBufferWriterTest,WriteBytes)141 TEST(NtlmBufferWriterTest, WriteBytes) {
142 uint8_t expected[8] = {0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
143
144 NtlmBufferWriter writer(std::size(expected));
145
146 ASSERT_TRUE(writer.WriteBytes(expected));
147 ASSERT_EQ(0, memcmp(GetBufferPtr(writer), expected, std::size(expected)));
148 ASSERT_TRUE(writer.IsEndOfBuffer());
149 ASSERT_FALSE(writer.WriteBytes(base::span(expected, 1u)));
150
151 ASSERT_EQ(0, memcmp(expected, GetBufferPtr(writer), std::size(expected)));
152 }
153
TEST(NtlmBufferWriterTest,WriteBytesPastEob)154 TEST(NtlmBufferWriterTest, WriteBytesPastEob) {
155 uint8_t buffer[8];
156
157 NtlmBufferWriter writer(std::size(buffer) - 1);
158
159 ASSERT_FALSE(writer.WriteBytes(buffer));
160 }
161
TEST(NtlmBufferWriterTest,WriteSecurityBuffer)162 TEST(NtlmBufferWriterTest, WriteSecurityBuffer) {
163 uint8_t expected[8] = {0x22, 0x11, 0x22, 0x11, 0x88, 0x77, 0x66, 0x55};
164 uint16_t length = 0x1122;
165 uint32_t offset = 0x55667788;
166
167 NtlmBufferWriter writer(kSecurityBufferLen);
168
169 ASSERT_TRUE(writer.WriteSecurityBuffer(SecurityBuffer(offset, length)));
170 ASSERT_TRUE(writer.IsEndOfBuffer());
171 ASSERT_FALSE(writer.WriteSecurityBuffer(SecurityBuffer(offset, length)));
172
173 ASSERT_EQ(0, memcmp(expected, GetBufferPtr(writer), std::size(expected)));
174 }
175
TEST(NtlmBufferWriterTest,WriteSecurityBufferPastEob)176 TEST(NtlmBufferWriterTest, WriteSecurityBufferPastEob) {
177 SecurityBuffer sec_buf;
178 NtlmBufferWriter writer(kSecurityBufferLen - 1);
179
180 ASSERT_FALSE(writer.WriteSecurityBuffer(sec_buf));
181 }
182
TEST(NtlmBufferWriterTest,WriteNarrowString)183 TEST(NtlmBufferWriterTest, WriteNarrowString) {
184 uint8_t expected[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};
185 std::string value("12345678");
186
187 NtlmBufferWriter writer(value.size());
188
189 ASSERT_TRUE(writer.WriteUtf8String(value));
190 ASSERT_TRUE(writer.IsEndOfBuffer());
191 ASSERT_FALSE(writer.WriteUtf8String(value));
192
193 ASSERT_EQ(0, memcmp(expected, GetBufferPtr(writer), std::size(expected)));
194 }
195
TEST(NtlmBufferWriterTest,WriteAsciiStringPastEob)196 TEST(NtlmBufferWriterTest, WriteAsciiStringPastEob) {
197 std::string str("12345678");
198 NtlmBufferWriter writer(str.length() - 1);
199
200 ASSERT_FALSE(writer.WriteUtf8String(str));
201 }
202
TEST(NtlmBufferWriterTest,WriteUtf16String)203 TEST(NtlmBufferWriterTest, WriteUtf16String) {
204 uint8_t expected[16] = {'1', 0, '2', 0, '3', 0, '4', 0,
205 '5', 0, '6', 0, '7', 0, '8', 0};
206 std::u16string value = u"12345678";
207
208 NtlmBufferWriter writer(value.size() * 2);
209
210 ASSERT_TRUE(writer.WriteUtf16String(value));
211 ASSERT_TRUE(writer.IsEndOfBuffer());
212 ASSERT_FALSE(writer.WriteUtf16String(value));
213
214 ASSERT_EQ(0, memcmp(expected, GetBufferPtr(writer), std::size(expected)));
215 }
216
TEST(NtlmBufferWriterTest,WriteUtf16StringPastEob)217 TEST(NtlmBufferWriterTest, WriteUtf16StringPastEob) {
218 std::u16string str = u"12345678";
219 NtlmBufferWriter writer((str.length() * 2) - 1);
220
221 ASSERT_FALSE(writer.WriteUtf16String(str));
222 }
223
TEST(NtlmBufferWriterTest,WriteUtf8AsUtf16String)224 TEST(NtlmBufferWriterTest, WriteUtf8AsUtf16String) {
225 uint8_t expected[16] = {'1', 0, '2', 0, '3', 0, '4', 0,
226 '5', 0, '6', 0, '7', 0, '8', 0};
227 std::string input = "12345678";
228
229 NtlmBufferWriter writer(input.size() * 2);
230
231 ASSERT_TRUE(writer.WriteUtf8AsUtf16String(input));
232 ASSERT_TRUE(writer.IsEndOfBuffer());
233 ASSERT_FALSE(writer.WriteUtf8AsUtf16String(input));
234
235 ASSERT_EQ(0, memcmp(expected, GetBufferPtr(writer), std::size(expected)));
236 }
237
TEST(NtlmBufferWriterTest,WriteSignature)238 TEST(NtlmBufferWriterTest, WriteSignature) {
239 uint8_t expected[8] = {'N', 'T', 'L', 'M', 'S', 'S', 'P', 0};
240 NtlmBufferWriter writer(kSignatureLen);
241
242 ASSERT_TRUE(writer.WriteSignature());
243 ASSERT_TRUE(writer.IsEndOfBuffer());
244
245 ASSERT_EQ(0, memcmp(expected, GetBufferPtr(writer), std::size(expected)));
246 }
247
TEST(NtlmBufferWriterTest,WriteSignaturePastEob)248 TEST(NtlmBufferWriterTest, WriteSignaturePastEob) {
249 NtlmBufferWriter writer(1);
250
251 ASSERT_FALSE(writer.WriteSignature());
252 }
253
TEST(NtlmBufferWriterTest,WriteMessageType)254 TEST(NtlmBufferWriterTest, WriteMessageType) {
255 NtlmBufferWriter writer(4);
256
257 ASSERT_TRUE(writer.WriteMessageType(MessageType::kNegotiate));
258 ASSERT_TRUE(writer.IsEndOfBuffer());
259 ASSERT_EQ(static_cast<uint32_t>(MessageType::kNegotiate),
260 GetByteFromBuffer(writer, 0));
261 ASSERT_EQ(0, GetByteFromBuffer(writer, 1));
262 ASSERT_EQ(0, GetByteFromBuffer(writer, 2));
263 ASSERT_EQ(0, GetByteFromBuffer(writer, 3));
264 }
265
TEST(NtlmBufferWriterTest,WriteMessageTypePastEob)266 TEST(NtlmBufferWriterTest, WriteMessageTypePastEob) {
267 NtlmBufferWriter writer(sizeof(uint32_t) - 1);
268
269 ASSERT_FALSE(writer.WriteMessageType(MessageType::kNegotiate));
270 }
271
TEST(NtlmBufferWriterTest,WriteAvPairHeader)272 TEST(NtlmBufferWriterTest, WriteAvPairHeader) {
273 const uint8_t expected[4] = {0x06, 0x00, 0x11, 0x22};
274 NtlmBufferWriter writer(std::size(expected));
275
276 ASSERT_TRUE(writer.WriteAvPairHeader(TargetInfoAvId::kFlags, 0x2211));
277 ASSERT_TRUE(writer.IsEndOfBuffer());
278
279 ASSERT_EQ(0, memcmp(expected, GetBufferPtr(writer), std::size(expected)));
280 }
281
TEST(NtlmBufferWriterTest,WriteAvPairHeaderPastEob)282 TEST(NtlmBufferWriterTest, WriteAvPairHeaderPastEob) {
283 NtlmBufferWriter writer(kAvPairHeaderLen - 1);
284
285 ASSERT_FALSE(writer.WriteAvPairHeader(TargetInfoAvId::kFlags, 0x2211));
286 ASSERT_EQ(0u, writer.GetCursor());
287 }
288
289 } // namespace net::ntlm
290