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

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: Add unit tests for existing NTLM portable code. Created 3 years, 6 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 (c) 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 "net/http/http_auth_handler_ntlm.h"
6
7 #include <string>
8
9 #include "base/base64.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "net/base/net_errors.h"
14 #include "net/base/test_completion_callback.h"
15 #include "net/dns/mock_host_resolver.h"
16 #include "net/http/http_auth_challenge_tokenizer.h"
17 #include "net/http/http_request_info.h"
18 #include "net/http/mock_allow_http_auth_preferences.h"
19 #include "net/http/ntlm.h"
20 #include "net/http/ntlm_buffer_reader.h"
21 #include "net/http/ntlm_buffer_writer.h"
22 #include "net/http/ntlm_client.h"
23 #include "net/log/net_log_with_source.h"
24 #include "net/ssl/ssl_info.h"
25 #include "net/test/gtest_util.h"
26 #include "testing/gmock/include/gmock/gmock.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "testing/platform_test.h"
29
30 using net::test::IsError;
31 using net::test::IsOk;
32
33 namespace net {
34
35 #if defined(NTLM_PORTABLE)
36
37 class HttpAuthHandlerNtlmPortableTest : public PlatformTest {
38 public:
39 HttpAuthHandlerNtlmPortableTest()
40 : domain_ascii_("THEDOMAIN"),
41 user_ascii_("someuser"),
42 password_ascii_("password") {
43 http_auth_preferences_.reset(new MockAllowHttpAuthPreferences());
44 factory_.reset(new HttpAuthHandlerNTLM::Factory());
45 factory_->set_http_auth_preferences(http_auth_preferences_.get());
46 creds_ =
47 AuthCredentials(base::ASCIIToUTF16(domain_ascii_ + "\\" + user_ascii_),
48 base::ASCIIToUTF16(password_ascii_));
49 }
50
51 int CreateHandler() {
52 GURL gurl("https://foo.com");
53 SSLInfo null_ssl_info;
54
55 return factory_->CreateAuthHandlerFromString(
56 "NTLM", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, NetLogWithSource(),
57 &auth_handler_);
58 }
59
60 std::string CreateType2Token(base::StringPiece message) {
61 std::string output;
62 base::Base64Encode(message, &output);
63
64 return "NTLM " + output;
65 }
66
67 void HandleAnotherChallenge(const std::string& challenge,
68 HttpAuth::AuthorizationResult expected_result) {
69 HttpAuthChallengeTokenizer tokenizer(challenge.begin(), challenge.end());
70 EXPECT_EQ(expected_result,
71 GetAuthHandler()->HandleAnotherChallenge(&tokenizer));
72 }
73
74 void HandleAnotherChallenge(const std::string& challenge) {
75 HandleAnotherChallenge(challenge, HttpAuth::AUTHORIZATION_RESULT_ACCEPT);
76 }
77
78 bool DecodeChallenge(const std::string& challenge, std::string* decoded) {
79 HttpAuthChallengeTokenizer tokenizer(challenge.begin(), challenge.end());
80 return base::Base64Decode(tokenizer.base64_param(), decoded);
81 }
82
83 int GenerateAuthToken(std::string* token) {
84 TestCompletionCallback callback;
85 HttpRequestInfo request_info;
86 return callback.GetResult(GetAuthHandler()->GenerateAuthToken(
87 GetCreds(), &request_info, callback.callback(), token));
88 }
89
90 int GetGenerateAuthTokenResult() {
91 std::string token;
92 return GenerateAuthToken(&token);
93 }
94
95 AuthCredentials* GetCreds() { return &creds_; }
96
97 HttpAuthHandlerNTLM* GetAuthHandler() {
98 return static_cast<HttpAuthHandlerNTLM*>(auth_handler_.get());
99 }
100
101 static void MockRandom(uint8_t* output, size_t n) {
102 static const uint8_t bytes[] = {0x55, 0x29, 0x66, 0x26,
103 0x6b, 0x9c, 0x73, 0x54};
104 static size_t current_byte = 0;
105 for (size_t i = 0; i < n; ++i) {
106 output[i] = bytes[current_byte++];
107 current_byte %= arraysize(bytes);
108 }
109 }
110
111 static std::string MockGetHostName() { return "MYHOSTNAME"; }
112
113 protected:
114 const std::string domain_ascii_;
115 const std::string user_ascii_;
116 const std::string password_ascii_;
117
118 private:
119 AuthCredentials creds_;
120 std::unique_ptr<HttpAuthHandler> auth_handler_;
121 std::unique_ptr<MockAllowHttpAuthPreferences> http_auth_preferences_;
122 std::unique_ptr<HttpAuthHandlerNTLM::Factory> factory_;
123 };
124
125 TEST_F(HttpAuthHandlerNtlmPortableTest, SimpleConstruction) {
126 EXPECT_EQ(OK, CreateHandler());
127 ASSERT_TRUE(GetAuthHandler() != nullptr);
128 }
129
130 TEST_F(HttpAuthHandlerNtlmPortableTest, DoNotAllowDefaultCreds) {
131 EXPECT_EQ(OK, CreateHandler());
132 EXPECT_FALSE(GetAuthHandler()->AllowsDefaultCredentials());
133 }
134
135 TEST_F(HttpAuthHandlerNtlmPortableTest, AllowsExplicitCredentials) {
136 EXPECT_EQ(OK, CreateHandler());
137 EXPECT_TRUE(GetAuthHandler()->AllowsExplicitCredentials());
138 }
139
140 TEST_F(HttpAuthHandlerNtlmPortableTest, VerifyType1Message) {
141 EXPECT_EQ(OK, CreateHandler());
142
143 std::string token;
144 EXPECT_EQ(OK, GenerateAuthToken(&token));
145 // The type 1 message generated is always the same. The only variable
146 // part of the message is the flags and Chrome always offers the same
147 // set of flags.
148 EXPECT_EQ("NTLM TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=", token);
149
150 // Poke into the message to verify the fields inside are expected.
151 std::string decoded;
152 EXPECT_TRUE(DecodeChallenge(token, &decoded));
153
154 NtlmBufferReader reader(decoded);
155 EXPECT_TRUE(reader.MatchMessageHeader(ntlm::MESSAGE_NEGOTIATE));
156 uint32_t flags;
157 EXPECT_TRUE(reader.ReadUInt32(&flags));
158 EXPECT_EQ(ntlm::NEGOTIATE_MESSAGE_FLAGS, flags);
159 EXPECT_TRUE(reader.MatchEmptySecurityBuffer());
160 EXPECT_TRUE(reader.MatchEmptySecurityBuffer());
161 EXPECT_TRUE(reader.IsEndOfBuffer());
162 }
163
164 TEST_F(HttpAuthHandlerNtlmPortableTest, EmptyTokenFails) {
165 EXPECT_EQ(OK, CreateHandler());
166
167 // The encoded token for a type 2 message can't be empty.
168 HandleAnotherChallenge("NTLM", HttpAuth::AUTHORIZATION_RESULT_REJECT);
169 }
170
171 TEST_F(HttpAuthHandlerNtlmPortableTest, InvalidBase64Encoding) {
172 EXPECT_EQ(OK, CreateHandler());
173
174 // Token isn't valid base64.
175 HandleAnotherChallenge("NTLM !!!!!!!!!!!!!");
176 EXPECT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
177 }
178
179 TEST_F(HttpAuthHandlerNtlmPortableTest, CantChangeSchemeMidway) {
180 EXPECT_EQ(OK, CreateHandler());
181
182 // Can't switch to a different auth scheme in the middle of the process.
183 HandleAnotherChallenge(
184 "Negotiate "
185 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCXziKeNIPIDYAAAAAAAAAAIYAhgBEAAAABgOAJQAA"
186 "AA9aAEUATgBEAE8ATQACAAwAWgBFAE4ARABPAE0AAQAMAFoARQBOAEQAQwAxAAQAFAB6AGUA"
187 "bgBkAG8AbQAuAGwAbwBjAAMAIgBaAGUAbgBEAEMAMQAuAHoAZQBuAGQAbwBtAC4AbABvAGMA"
188 "BQAUAHoAZQBuAGQAbwBtAC4AbABvAGMABwAIAN6N+IxGwNIBAAAAAA==",
189 HttpAuth::AUTHORIZATION_RESULT_INVALID);
190 }
191
192 TEST_F(HttpAuthHandlerNtlmPortableTest, Type2MessageTooShort) {
193 EXPECT_EQ(OK, CreateHandler());
194
195 // Fail because the minimum size valid message is 32 bytes.
196 char raw[31];
197 HandleAnotherChallenge(CreateType2Token(base::StringPiece(raw, sizeof(raw))));
198 EXPECT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
199 }
200
201 TEST_F(HttpAuthHandlerNtlmPortableTest, Type2MessageNoSig) {
202 EXPECT_EQ(OK, CreateHandler());
203
204 // Fail because the first bytes don't match "NTLMSSP\0"
205 char raw[32];
206 memset(raw, 0, ntlm::SIGNATURE_LEN);
207 HandleAnotherChallenge(CreateType2Token(base::StringPiece(raw, sizeof(raw))));
208 EXPECT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
209 }
210
211 TEST_F(HttpAuthHandlerNtlmPortableTest, Type2WrongMessageType) {
212 EXPECT_EQ(OK, CreateHandler());
213
214 // Fail because the message type should be MESSAGE_CHALLENGE (0x00000002)
215 NtlmBufferWriter writer(32);
216 writer.WriteMessageHeader(ntlm::MESSAGE_NEGOTIATE);
217
218 HandleAnotherChallenge(CreateType2Token(writer.GetBuffer()));
219 EXPECT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
220 }
221
222 TEST_F(HttpAuthHandlerNtlmPortableTest, MinimalStructurallyValidType2) {
223 EXPECT_EQ(OK, CreateHandler());
224
225 NtlmBufferWriter writer(32);
226 writer.WriteMessageHeader(ntlm::MESSAGE_CHALLENGE);
227
228 // A message with both length and offset equal zero is not forbidden
229 // by the spec (2.2.1.2) however it is not what is recommended.
230 // But test it anyway.
231 writer.WriteEmptySecurityBuffer();
232
233 HandleAnotherChallenge(CreateType2Token(writer.GetBuffer()));
234 EXPECT_EQ(OK, GetGenerateAuthTokenResult());
235 }
236
237 TEST_F(HttpAuthHandlerNtlmPortableTest, Type2MessageWithNoTargetName) {
238 EXPECT_EQ(OK, CreateHandler());
239
240 NtlmBufferWriter writer(32);
241 writer.WriteMessageHeader(ntlm::MESSAGE_CHALLENGE);
242
243 // The spec (2.2.1.2) states that the length SHOULD be 0 and the
244 // offset SHOULD be where the payload would be if it was present.
245 // This is the expected response from a compliant server when
246 // no target name is sent. In reality the offset should always
247 // be ignored if the length is zero. Also implementations often
248 // just write zeros.
249 writer.WriteSecurityBuffer(ntlm::SecurityBuffer(32, 0));
250
251 HandleAnotherChallenge(CreateType2Token(writer.GetBuffer()));
252 EXPECT_EQ(OK, GetGenerateAuthTokenResult());
253 }
254
255 TEST_F(HttpAuthHandlerNtlmPortableTest, Type2MessageWithTargetName) {
256 EXPECT_EQ(OK, CreateHandler());
257
258 // One extra byte is provided for target name.
259 NtlmBufferWriter writer(33);
260 writer.WriteMessageHeader(ntlm::MESSAGE_CHALLENGE);
261
262 // The target name field is 1 byte long.
263 writer.WriteSecurityBuffer(ntlm::SecurityBuffer(32, 1));
264
265 HandleAnotherChallenge(CreateType2Token(writer.GetBuffer()));
266 EXPECT_EQ(OK, GetGenerateAuthTokenResult());
267 }
268
269 TEST_F(HttpAuthHandlerNtlmPortableTest, NoTargetNameOverflowFromOffset) {
270 EXPECT_EQ(OK, CreateHandler());
271
272 NtlmBufferWriter writer(32);
273 writer.WriteMessageHeader(ntlm::MESSAGE_CHALLENGE);
274
275 // Claim that the target name field is 1 byte long and outside
276 // the buffer.
277 writer.WriteSecurityBuffer(ntlm::SecurityBuffer(32, 1));
278
279 // The above malformed message could cause an implementation
280 // to read outside the message buffer because the offset is
281 // past the end of the message. Verify it gets rejected.
282 HandleAnotherChallenge(CreateType2Token(writer.GetBuffer()));
283 EXPECT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
284 }
285
286 TEST_F(HttpAuthHandlerNtlmPortableTest, NoTargetNameOverflowFromLength) {
287 EXPECT_EQ(OK, CreateHandler());
288
289 // Message has 1 extra byte of space after the header for the
290 // target name.
291 NtlmBufferWriter writer(33);
292 writer.WriteMessageHeader(ntlm::MESSAGE_CHALLENGE);
293 // Claim that the target name field is 2 bytes long but
294 // there is only 1 byte of space.
295 writer.WriteSecurityBuffer(ntlm::SecurityBuffer(32, 2));
296
297 // The above malformed message could cause an implementation
298 // to read outside the message buffer because the length is
299 // longer than available space. Verify it gets rejected.
300 HandleAnotherChallenge(CreateType2Token(writer.GetBuffer()));
301 EXPECT_EQ(ERR_UNEXPECTED, GetGenerateAuthTokenResult());
302 }
303
304 TEST_F(HttpAuthHandlerNtlmPortableTest, Type3RespectsUnicode) {
305 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockRandom,
306 MockGetHostName);
307 EXPECT_EQ(OK, CreateHandler());
308
309 // Generate the type 2 message from the server.
310 NtlmBufferWriter writer(32);
311 writer.WriteMessageHeader(ntlm::MESSAGE_CHALLENGE);
312 // No target name. Chrome doesn't use it anyway.
313 writer.WriteEmptySecurityBuffer();
314 // Set the unicode flag.
315 writer.WriteUInt32(ntlm::NTLMSSP_NEGOTIATE_UNICODE);
316
317 std::string token;
318 HandleAnotherChallenge(CreateType2Token(writer.GetBuffer()));
319 EXPECT_EQ(OK, GenerateAuthToken(&token));
320
321 // Validate the type 3 message
322 std::string decoded;
323 EXPECT_TRUE(DecodeChallenge(token, &decoded));
324 NtlmBufferReader reader(decoded);
325 EXPECT_TRUE(reader.MatchMessageHeader(ntlm::MESSAGE_AUTHENTICATE));
326
327 // Skip the LM and NTLM Hash fields. This test isn't testing that.
328 EXPECT_TRUE(reader.SkipSecurityBuffer());
329 EXPECT_TRUE(reader.SkipSecurityBuffer());
330 base::string16 domain;
331 base::string16 username;
332 base::string16 hostname;
333 EXPECT_TRUE(reader.ReadUnicodePayload(&domain));
334 EXPECT_EQ(base::ASCIIToUTF16(domain_ascii_), domain);
335 EXPECT_TRUE(reader.ReadUnicodePayload(&username));
336 EXPECT_EQ(base::ASCIIToUTF16(user_ascii_), username);
337 EXPECT_TRUE(reader.ReadUnicodePayload(&hostname));
338 EXPECT_EQ(base::ASCIIToUTF16(MockGetHostName()), hostname);
339
340 // Skip the session key which isn't used.
341 EXPECT_TRUE(reader.SkipSecurityBufferWithValidation());
342
343 // Verify the unicode flag is set.
344 uint32_t flags;
345 EXPECT_TRUE(reader.ReadUInt32(&flags));
346 EXPECT_EQ(ntlm::NTLMSSP_NEGOTIATE_UNICODE,
347 flags & ntlm::NTLMSSP_NEGOTIATE_UNICODE);
348 }
349
350 TEST_F(HttpAuthHandlerNtlmPortableTest, Type3WithoutUnicode) {
351 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockRandom,
352 MockGetHostName);
353 EXPECT_EQ(OK, CreateHandler());
354
355 // Generate the type 2 message from the server.
356 NtlmBufferWriter writer(32);
357 writer.WriteMessageHeader(ntlm::MESSAGE_CHALLENGE);
358 // No target name. Chrome doesn't use it anyway.
359 writer.WriteEmptySecurityBuffer();
360 // Set the OEM flag.
361 writer.WriteUInt32(ntlm::NTLMSSP_NEGOTIATE_OEM);
362
363 std::string token;
364 HandleAnotherChallenge(CreateType2Token(writer.GetBuffer()));
365 EXPECT_EQ(OK, GenerateAuthToken(&token));
366
367 // Validate the type 3 message
368 std::string decoded;
369 EXPECT_TRUE(DecodeChallenge(token, &decoded));
370 NtlmBufferReader reader(decoded);
371 EXPECT_TRUE(reader.MatchMessageHeader(ntlm::MESSAGE_AUTHENTICATE));
372
373 // Skip the 2 hash fields. This test isn't testing that.
374 EXPECT_TRUE(reader.SkipSecurityBufferWithValidation());
375 EXPECT_TRUE(reader.SkipSecurityBufferWithValidation());
376 std::string domain;
377 std::string username;
378 std::string hostname;
379 EXPECT_TRUE(reader.ReadAsciiPayload(&domain));
380 EXPECT_EQ(domain_ascii_, domain);
381 EXPECT_TRUE(reader.ReadAsciiPayload(&username));
382 EXPECT_EQ(user_ascii_, username);
383 EXPECT_TRUE(reader.ReadAsciiPayload(&hostname));
384 EXPECT_EQ(MockGetHostName(), hostname);
385
386 // Skip the session key which isn't used.
387 EXPECT_TRUE(reader.SkipSecurityBufferWithValidation());
388
389 // Verify the unicode flag is not set and OEM flag is.
390 uint32_t flags;
391 EXPECT_TRUE(reader.ReadUInt32(&flags));
392 EXPECT_EQ(0u, flags & ntlm::NTLMSSP_NEGOTIATE_UNICODE);
393 EXPECT_EQ(ntlm::NTLMSSP_NEGOTIATE_OEM, flags & ntlm::NTLMSSP_NEGOTIATE_OEM);
394 }
395
396 TEST_F(HttpAuthHandlerNtlmPortableTest, Type3UnicodeNoSessionSecurity) {
397 // Verify that the client won't be downgraded if the server clears
398 // the session security flag.
399 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockRandom,
400 MockGetHostName);
401 EXPECT_EQ(OK, CreateHandler());
402
403 // Generate the type 2 message from the server.
404 NtlmBufferWriter writer(32);
405 EXPECT_TRUE(writer.WriteMessageHeader(ntlm::MESSAGE_CHALLENGE));
406 // No target name. Chrome doesn't use it anyway.
407 EXPECT_TRUE(writer.WriteEmptySecurityBuffer());
408 // Set the unicode but not the session security flag.
409 EXPECT_TRUE(writer.WriteUInt32(ntlm::NTLMSSP_NEGOTIATE_UNICODE));
410
411 uint8_t server_challenge[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
412 EXPECT_EQ(arraysize(server_challenge), ntlm::CHALLENGE_LEN);
413 EXPECT_TRUE(writer.WriteBytes(server_challenge, ntlm::CHALLENGE_LEN));
414 EXPECT_TRUE(writer.IsEndOfBuffer());
415
416 std::string token;
417 HandleAnotherChallenge(CreateType2Token(writer.GetBuffer()));
418 EXPECT_EQ(OK, GenerateAuthToken(&token));
419
420 // Validate the type 3 message
421 std::string decoded;
422 EXPECT_TRUE(DecodeChallenge(token, &decoded));
423 NtlmBufferReader reader(decoded);
424 EXPECT_TRUE(reader.MatchMessageHeader(ntlm::MESSAGE_AUTHENTICATE));
425
426 // Read the LM and NTLM Response Payloads.
427 uint8_t expected_lm_response[ntlm::RESPONSE_V1_LEN];
428 uint8_t expected_ntlm_response[ntlm::RESPONSE_V1_LEN];
429 uint8_t actual_lm_response[ntlm::RESPONSE_V1_LEN];
430 uint8_t actual_ntlm_response[ntlm::RESPONSE_V1_LEN];
431
432 EXPECT_TRUE(
433 reader.ReadBytesPayload(actual_lm_response, ntlm::RESPONSE_V1_LEN));
434 EXPECT_TRUE(
435 reader.ReadBytesPayload(actual_ntlm_response, ntlm::RESPONSE_V1_LEN));
436
437 // Session security also uses a client generated challenge so
438 // use the mock to get the same value that the implementation
439 // would get.
440 uint8_t client_challenge[ntlm::CHALLENGE_LEN];
441 MockRandom(client_challenge, ntlm::CHALLENGE_LEN);
442
443 ntlm::GenerateResponsesV1WithSS(base::ASCIIToUTF16(password_ascii_),
444 server_challenge, client_challenge,
445 expected_lm_response, expected_ntlm_response);
446
447 // Verify that the client still generated a response that uses
448 // session security.
449 EXPECT_EQ(0, memcmp(expected_lm_response, actual_lm_response,
450 ntlm::RESPONSE_V1_LEN));
451 EXPECT_EQ(0, memcmp(expected_ntlm_response, actual_ntlm_response,
452 ntlm::RESPONSE_V1_LEN));
453
454 base::string16 domain;
455 base::string16 username;
456 base::string16 hostname;
457 EXPECT_TRUE(reader.ReadUnicodePayload(&domain));
458 EXPECT_EQ(base::ASCIIToUTF16(domain_ascii_), domain);
459 EXPECT_TRUE(reader.ReadUnicodePayload(&username));
460 EXPECT_EQ(base::ASCIIToUTF16(user_ascii_), username);
461 EXPECT_TRUE(reader.ReadUnicodePayload(&hostname));
462 EXPECT_EQ(base::ASCIIToUTF16(MockGetHostName()), hostname);
463
464 // Skip the session key which isn't used.
465 EXPECT_TRUE(reader.SkipSecurityBufferWithValidation());
466
467 // Verify the unicode flag is set.
468 uint32_t flags;
469 EXPECT_TRUE(reader.ReadUInt32(&flags));
470 EXPECT_EQ(ntlm::NTLMSSP_NEGOTIATE_UNICODE,
471 flags & ntlm::NTLMSSP_NEGOTIATE_UNICODE);
472 }
473
474 TEST_F(HttpAuthHandlerNtlmPortableTest, Type3UnicodeWithSessionSecurity) {
475 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockRandom,
476 MockGetHostName);
477 EXPECT_EQ(OK, CreateHandler());
478
479 // Generate the type 2 message from the server.
480 NtlmBufferWriter writer(32);
481 EXPECT_TRUE(writer.WriteMessageHeader(ntlm::MESSAGE_CHALLENGE));
482 // No target name. Chrome doesn't use it anyway.
483 EXPECT_TRUE(writer.WriteEmptySecurityBuffer());
484 // Set the unicode and session security flag.
485 EXPECT_TRUE(
486 writer.WriteUInt32(ntlm::NTLMSSP_NEGOTIATE_UNICODE |
487 ntlm::NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY));
488
489 uint8_t server_challenge[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
490 EXPECT_EQ(arraysize(server_challenge), ntlm::CHALLENGE_LEN);
491 EXPECT_TRUE(writer.WriteBytes(server_challenge, ntlm::CHALLENGE_LEN));
492 EXPECT_TRUE(writer.IsEndOfBuffer());
493
494 std::string token;
495 HandleAnotherChallenge(CreateType2Token(writer.GetBuffer()));
496 EXPECT_EQ(OK, GenerateAuthToken(&token));
497
498 // Validate the type 3 message
499 std::string decoded;
500 EXPECT_TRUE(DecodeChallenge(token, &decoded));
501 NtlmBufferReader reader(decoded);
502 EXPECT_TRUE(reader.MatchMessageHeader(ntlm::MESSAGE_AUTHENTICATE));
503
504 // Read the LM and NTLM Response Payloads.
505 uint8_t expected_lm_response[ntlm::RESPONSE_V1_LEN];
506 uint8_t expected_ntlm_response[ntlm::RESPONSE_V1_LEN];
507 uint8_t actual_lm_response[ntlm::RESPONSE_V1_LEN];
508 uint8_t actual_ntlm_response[ntlm::RESPONSE_V1_LEN];
509
510 EXPECT_TRUE(
511 reader.ReadBytesPayload(actual_lm_response, ntlm::RESPONSE_V1_LEN));
512 EXPECT_TRUE(
513 reader.ReadBytesPayload(actual_ntlm_response, ntlm::RESPONSE_V1_LEN));
514
515 // Session security also uses a client generated challenge so
516 // use the mock to get the same value that the implementation
517 // would get.
518 uint8_t client_challenge[ntlm::CHALLENGE_LEN];
519 MockRandom(client_challenge, ntlm::CHALLENGE_LEN);
520
521 ntlm::GenerateResponsesV1WithSS(base::ASCIIToUTF16(password_ascii_),
522 server_challenge, client_challenge,
523 expected_lm_response, expected_ntlm_response);
524
525 EXPECT_EQ(0, memcmp(expected_lm_response, actual_lm_response,
526 ntlm::RESPONSE_V1_LEN));
527 EXPECT_EQ(0, memcmp(expected_ntlm_response, actual_ntlm_response,
528 ntlm::RESPONSE_V1_LEN));
529
530 base::string16 domain;
531 base::string16 username;
532 base::string16 hostname;
533 EXPECT_TRUE(reader.ReadUnicodePayload(&domain));
534 EXPECT_EQ(base::ASCIIToUTF16(domain_ascii_), domain);
535 EXPECT_TRUE(reader.ReadUnicodePayload(&username));
536 EXPECT_EQ(base::ASCIIToUTF16(user_ascii_), username);
537 EXPECT_TRUE(reader.ReadUnicodePayload(&hostname));
538 EXPECT_EQ(base::ASCIIToUTF16(MockGetHostName()), hostname);
539
540 // Skip the session key which isn't used.
541 EXPECT_TRUE(reader.SkipSecurityBufferWithValidation());
542
543 // Verify the unicode flag is set.
544 uint32_t flags;
545 EXPECT_TRUE(reader.ReadUInt32(&flags));
546 EXPECT_EQ(ntlm::NTLMSSP_NEGOTIATE_UNICODE,
547 flags & ntlm::NTLMSSP_NEGOTIATE_UNICODE);
548 }
549
550 #endif // defined(NTLM_PORTABLE)
551
552 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698