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

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

Powered by Google App Engine
This is Rietveld 408576698