OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/http/http_auth_handler_ntlm.h" | 5 #include "net/http/http_auth_handler_ntlm.h" |
6 | 6 |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 // For gethostname | 8 // For gethostname |
9 #if defined(OS_POSIX) | 9 #if defined(OS_POSIX) |
10 #include <unistd.h> | 10 #include <unistd.h> |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 LogBuf("flags", (const uint8*) &msg->flags, 4); | 427 LogBuf("flags", (const uint8*) &msg->flags, 4); |
428 LogFlags(msg->flags); | 428 LogFlags(msg->flags); |
429 LogBuf("challenge", msg->challenge, sizeof(msg->challenge)); | 429 LogBuf("challenge", msg->challenge, sizeof(msg->challenge)); |
430 | 430 |
431 // We currently do not implement LMv2/NTLMv2 or NTLM2 responses, | 431 // We currently do not implement LMv2/NTLMv2 or NTLM2 responses, |
432 // so we can ignore target information. We may want to enable | 432 // so we can ignore target information. We may want to enable |
433 // support for these alternate mechanisms in the future. | 433 // support for these alternate mechanisms in the future. |
434 return OK; | 434 return OK; |
435 } | 435 } |
436 | 436 |
| 437 static void GenerateRandom(uint8* output, size_t n) { |
| 438 for (size_t i = 0; i < n; ++i) |
| 439 output[i] = base::RandInt(0, 255); |
| 440 } |
| 441 |
| 442 static void GetHostName(char* name, size_t namelen) { |
| 443 if (gethostname(name, namelen) != 0) |
| 444 name[0] = '\0'; |
| 445 } |
| 446 |
| 447 // TODO(wtc): these two function pointers should become static members of |
| 448 // HttpAuthHandlerNTLM. They are file-scope static variables now so that |
| 449 // GenerateType3Msg can use them without being a friend function. We should |
| 450 // have HttpAuthHandlerNTLM absorb NTLMAuthModule and pass the host name and |
| 451 // random bytes as input arguments to GenerateType3Msg. |
| 452 static HttpAuthHandlerNTLM::GenerateRandomProc generate_random_proc_ = |
| 453 GenerateRandom; |
| 454 static HttpAuthHandlerNTLM::HostNameProc get_host_name_proc_ = GetHostName; |
| 455 |
437 // Returns OK or a network error code. | 456 // Returns OK or a network error code. |
438 static int GenerateType3Msg(const string16& domain, | 457 static int GenerateType3Msg(const string16& domain, |
439 const string16& username, | 458 const string16& username, |
440 const string16& password, | 459 const string16& password, |
441 const void* in_buf, | 460 const void* in_buf, |
442 uint32 in_len, | 461 uint32 in_len, |
443 void** out_buf, | 462 void** out_buf, |
444 uint32* out_len) { | 463 uint32* out_len) { |
445 // in_buf contains Type-2 msg (the challenge) from server. | 464 // in_buf contains Type-2 msg (the challenge) from server. |
446 | 465 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 } else { | 523 } else { |
505 oem_user_buf = base::SysWideToNativeMB(UTF16ToWide(username)); | 524 oem_user_buf = base::SysWideToNativeMB(UTF16ToWide(username)); |
506 user_ptr = oem_user_buf.data(); | 525 user_ptr = oem_user_buf.data(); |
507 user_len = oem_user_buf.length(); | 526 user_len = oem_user_buf.length(); |
508 } | 527 } |
509 | 528 |
510 // | 529 // |
511 // Get workstation name (use local machine's hostname). | 530 // Get workstation name (use local machine's hostname). |
512 // | 531 // |
513 char host_buf[256]; // Host names are limited to 255 bytes. | 532 char host_buf[256]; // Host names are limited to 255 bytes. |
514 if (gethostname(host_buf, sizeof(host_buf)) != 0) | 533 get_host_name_proc_(host_buf, sizeof(host_buf)); |
| 534 host_len = strlen(host_buf); |
| 535 if (host_len == 0) |
515 return ERR_UNEXPECTED; | 536 return ERR_UNEXPECTED; |
516 host_len = strlen(host_buf); | |
517 if (unicode) { | 537 if (unicode) { |
518 // hostname is ASCII, so we can do a simple zero-pad expansion: | 538 // hostname is ASCII, so we can do a simple zero-pad expansion: |
519 ucs_host_buf.assign(host_buf, host_buf + host_len); | 539 ucs_host_buf.assign(host_buf, host_buf + host_len); |
520 host_ptr = ucs_host_buf.data(); | 540 host_ptr = ucs_host_buf.data(); |
521 host_len = ucs_host_buf.length() * 2; | 541 host_len = ucs_host_buf.length() * 2; |
522 #ifdef IS_BIG_ENDIAN | 542 #ifdef IS_BIG_ENDIAN |
523 WriteUnicodeLE(const_cast<void*>(host_ptr), (const char16*) host_ptr, | 543 WriteUnicodeLE(const_cast<void*>(host_ptr), (const char16*) host_ptr, |
524 ucs_host_buf.length()); | 544 ucs_host_buf.length()); |
525 #endif | 545 #endif |
526 } else { | 546 } else { |
(...skipping 13 matching lines...) Expand all Loading... |
540 // Next, we compute the LM and NTLM responses. | 560 // Next, we compute the LM and NTLM responses. |
541 // | 561 // |
542 uint8 lm_resp[LM_RESP_LEN]; | 562 uint8 lm_resp[LM_RESP_LEN]; |
543 uint8 ntlm_resp[NTLM_RESP_LEN]; | 563 uint8 ntlm_resp[NTLM_RESP_LEN]; |
544 uint8 ntlm_hash[NTLM_HASH_LEN]; | 564 uint8 ntlm_hash[NTLM_HASH_LEN]; |
545 if (msg.flags & NTLM_NegotiateNTLM2Key) { | 565 if (msg.flags & NTLM_NegotiateNTLM2Key) { |
546 // compute NTLM2 session response | 566 // compute NTLM2 session response |
547 MD5Digest session_hash; | 567 MD5Digest session_hash; |
548 uint8 temp[16]; | 568 uint8 temp[16]; |
549 | 569 |
550 // TODO(wtc): Add a function that generates random bytes so we can say: | 570 generate_random_proc_(lm_resp, 8); |
551 // GenerateRandom(lm_resp, 8); | |
552 for (int i = 0; i < 8; ++i) | |
553 lm_resp[i] = base::RandInt(0, 255); | |
554 memset(lm_resp + 8, 0, LM_RESP_LEN - 8); | 571 memset(lm_resp + 8, 0, LM_RESP_LEN - 8); |
555 | 572 |
556 memcpy(temp, msg.challenge, 8); | 573 memcpy(temp, msg.challenge, 8); |
557 memcpy(temp + 8, lm_resp, 8); | 574 memcpy(temp + 8, lm_resp, 8); |
558 MD5Sum(temp, 16, &session_hash); | 575 MD5Sum(temp, 16, &session_hash); |
559 | 576 |
560 NTLM_Hash(password, ntlm_hash); | 577 NTLM_Hash(password, ntlm_hash); |
561 LM_Response(ntlm_hash, session_hash.a, ntlm_resp); | 578 LM_Response(ntlm_hash, session_hash.a, ntlm_resp); |
562 } else { | 579 } else { |
563 NTLM_Hash(password, ntlm_hash); | 580 NTLM_Hash(password, ntlm_hash); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 std::string encode_input(static_cast<char*>(out_buf), out_buf_len); | 767 std::string encode_input(static_cast<char*>(out_buf), out_buf_len); |
751 std::string encode_output; | 768 std::string encode_output; |
752 bool ok = Base64Encode(encode_input, &encode_output); | 769 bool ok = Base64Encode(encode_input, &encode_output); |
753 // OK, we are done with |out_buf| | 770 // OK, we are done with |out_buf| |
754 free(out_buf); | 771 free(out_buf); |
755 if (!ok) | 772 if (!ok) |
756 return std::string(); | 773 return std::string(); |
757 return std::string("NTLM ") + encode_output; | 774 return std::string("NTLM ") + encode_output; |
758 } | 775 } |
759 | 776 |
| 777 // static |
| 778 void HttpAuthHandlerNTLM::SetGenerateRandomProc(GenerateRandomProc proc) { |
| 779 generate_random_proc_ = proc; |
| 780 } |
| 781 |
| 782 // static |
| 783 void HttpAuthHandlerNTLM::SetHostNameProc(HostNameProc proc) { |
| 784 get_host_name_proc_ = proc; |
| 785 } |
| 786 |
760 // The NTLM challenge header looks like: | 787 // The NTLM challenge header looks like: |
761 // WWW-Authenticate: NTLM auth-data | 788 // WWW-Authenticate: NTLM auth-data |
762 bool HttpAuthHandlerNTLM::ParseChallenge( | 789 bool HttpAuthHandlerNTLM::ParseChallenge( |
763 std::string::const_iterator challenge_begin, | 790 std::string::const_iterator challenge_begin, |
764 std::string::const_iterator challenge_end) { | 791 std::string::const_iterator challenge_end) { |
765 scheme_ = "ntlm"; | 792 scheme_ = "ntlm"; |
766 score_ = 3; | 793 score_ = 3; |
767 properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED; | 794 properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED; |
768 auth_data_.clear(); | 795 auth_data_.clear(); |
769 | 796 |
770 // Verify the challenge's auth-scheme. | 797 // Verify the challenge's auth-scheme. |
771 HttpAuth::ChallengeTokenizer challenge_tok(challenge_begin, challenge_end); | 798 HttpAuth::ChallengeTokenizer challenge_tok(challenge_begin, challenge_end); |
772 if (!challenge_tok.valid() || | 799 if (!challenge_tok.valid() || |
773 !LowerCaseEqualsASCII(challenge_tok.scheme(), "ntlm")) | 800 !LowerCaseEqualsASCII(challenge_tok.scheme(), "ntlm")) |
774 return false; | 801 return false; |
775 | 802 |
776 // Extract the auth-data. We can't use challenge_tok.GetNext() because | 803 // Extract the auth-data. We can't use challenge_tok.GetNext() because |
777 // auth-data is base64-encoded and may contain '=' padding at the end, | 804 // auth-data is base64-encoded and may contain '=' padding at the end, |
778 // which would be mistaken for a name=value pair. | 805 // which would be mistaken for a name=value pair. |
779 challenge_begin += 4; // Skip over "NTLM". | 806 challenge_begin += 4; // Skip over "NTLM". |
780 HttpUtil::TrimLWS(&challenge_begin, &challenge_end); | 807 HttpUtil::TrimLWS(&challenge_begin, &challenge_end); |
781 | 808 |
782 auth_data_.assign(challenge_begin, challenge_end); | 809 auth_data_.assign(challenge_begin, challenge_end); |
783 | 810 |
784 return true; | 811 return true; |
785 } | 812 } |
786 | 813 |
787 } // namespace net | 814 } // namespace net |
OLD | NEW |