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

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

Issue 2873673002: Add unit tests for NTLMv1 portable implementation (Closed)
Patch Set: Review feedback Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <string>
6
7 #include "base/base64.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "net/base/test_completion_callback.h"
12 #include "net/dns/mock_host_resolver.h"
13 #include "net/http/http_auth_challenge_tokenizer.h"
14 #include "net/http/http_auth_handler_ntlm.h"
15 #include "net/http/http_request_info.h"
16 #include "net/http/mock_allow_http_auth_preferences.h"
17 #include "net/log/net_log_with_source.h"
18 #include "net/ntlm/ntlm.h"
19 #include "net/ntlm/ntlm_buffer_reader.h"
20 #include "net/ntlm/ntlm_buffer_writer.h"
21 #include "net/ntlm/ntlm_test_data.h"
22 #include "net/ssl/ssl_info.h"
23 #include "net/test/gtest_util.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "testing/platform_test.h"
27
28 namespace net {
29
30 class HttpAuthHandlerNtlmPortableTest : public PlatformTest {
31 public:
32 // Test input value defined in [MS-NLMP] Section 4.2.1.
33 HttpAuthHandlerNtlmPortableTest() {
34 http_auth_preferences_.reset(new MockAllowHttpAuthPreferences());
35 factory_.reset(new HttpAuthHandlerNTLM::Factory());
36 factory_->set_http_auth_preferences(http_auth_preferences_.get());
37 creds_ = AuthCredentials(
38 ntlm::test::kNtlmDomain + base::ASCIIToUTF16("\\") + ntlm::test::kUser,
39 ntlm::test::kPassword);
40 }
41
42 int CreateHandler() {
43 GURL gurl("https://foo.com");
44 SSLInfo null_ssl_info;
45
46 return factory_->CreateAuthHandlerFromString(
47 "NTLM", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, NetLogWithSource(),
48 &auth_handler_);
49 }
50
51 std::string CreateNtlmAuthHeader(base::StringPiece message) {
52 std::string output;
53 base::Base64Encode(message, &output);
54
55 return "NTLM " + output;
56 }
57
58 HttpAuth::AuthorizationResult HandleAnotherChallenge(
59 const std::string& challenge) {
60 HttpAuthChallengeTokenizer tokenizer(challenge.begin(), challenge.end());
61 return GetAuthHandler()->HandleAnotherChallenge(&tokenizer);
62 }
63
64 bool DecodeChallenge(const std::string& challenge, std::string* decoded) {
65 HttpAuthChallengeTokenizer tokenizer(challenge.begin(), challenge.end());
66 return base::Base64Decode(tokenizer.base64_param(), decoded);
67 }
68
69 int GenerateAuthToken(std::string* token) {
70 TestCompletionCallback callback;
71 HttpRequestInfo request_info;
72 return callback.GetResult(GetAuthHandler()->GenerateAuthToken(
73 GetCreds(), &request_info, callback.callback(), token));
74 }
75
76 void ReadBytesPayload(ntlm::NtlmBufferReader* reader,
77 uint8_t* buffer,
78 size_t len) {
79 // First read the security buffer.
80 ntlm::SecurityBuffer sec_buf;
81 EXPECT_TRUE(reader->ReadSecurityBuffer(&sec_buf));
82 EXPECT_EQ(sec_buf.length, len);
Ryan Sleevi 2017/07/13 17:39:54 ASSERT_EQ ? If .length > len, this would be a cra
zentaro 2017/07/13 18:20:31 Done.
83 EXPECT_TRUE(reader->ReadBytesFrom(sec_buf, buffer));
84 }
85
86 // Reads bytes from a payload and assigns them to a string. This makes
87 // no assumptions about the underlying encoding.
88 void ReadStringPayload(ntlm::NtlmBufferReader* reader, std::string* str) {
89 ntlm::SecurityBuffer sec_buf;
90 EXPECT_TRUE(reader->ReadSecurityBuffer(&sec_buf));
Ryan Sleevi 2017/07/13 17:39:53 ASSERT_TRUE ?
zentaro 2017/07/13 18:20:31 Done.
91
92 uint8_t raw[sec_buf.length];
Ryan Sleevi 2017/07/13 17:39:53 I don't believe this is legal C++, because it's a
zentaro 2017/07/13 18:20:31 Done.
93 EXPECT_TRUE(reader->ReadBytesFrom(sec_buf, raw));
94
95 str->assign(reinterpret_cast<const char*>(raw), sec_buf.length);
96 }
97
98 // Reads bytes from a payload and assigns them to a string16. This makes
99 // no assumptions about the underlying encoding. This will fail if there
100 // are an odd number of bytes in the payload.
101 void ReadString16Payload(ntlm::NtlmBufferReader* reader,
102 base::string16* str) {
103 ntlm::SecurityBuffer sec_buf;
104 EXPECT_TRUE(reader->ReadSecurityBuffer(&sec_buf));
105 EXPECT_EQ(0, sec_buf.length % 2);
106
107 uint8_t raw[sec_buf.length];
Ryan Sleevi 2017/07/13 17:39:54 Ditto re: VLAs
zentaro 2017/07/13 18:20:31 Done.
108 EXPECT_TRUE(reader->ReadBytesFrom(sec_buf, raw));
109
110 #if IS_BIG_ENDIAN
Ryan Sleevi 2017/07/13 17:39:53 The code elsewhere (e.g. http_auth_handler_ntlm_po
zentaro 2017/07/13 18:20:31 Done.
111 for (size_t i = 0; i < sec_buf.length; i += 2) {
112 std::swap(raw[i], raw[i + 1]);
113 }
114 #endif
115
116 str->assign(reinterpret_cast<const base::char16*>(raw), sec_buf.length / 2);
117 }
118
119 int GetGenerateAuthTokenResult() {
120 std::string token;
121 return GenerateAuthToken(&token);
122 }
123
124 AuthCredentials* GetCreds() { return &creds_; }
125
126 HttpAuthHandlerNTLM* GetAuthHandler() {
127 return static_cast<HttpAuthHandlerNTLM*>(auth_handler_.get());
128 }
129
130 static void MockRandom(uint8_t* output, size_t n) {
131 // This is set to 0xaa because the client challenge for testing in
132 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
133 memset(output, 0xaa, n);
134 }
135
136 static std::string MockGetHostName() { return ntlm::test::kHostnameAscii; }
137
138 private:
139 AuthCredentials creds_;
140 std::unique_ptr<HttpAuthHandler> auth_handler_;
141 std::unique_ptr<MockAllowHttpAuthPreferences> http_auth_preferences_;
142 std::unique_ptr<HttpAuthHandlerNTLM::Factory> factory_;
143 };
144
145 TEST_F(HttpAuthHandlerNtlmPortableTest, SimpleConstruction) {
146 ASSERT_EQ(OK, CreateHandler());
147 ASSERT_TRUE(GetAuthHandler() != nullptr);
148 }
149
150 TEST_F(HttpAuthHandlerNtlmPortableTest, DoNotAllowDefaultCreds) {
151 ASSERT_EQ(OK, CreateHandler());
152 ASSERT_FALSE(GetAuthHandler()->AllowsDefaultCredentials());
153 }
154
155 TEST_F(HttpAuthHandlerNtlmPortableTest, AllowsExplicitCredentials) {
156 ASSERT_EQ(OK, CreateHandler());
157 ASSERT_TRUE(GetAuthHandler()->AllowsExplicitCredentials());
158 }
159
160 TEST_F(HttpAuthHandlerNtlmPortableTest, VerifyType1Message) {
161 ASSERT_EQ(OK, CreateHandler());
162
163 std::string token;
164 ASSERT_EQ(OK, GenerateAuthToken(&token));
165 // The type 1 message generated is always the same. The only variable
166 // part of the message is the flags and this implementation always offers
167 // the same set of flags.
168 ASSERT_EQ("NTLM TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=", token);
169 }
170
171 TEST_F(HttpAuthHandlerNtlmPortableTest, EmptyTokenFails) {
172 ASSERT_EQ(OK, CreateHandler());
173 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
174
175 // The encoded token for a type 2 message can't be empty.
176 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT,
177 HandleAnotherChallenge("NTLM"));
178 }
179
180 TEST_F(HttpAuthHandlerNtlmPortableTest, InvalidBase64Encoding) {
181 ASSERT_EQ(OK, CreateHandler());
182 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
183
184 // Token isn't valid base64.
185 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
186 HandleAnotherChallenge("NTLM !!!!!!!!!!!!!"));
187 ASSERT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
188 }
189
190 TEST_F(HttpAuthHandlerNtlmPortableTest, CantChangeSchemeMidway) {
191 ASSERT_EQ(OK, CreateHandler());
192 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
193
194 // Can't switch to a different auth scheme in the middle of the process.
195 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_INVALID,
196 HandleAnotherChallenge("Negotiate SSdtIG5vdCBhIHJlYWwgdG9rZW4h"));
197 }
198
199 TEST_F(HttpAuthHandlerNtlmPortableTest, MinimalStructurallyValidType2) {
200 ASSERT_EQ(OK, CreateHandler());
201 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
202 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
203 HandleAnotherChallenge(CreateNtlmAuthHeader(base::StringPiece(
204 reinterpret_cast<const char*>(ntlm::test::kMinChallengeMessage),
205 ntlm::kChallengeHeaderLen))));
206 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
207 }
208
209 TEST_F(HttpAuthHandlerNtlmPortableTest, Type2MessageTooShort) {
210 ASSERT_EQ(OK, CreateHandler());
211 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
212
213 char raw[31];
214 memcpy(raw, ntlm::test::kMinChallengeMessage, 31);
215
216 // Fail because the minimum size valid message is 32 bytes.
217 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
218 HandleAnotherChallenge(
219 CreateNtlmAuthHeader(base::StringPiece(raw, sizeof(raw)))));
220 ASSERT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
221 }
222
223 TEST_F(HttpAuthHandlerNtlmPortableTest, Type2MessageWrongSignature) {
224 ASSERT_EQ(OK, CreateHandler());
225 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
226
227 char raw[32];
228 memcpy(raw, ntlm::test::kMinChallengeMessage, 32);
229 // Modify the default valid message to overwrite the last byte of the
230 // signature.
231 raw[7] = 0xff;
232
233 // Fail because the first 8 bytes don't match "NTLMSSP\0"
234 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
235 HandleAnotherChallenge(
236 CreateNtlmAuthHeader(base::StringPiece(raw, sizeof(raw)))));
237 ASSERT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
238 }
239
240 TEST_F(HttpAuthHandlerNtlmPortableTest, Type2WrongMessageType) {
241 ASSERT_EQ(OK, CreateHandler());
242 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
243
244 char raw[32];
245 memcpy(raw, ntlm::test::kMinChallengeMessage, 32);
246 // Modify the message type so it is not 0x00000002
247 raw[8] = 0x03;
248
249 // Fail because the message type should be MessageType::kChallenge
250 // (0x00000002)
251 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
252 HandleAnotherChallenge(CreateNtlmAuthHeader(raw)));
253 ASSERT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
254 }
255
256 TEST_F(HttpAuthHandlerNtlmPortableTest, Type2MessageWithNoTargetName) {
257 ASSERT_EQ(OK, CreateHandler());
258 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
259
260 // The spec (2.2.1.2) states that the length SHOULD be 0 and the offset
261 // SHOULD be where the payload would be if it was present. This is the
262 // expected response from a compliant server when no target name is sent.
263 // In reality the offset should always be ignored if the length is zero.
264 // Also implementations often just write zeros.
265 char raw[32];
266 memcpy(raw, ntlm::test::kMinChallengeMessage, 32);
267 // Modify the default valid message to overwrite the offset to zero.
268 raw[16] = 0x00;
269
270 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
271 HandleAnotherChallenge(
272 CreateNtlmAuthHeader(base::StringPiece(raw, sizeof(raw)))));
273 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
274 }
275
276 TEST_F(HttpAuthHandlerNtlmPortableTest, Type2MessageWithTargetName) {
277 ASSERT_EQ(OK, CreateHandler());
278 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
279
280 // One extra byte is provided for target name.
281 char raw[33];
282 memcpy(raw, ntlm::test::kMinChallengeMessage, 32);
283 // Modify the default valid message to indicate 1 byte is present in the
284 // target name payload.
285 raw[12] = 0x01;
286 raw[14] = 0x01;
287 // Put something in the target name.
288 raw[32] = 'Z';
289
290 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
291 HandleAnotherChallenge(
292 CreateNtlmAuthHeader(base::StringPiece(raw, sizeof(raw)))));
293 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
294 }
295
296 TEST_F(HttpAuthHandlerNtlmPortableTest, NoTargetNameOverflowFromOffset) {
297 ASSERT_EQ(OK, CreateHandler());
298 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
299
300 char raw[32];
301 memcpy(raw, ntlm::test::kMinChallengeMessage, 32);
302 // Modify the default valid message to claim that the target name field is 1
303 // byte long overrunning the end of the message message.
304 raw[12] = 0x01;
305 raw[14] = 0x01;
306
307 // The above malformed message could cause an implementation to read outside
308 // the message buffer because the offset is past the end of the message.
309 // Verify it gets rejected.
310 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
311 HandleAnotherChallenge(
312 CreateNtlmAuthHeader(base::StringPiece(raw, sizeof(raw)))));
313 ASSERT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
314 }
315
316 TEST_F(HttpAuthHandlerNtlmPortableTest, NoTargetNameOverflowFromLength) {
317 ASSERT_EQ(OK, CreateHandler());
318 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
319
320 // Message has 1 extra byte of space after the header for the target name.
321 // One extra byte is provided for target name.
322 char raw[33];
323 memcpy(raw, ntlm::test::kMinChallengeMessage, 32);
324 // Modify the default valid message to indicate 2 bytes are present in the
325 // target name payload (however there is only space for 1).
326 raw[12] = 0x02;
327 raw[14] = 0x02;
328 // Put something in the target name.
329 raw[32] = 'Z';
330
331 // The above malformed message could cause an implementation to read outside
332 // the message buffer because the length is longer than available space.
333 // Verify it gets rejected.
334 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
335 HandleAnotherChallenge(
336 CreateNtlmAuthHeader(base::StringPiece(raw, sizeof(raw)))));
337 ASSERT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
338 }
339
340 TEST_F(HttpAuthHandlerNtlmPortableTest, Type3RespectsUnicode) {
341 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockRandom,
342 MockGetHostName);
343 ASSERT_EQ(OK, CreateHandler());
344 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
345
346 // Generate the type 2 message from the server.
347 ntlm::NtlmBufferWriter writer(ntlm::kChallengeHeaderLen);
348 ASSERT_TRUE(writer.WriteMessageHeader(ntlm::MessageType::kChallenge));
349 // No target name. It is never used.
350 ASSERT_TRUE(writer.WriteSecurityBuffer(
351 ntlm::SecurityBuffer(ntlm::kChallengeHeaderLen, 0)));
352 // Set the unicode flag.
353 ASSERT_TRUE(writer.WriteFlags(ntlm::NegotiateFlags::kUnicode));
354
355 std::string token;
356 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
357 HandleAnotherChallenge(CreateNtlmAuthHeader(writer.GetBuffer())));
358 ASSERT_EQ(OK, GenerateAuthToken(&token));
359
360 // Validate the type 3 message
361 std::string decoded;
362 ASSERT_TRUE(DecodeChallenge(token, &decoded));
363 ntlm::NtlmBufferReader reader(decoded);
364 ASSERT_TRUE(reader.MatchMessageHeader(ntlm::MessageType::kAuthenticate));
365
366 // Skip the LM and NTLM Hash fields. This test isn't testing that.
367 ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
368 ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
369 base::string16 domain;
370 base::string16 username;
371 base::string16 hostname;
372 ReadString16Payload(&reader, &domain);
373 ASSERT_EQ(ntlm::test::kNtlmDomain, domain);
374 ReadString16Payload(&reader, &username);
375 ASSERT_EQ(ntlm::test::kUser, username);
376 ReadString16Payload(&reader, &hostname);
377 ASSERT_EQ(ntlm::test::kHostname, hostname);
378
379 // The session key is not used for the NTLM scheme in HTTP. Since
380 // NTLMSSP_NEGOTIATE_KEY_EXCH was not sent this is empty.
381 ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
382
383 // Verify the unicode flag is set.
384 ntlm::NegotiateFlags flags;
385 ASSERT_TRUE(reader.ReadFlags(&flags));
386 ASSERT_EQ(ntlm::NegotiateFlags::kUnicode,
387 flags & ntlm::NegotiateFlags::kUnicode);
388 }
389
390 TEST_F(HttpAuthHandlerNtlmPortableTest, Type3WithoutUnicode) {
391 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockRandom,
392 MockGetHostName);
393 ASSERT_EQ(OK, CreateHandler());
394 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
395
396 // Generate the type 2 message from the server.
397 ntlm::NtlmBufferWriter writer(ntlm::kChallengeHeaderLen);
398 ASSERT_TRUE(writer.WriteMessageHeader(ntlm::MessageType::kChallenge));
399 // No target name. It is never used.
400 ASSERT_TRUE(writer.WriteSecurityBuffer(
401 ntlm::SecurityBuffer(ntlm::kChallengeHeaderLen, 0)));
402 // Set the OEM flag.
403 ASSERT_TRUE(writer.WriteFlags(ntlm::NegotiateFlags::kOem));
404
405 std::string token;
406 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
407 HandleAnotherChallenge(CreateNtlmAuthHeader(writer.GetBuffer())));
408 ASSERT_EQ(OK, GenerateAuthToken(&token));
409
410 // Validate the type 3 message
411 std::string decoded;
412 ASSERT_TRUE(DecodeChallenge(token, &decoded));
413 ntlm::NtlmBufferReader reader(decoded);
414 ASSERT_TRUE(reader.MatchMessageHeader(ntlm::MessageType::kAuthenticate));
415
416 // Skip the 2 hash fields. This test isn't testing that.
417 ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
418 ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
419 std::string domain;
420 std::string username;
421 std::string hostname;
422 ReadStringPayload(&reader, &domain);
423 ASSERT_EQ(ntlm::test::kNtlmDomainAscii, domain);
424 ReadStringPayload(&reader, &username);
425 ASSERT_EQ(ntlm::test::kUserAscii, username);
426 ReadStringPayload(&reader, &hostname);
427 ASSERT_EQ(ntlm::test::kHostnameAscii, hostname);
428
429 // The session key is not used for the NTLM scheme in HTTP. Since
430 // NTLMSSP_NEGOTIATE_KEY_EXCH was not sent this is empty.
431 ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
432
433 // Verify the unicode flag is not set and OEM flag is.
434 ntlm::NegotiateFlags flags;
435 ASSERT_TRUE(reader.ReadFlags(&flags));
436 ASSERT_EQ(ntlm::NegotiateFlags::kNone,
437 flags & ntlm::NegotiateFlags::kUnicode);
438 ASSERT_EQ(ntlm::NegotiateFlags::kOem, flags & ntlm::NegotiateFlags::kOem);
439 }
440
441 TEST_F(HttpAuthHandlerNtlmPortableTest, Type3UnicodeNoSessionSecurity) {
442 // Verify that the client won't be downgraded if the server clears
443 // the session security flag.
444 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockRandom,
445 MockGetHostName);
446 ASSERT_EQ(OK, CreateHandler());
447 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
448
449 // Generate the type 2 message from the server.
450 ntlm::NtlmBufferWriter writer(ntlm::kChallengeHeaderLen);
451 ASSERT_TRUE(writer.WriteMessageHeader(ntlm::MessageType::kChallenge));
452 // No target name. It is never used.
453 ASSERT_TRUE(writer.WriteSecurityBuffer(
454 ntlm::SecurityBuffer(ntlm::kChallengeHeaderLen, 0)));
455 // Set the unicode but not the session security flag.
456 ASSERT_TRUE(writer.WriteFlags(ntlm::NegotiateFlags::kUnicode));
457
458 ASSERT_TRUE(
459 writer.WriteBytes(ntlm::test::kServerChallenge, ntlm::kChallengeLen));
460 ASSERT_TRUE(writer.IsEndOfBuffer());
461
462 std::string token;
463 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
464 HandleAnotherChallenge(CreateNtlmAuthHeader(writer.GetBuffer())));
465 ASSERT_EQ(OK, GenerateAuthToken(&token));
466
467 // Validate the type 3 message
468 std::string decoded;
469 ASSERT_TRUE(DecodeChallenge(token, &decoded));
470 ntlm::NtlmBufferReader reader(decoded);
471 ASSERT_TRUE(reader.MatchMessageHeader(ntlm::MessageType::kAuthenticate));
472
473 // Read the LM and NTLM Response Payloads.
474 uint8_t actual_lm_response[ntlm::kResponseLenV1];
475 uint8_t actual_ntlm_response[ntlm::kResponseLenV1];
476 ReadBytesPayload(&reader, actual_lm_response, ntlm::kResponseLenV1);
477 ReadBytesPayload(&reader, actual_ntlm_response, ntlm::kResponseLenV1);
478
479 // Verify that the client still generated a response that uses
480 // session security.
481 ASSERT_EQ(0, memcmp(ntlm::test::kExpectedLmResponseWithV1SS,
482 actual_lm_response, ntlm::kResponseLenV1));
483 ASSERT_EQ(0, memcmp(ntlm::test::kExpectedNtlmResponseWithV1SS,
484 actual_ntlm_response, ntlm::kResponseLenV1));
485
486 base::string16 domain;
487 base::string16 username;
488 base::string16 hostname;
489 ReadString16Payload(&reader, &domain);
490 ASSERT_EQ(ntlm::test::kNtlmDomain, domain);
491 ReadString16Payload(&reader, &username);
492 ASSERT_EQ(ntlm::test::kUser, username);
493 ReadString16Payload(&reader, &hostname);
494 ASSERT_EQ(ntlm::test::kHostname, hostname);
495
496 // The session key is not used for the NTLM scheme in HTTP. Since
497 // NTLMSSP_NEGOTIATE_KEY_EXCH was not sent this is empty.
498 ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
499
500 // Verify the unicode flag is set.
501 ntlm::NegotiateFlags flags;
502 ASSERT_TRUE(reader.ReadFlags(&flags));
503 ASSERT_EQ(ntlm::NegotiateFlags::kUnicode,
504 flags & ntlm::NegotiateFlags::kUnicode);
505 }
506
507 TEST_F(HttpAuthHandlerNtlmPortableTest, Type3UnicodeWithSessionSecurity) {
508 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockRandom,
509 MockGetHostName);
510 ASSERT_EQ(OK, CreateHandler());
511 ASSERT_EQ(OK, GetGenerateAuthTokenResult());
512
513 // Generate the type 2 message from the server.
514 ntlm::NtlmBufferWriter writer(ntlm::kChallengeHeaderLen);
515 ASSERT_TRUE(writer.WriteMessageHeader(ntlm::MessageType::kChallenge));
516 // No target name. It is never used.
517 ASSERT_TRUE(writer.WriteSecurityBuffer(
518 ntlm::SecurityBuffer(ntlm::kChallengeHeaderLen, 0)));
519 // Set the unicode and session security flag.
520 ASSERT_TRUE(
521 writer.WriteFlags((ntlm::NegotiateFlags::kUnicode |
522 ntlm::NegotiateFlags::kExtendedSessionSecurity)));
523
524 ASSERT_TRUE(
525 writer.WriteBytes(ntlm::test::kServerChallenge, ntlm::kChallengeLen));
526 ASSERT_TRUE(writer.IsEndOfBuffer());
527
528 std::string token;
529 ASSERT_EQ(HttpAuth::AUTHORIZATION_RESULT_ACCEPT,
530 HandleAnotherChallenge(CreateNtlmAuthHeader(writer.GetBuffer())));
531 ASSERT_EQ(OK, GenerateAuthToken(&token));
532
533 // Validate the type 3 message
534 std::string decoded;
535 ASSERT_TRUE(DecodeChallenge(token, &decoded));
536 ntlm::NtlmBufferReader reader(decoded);
537 ASSERT_TRUE(reader.MatchMessageHeader(ntlm::MessageType::kAuthenticate));
538
539 // Read the LM and NTLM Response Payloads.
540 uint8_t actual_lm_response[ntlm::kResponseLenV1];
541 uint8_t actual_ntlm_response[ntlm::kResponseLenV1];
542 ReadBytesPayload(&reader, actual_lm_response, ntlm::kResponseLenV1);
543 ReadBytesPayload(&reader, actual_ntlm_response, ntlm::kResponseLenV1);
544
545 ASSERT_EQ(0, memcmp(ntlm::test::kExpectedLmResponseWithV1SS,
546 actual_lm_response, ntlm::kResponseLenV1));
547 ASSERT_EQ(0, memcmp(ntlm::test::kExpectedNtlmResponseWithV1SS,
548 actual_ntlm_response, ntlm::kResponseLenV1));
549
550 base::string16 domain;
551 base::string16 username;
552 base::string16 hostname;
553 ReadString16Payload(&reader, &domain);
554 ASSERT_EQ(ntlm::test::kNtlmDomain, domain);
555 ReadString16Payload(&reader, &username);
556 ASSERT_EQ(ntlm::test::kUser, username);
557 ReadString16Payload(&reader, &hostname);
558 ASSERT_EQ(ntlm::test::kHostname, hostname);
559
560 // The session key is not used for the NTLM scheme in HTTP. Since
561 // NTLMSSP_NEGOTIATE_KEY_EXCH was not sent this is empty.
562 ASSERT_TRUE(reader.SkipSecurityBufferWithValidation());
563
564 // Verify the unicode flag is set.
565 ntlm::NegotiateFlags flags;
566 ASSERT_TRUE(reader.ReadFlags(&flags));
567 ASSERT_EQ(ntlm::NegotiateFlags::kUnicode,
568 flags & ntlm::NegotiateFlags::kUnicode);
569 }
570
571 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_auth_handler_ntlm_portable.cc ('k') | net/http/md4.h » ('j') | net/ntlm/des.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698