| 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> |
| 11 #elif defined(OS_WIN) | 11 #elif defined(OS_WIN) |
| 12 #include <winsock2.h> | 12 #include <winsock2.h> |
| 13 #endif | 13 #endif |
| 14 | 14 |
| 15 #include "base/md5.h" | 15 #include "base/md5.h" |
| 16 #include "base/rand_util.h" | 16 #include "base/rand_util.h" |
| 17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
| 18 #include "base/sys_string_conversions.h" | 18 #include "base/sys_string_conversions.h" |
| 19 #include "net/base/base64.h" | 19 #include "net/base/base64.h" |
| 20 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" |
| 21 #include "net/base/net_util.h" |
| 21 #include "net/http/des.h" | 22 #include "net/http/des.h" |
| 22 #include "net/http/md4.h" | 23 #include "net/http/md4.h" |
| 23 | 24 |
| 24 namespace net { | 25 namespace net { |
| 25 | 26 |
| 26 // Based on mozilla/security/manager/ssl/src/nsNTLMAuthModule.cpp, | 27 // Based on mozilla/security/manager/ssl/src/nsNTLMAuthModule.cpp, |
| 27 // CVS rev. 1.14. | 28 // CVS rev. 1.14. |
| 28 // | 29 // |
| 29 // TODO(wtc): | 30 // TODO(wtc): |
| 30 // - The IS_BIG_ENDIAN code is not tested. | 31 // - The IS_BIG_ENDIAN code is not tested. |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 // so we can ignore target information. We may want to enable | 433 // so we can ignore target information. We may want to enable |
| 433 // support for these alternate mechanisms in the future. | 434 // support for these alternate mechanisms in the future. |
| 434 return OK; | 435 return OK; |
| 435 } | 436 } |
| 436 | 437 |
| 437 static void GenerateRandom(uint8* output, size_t n) { | 438 static void GenerateRandom(uint8* output, size_t n) { |
| 438 for (size_t i = 0; i < n; ++i) | 439 for (size_t i = 0; i < n; ++i) |
| 439 output[i] = base::RandInt(0, 255); | 440 output[i] = base::RandInt(0, 255); |
| 440 } | 441 } |
| 441 | 442 |
| 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 | |
| 456 // Returns OK or a network error code. | 443 // Returns OK or a network error code. |
| 457 static int GenerateType3Msg(const string16& domain, | 444 static int GenerateType3Msg(const string16& domain, |
| 458 const string16& username, | 445 const string16& username, |
| 459 const string16& password, | 446 const string16& password, |
| 460 const void* in_buf, | 447 const std::string& hostname, |
| 461 uint32 in_len, | 448 const void* rand_8_bytes, |
| 462 void** out_buf, | 449 const void* in_buf, |
| 463 uint32* out_len) { | 450 uint32 in_len, |
| 451 void** out_buf, |
| 452 uint32* out_len) { |
| 464 // in_buf contains Type-2 msg (the challenge) from server. | 453 // in_buf contains Type-2 msg (the challenge) from server. |
| 465 | 454 |
| 466 int rv; | 455 int rv; |
| 467 Type2Msg msg; | 456 Type2Msg msg; |
| 468 | 457 |
| 469 rv = ParseType2Msg(in_buf, in_len, &msg); | 458 rv = ParseType2Msg(in_buf, in_len, &msg); |
| 470 if (rv != OK) | 459 if (rv != OK) |
| 471 return rv; | 460 return rv; |
| 472 | 461 |
| 473 bool unicode = (msg.flags & NTLM_NegotiateUnicode) != 0; | 462 bool unicode = (msg.flags & NTLM_NegotiateUnicode) != 0; |
| 474 | 463 |
| 475 // Temporary buffers for unicode strings | 464 // Temporary buffers for unicode strings |
| 476 #ifdef IS_BIG_ENDIAN | 465 #ifdef IS_BIG_ENDIAN |
| 477 string16 ucs_domain_buf, ucs_user_buf; | 466 string16 ucs_domain_buf, ucs_user_buf; |
| 478 #endif | 467 #endif |
| 479 string16 ucs_host_buf; | 468 string16 ucs_host_buf; |
| 480 // Temporary buffers for oem strings | 469 // Temporary buffers for oem strings |
| 481 std::string oem_domain_buf, oem_user_buf, oem_host_buf; | 470 std::string oem_domain_buf, oem_user_buf; |
| 482 // Pointers and lengths for the string buffers; encoding is unicode if | 471 // Pointers and lengths for the string buffers; encoding is unicode if |
| 483 // the "negotiate unicode" flag was set in the Type-2 message. | 472 // the "negotiate unicode" flag was set in the Type-2 message. |
| 484 const void* domain_ptr; | 473 const void* domain_ptr; |
| 485 const void* user_ptr; | 474 const void* user_ptr; |
| 486 const void* host_ptr; | 475 const void* host_ptr; |
| 487 uint32 domain_len, user_len, host_len; | 476 uint32 domain_len, user_len, host_len; |
| 488 | 477 |
| 489 // | 478 // |
| 490 // Get domain name. | 479 // Get domain name. |
| 491 // | 480 // |
| (...skipping 30 matching lines...) Expand all Loading... |
| 522 #endif | 511 #endif |
| 523 } else { | 512 } else { |
| 524 oem_user_buf = base::SysWideToNativeMB(UTF16ToWide(username)); | 513 oem_user_buf = base::SysWideToNativeMB(UTF16ToWide(username)); |
| 525 user_ptr = oem_user_buf.data(); | 514 user_ptr = oem_user_buf.data(); |
| 526 user_len = oem_user_buf.length(); | 515 user_len = oem_user_buf.length(); |
| 527 } | 516 } |
| 528 | 517 |
| 529 // | 518 // |
| 530 // Get workstation name (use local machine's hostname). | 519 // Get workstation name (use local machine's hostname). |
| 531 // | 520 // |
| 532 char host_buf[256]; // Host names are limited to 255 bytes. | |
| 533 get_host_name_proc_(host_buf, sizeof(host_buf)); | |
| 534 host_len = strlen(host_buf); | |
| 535 if (host_len == 0) | |
| 536 return ERR_UNEXPECTED; | |
| 537 if (unicode) { | 521 if (unicode) { |
| 538 // hostname is ASCII, so we can do a simple zero-pad expansion: | 522 // hostname is ASCII, so we can do a simple zero-pad expansion: |
| 539 ucs_host_buf.assign(host_buf, host_buf + host_len); | 523 ucs_host_buf.assign(hostname.begin(), hostname.end()); |
| 540 host_ptr = ucs_host_buf.data(); | 524 host_ptr = ucs_host_buf.data(); |
| 541 host_len = ucs_host_buf.length() * 2; | 525 host_len = ucs_host_buf.length() * 2; |
| 542 #ifdef IS_BIG_ENDIAN | 526 #ifdef IS_BIG_ENDIAN |
| 543 WriteUnicodeLE(const_cast<void*>(host_ptr), (const char16*) host_ptr, | 527 WriteUnicodeLE(const_cast<void*>(host_ptr), (const char16*) host_ptr, |
| 544 ucs_host_buf.length()); | 528 ucs_host_buf.length()); |
| 545 #endif | 529 #endif |
| 546 } else { | 530 } else { |
| 547 host_ptr = host_buf; | 531 host_ptr = hostname.data(); |
| 532 host_len = hostname.length(); |
| 548 } | 533 } |
| 549 | 534 |
| 550 // | 535 // |
| 551 // Now that we have generated all of the strings, we can allocate out_buf. | 536 // Now that we have generated all of the strings, we can allocate out_buf. |
| 552 // | 537 // |
| 553 *out_len = NTLM_TYPE3_HEADER_LEN + host_len + domain_len + user_len + | 538 *out_len = NTLM_TYPE3_HEADER_LEN + host_len + domain_len + user_len + |
| 554 LM_RESP_LEN + NTLM_RESP_LEN; | 539 LM_RESP_LEN + NTLM_RESP_LEN; |
| 555 *out_buf = malloc(*out_len); | 540 *out_buf = malloc(*out_len); |
| 556 if (!*out_buf) | 541 if (!*out_buf) |
| 557 return ERR_OUT_OF_MEMORY; | 542 return ERR_OUT_OF_MEMORY; |
| 558 | 543 |
| 559 // | 544 // |
| 560 // Next, we compute the LM and NTLM responses. | 545 // Next, we compute the LM and NTLM responses. |
| 561 // | 546 // |
| 562 uint8 lm_resp[LM_RESP_LEN]; | 547 uint8 lm_resp[LM_RESP_LEN]; |
| 563 uint8 ntlm_resp[NTLM_RESP_LEN]; | 548 uint8 ntlm_resp[NTLM_RESP_LEN]; |
| 564 uint8 ntlm_hash[NTLM_HASH_LEN]; | 549 uint8 ntlm_hash[NTLM_HASH_LEN]; |
| 565 if (msg.flags & NTLM_NegotiateNTLM2Key) { | 550 if (msg.flags & NTLM_NegotiateNTLM2Key) { |
| 566 // compute NTLM2 session response | 551 // compute NTLM2 session response |
| 567 MD5Digest session_hash; | 552 MD5Digest session_hash; |
| 568 uint8 temp[16]; | 553 uint8 temp[16]; |
| 569 | 554 |
| 570 generate_random_proc_(lm_resp, 8); | 555 memcpy(lm_resp, rand_8_bytes, 8); |
| 571 memset(lm_resp + 8, 0, LM_RESP_LEN - 8); | 556 memset(lm_resp + 8, 0, LM_RESP_LEN - 8); |
| 572 | 557 |
| 573 memcpy(temp, msg.challenge, 8); | 558 memcpy(temp, msg.challenge, 8); |
| 574 memcpy(temp + 8, lm_resp, 8); | 559 memcpy(temp + 8, lm_resp, 8); |
| 575 MD5Sum(temp, 16, &session_hash); | 560 MD5Sum(temp, 16, &session_hash); |
| 576 | 561 |
| 577 NTLM_Hash(password, ntlm_hash); | 562 NTLM_Hash(password, ntlm_hash); |
| 578 LM_Response(ntlm_hash, session_hash.a, ntlm_resp); | 563 LM_Response(ntlm_hash, session_hash.a, ntlm_resp); |
| 579 } else { | 564 } else { |
| 580 NTLM_Hash(password, ntlm_hash); | 565 NTLM_Hash(password, ntlm_hash); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 | 616 |
| 632 // 52 : session key sec buf (not used) | 617 // 52 : session key sec buf (not used) |
| 633 cursor = WriteSecBuf(cursor, 0, 0); | 618 cursor = WriteSecBuf(cursor, 0, 0); |
| 634 | 619 |
| 635 // 60 : negotiated flags | 620 // 60 : negotiated flags |
| 636 cursor = WriteDWORD(cursor, msg.flags & NTLM_TYPE1_FLAGS); | 621 cursor = WriteDWORD(cursor, msg.flags & NTLM_TYPE1_FLAGS); |
| 637 | 622 |
| 638 return OK; | 623 return OK; |
| 639 } | 624 } |
| 640 | 625 |
| 641 //----------------------------------------------------------------------------- | |
| 642 | |
| 643 class NTLMAuthModule { | |
| 644 public: | |
| 645 NTLMAuthModule() {} | |
| 646 | |
| 647 ~NTLMAuthModule(); | |
| 648 | |
| 649 int Init(const string16& domain, | |
| 650 const string16& username, | |
| 651 const string16& password); | |
| 652 | |
| 653 int GetNextToken(const void* in_token, | |
| 654 uint32 in_token_len, | |
| 655 void** out_token, | |
| 656 uint32* out_token_len); | |
| 657 | |
| 658 private: | |
| 659 string16 domain_; | |
| 660 string16 username_; | |
| 661 string16 password_; | |
| 662 }; | |
| 663 | |
| 664 NTLMAuthModule::~NTLMAuthModule() { | |
| 665 ZapString(&password_); | |
| 666 } | |
| 667 | |
| 668 int NTLMAuthModule::Init(const string16& domain, | |
| 669 const string16& username, | |
| 670 const string16& password) { | |
| 671 domain_ = domain; | |
| 672 username_ = username; | |
| 673 password_ = password; | |
| 674 return OK; | |
| 675 } | |
| 676 | |
| 677 int NTLMAuthModule::GetNextToken(const void* in_token, | |
| 678 uint32 in_token_len, | |
| 679 void** out_token, | |
| 680 uint32* out_token_len) { | |
| 681 int rv; | |
| 682 | |
| 683 // If in_token is non-null, then assume it contains a type 2 message... | |
| 684 if (in_token) { | |
| 685 LogToken("in-token", in_token, in_token_len); | |
| 686 rv = GenerateType3Msg(domain_, username_, password_, in_token, | |
| 687 in_token_len, out_token, out_token_len); | |
| 688 } else { | |
| 689 rv = GenerateType1Msg(out_token, out_token_len); | |
| 690 } | |
| 691 | |
| 692 if (rv == OK) | |
| 693 LogToken("out-token", *out_token, *out_token_len); | |
| 694 | |
| 695 return rv; | |
| 696 } | |
| 697 | |
| 698 // NTLM authentication is specified in "NTLM Over HTTP Protocol Specification" | 626 // NTLM authentication is specified in "NTLM Over HTTP Protocol Specification" |
| 699 // [MS-NTHT]. | 627 // [MS-NTHT]. |
| 700 | 628 |
| 701 HttpAuthHandlerNTLM::HttpAuthHandlerNTLM() | 629 // static |
| 702 : ntlm_module_(new NTLMAuthModule) { | 630 HttpAuthHandlerNTLM::GenerateRandomProc |
| 631 HttpAuthHandlerNTLM::generate_random_proc_ = GenerateRandom; |
| 632 |
| 633 // static |
| 634 HttpAuthHandlerNTLM::HostNameProc |
| 635 HttpAuthHandlerNTLM::get_host_name_proc_ = GetMyHostName; |
| 636 |
| 637 HttpAuthHandlerNTLM::HttpAuthHandlerNTLM() { |
| 703 } | 638 } |
| 704 | 639 |
| 705 HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() { | 640 HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() { |
| 641 // Wipe our copy of the password from memory, to reduce the chance of being |
| 642 // written to the paging file on disk. |
| 643 ZapString(&password_); |
| 706 } | 644 } |
| 707 | 645 |
| 708 bool HttpAuthHandlerNTLM::NeedsIdentity() { | 646 bool HttpAuthHandlerNTLM::NeedsIdentity() { |
| 709 return !auth_data_.empty(); | 647 return !auth_data_.empty(); |
| 710 } | 648 } |
| 711 | 649 |
| 712 std::string HttpAuthHandlerNTLM::GenerateCredentials( | 650 std::string HttpAuthHandlerNTLM::GenerateCredentials( |
| 713 const std::wstring& username, | 651 const std::wstring& username, |
| 714 const std::wstring& password, | 652 const std::wstring& password, |
| 715 const HttpRequestInfo* request, | 653 const HttpRequestInfo* request, |
| 716 const ProxyInfo* proxy) { | 654 const ProxyInfo* proxy) { |
| 717 int rv; | |
| 718 // TODO(wtc): See if we can use char* instead of void* for in_buf and | 655 // TODO(wtc): See if we can use char* instead of void* for in_buf and |
| 719 // out_buf. This change will need to propagate to GetNextToken, | 656 // out_buf. This change will need to propagate to GetNextToken, |
| 720 // GenerateType1Msg, and GenerateType3Msg, and perhaps further. | 657 // GenerateType1Msg, and GenerateType3Msg, and perhaps further. |
| 721 const void* in_buf; | 658 const void* in_buf; |
| 722 void* out_buf; | 659 void* out_buf; |
| 723 uint32 in_buf_len, out_buf_len; | 660 uint32 in_buf_len, out_buf_len; |
| 724 std::string decoded_auth_data; | 661 std::string decoded_auth_data; |
| 725 | 662 |
| 726 // |username| may be in the form "DOMAIN\user". Parse it into the two | 663 // |username| may be in the form "DOMAIN\user". Parse it into the two |
| 727 // components. | 664 // components. |
| 728 std::wstring domain; | 665 std::wstring domain; |
| 729 std::wstring user; | 666 std::wstring user; |
| 730 size_t backslash_idx = username.find(L'\\'); | 667 size_t backslash_idx = username.find(L'\\'); |
| 731 if (backslash_idx == std::wstring::npos) { | 668 if (backslash_idx == std::wstring::npos) { |
| 732 user = username; | 669 user = username; |
| 733 } else { | 670 } else { |
| 734 domain = username.substr(0, backslash_idx); | 671 domain = username.substr(0, backslash_idx); |
| 735 user = username.substr(backslash_idx + 1); | 672 user = username.substr(backslash_idx + 1); |
| 736 } | 673 } |
| 737 rv = ntlm_module_->Init(WideToUTF16(domain), WideToUTF16(user), | 674 domain_ = WideToUTF16(domain); |
| 738 WideToUTF16(password)); | 675 username_ = WideToUTF16(user); |
| 676 password_ = WideToUTF16(password); |
| 739 | 677 |
| 740 // Initial challenge. | 678 // Initial challenge. |
| 741 if (auth_data_.empty()) { | 679 if (auth_data_.empty()) { |
| 742 in_buf_len = 0; | 680 in_buf_len = 0; |
| 743 in_buf = NULL; | 681 in_buf = NULL; |
| 744 } else { | 682 } else { |
| 745 // Decode |auth_data_| into the input buffer. | 683 // Decode |auth_data_| into the input buffer. |
| 746 int len = auth_data_.length(); | 684 int len = auth_data_.length(); |
| 747 | 685 |
| 748 // Strip off any padding. | 686 // Strip off any padding. |
| 749 // (See https://bugzilla.mozilla.org/show_bug.cgi?id=230351.) | 687 // (See https://bugzilla.mozilla.org/show_bug.cgi?id=230351.) |
| 750 // | 688 // |
| 751 // Our base64 decoder requires that the length be a multiple of 4. | 689 // Our base64 decoder requires that the length be a multiple of 4. |
| 752 while (len > 0 && len % 4 != 0 && auth_data_[len - 1] == '=') | 690 while (len > 0 && len % 4 != 0 && auth_data_[len - 1] == '=') |
| 753 len--; | 691 len--; |
| 754 auth_data_.erase(len); | 692 auth_data_.erase(len); |
| 755 | 693 |
| 756 if (!Base64Decode(auth_data_, &decoded_auth_data)) | 694 if (!Base64Decode(auth_data_, &decoded_auth_data)) |
| 757 return std::string(); // Improper base64 encoding | 695 return std::string(); // Improper base64 encoding |
| 758 in_buf_len = decoded_auth_data.length(); | 696 in_buf_len = decoded_auth_data.length(); |
| 759 in_buf = decoded_auth_data.data(); | 697 in_buf = decoded_auth_data.data(); |
| 760 } | 698 } |
| 761 | 699 |
| 762 rv = ntlm_module_->GetNextToken(in_buf, in_buf_len, &out_buf, &out_buf_len); | 700 int rv = GetNextToken(in_buf, in_buf_len, &out_buf, &out_buf_len); |
| 763 if (rv != OK) | 701 if (rv != OK) |
| 764 return std::string(); | 702 return std::string(); |
| 765 | 703 |
| 766 // Base64 encode data in output buffer and prepend "NTLM ". | 704 // Base64 encode data in output buffer and prepend "NTLM ". |
| 767 std::string encode_input(static_cast<char*>(out_buf), out_buf_len); | 705 std::string encode_input(static_cast<char*>(out_buf), out_buf_len); |
| 768 std::string encode_output; | 706 std::string encode_output; |
| 769 bool ok = Base64Encode(encode_input, &encode_output); | 707 bool ok = Base64Encode(encode_input, &encode_output); |
| 770 // OK, we are done with |out_buf| | 708 // OK, we are done with |out_buf| |
| 771 free(out_buf); | 709 free(out_buf); |
| 772 if (!ok) | 710 if (!ok) |
| 773 return std::string(); | 711 return std::string(); |
| 774 return std::string("NTLM ") + encode_output; | 712 return std::string("NTLM ") + encode_output; |
| 775 } | 713 } |
| 776 | 714 |
| 777 // static | 715 // static |
| 778 void HttpAuthHandlerNTLM::SetGenerateRandomProc(GenerateRandomProc proc) { | 716 HttpAuthHandlerNTLM::GenerateRandomProc |
| 717 HttpAuthHandlerNTLM::SetGenerateRandomProc( |
| 718 GenerateRandomProc proc) { |
| 719 GenerateRandomProc old_proc = generate_random_proc_; |
| 779 generate_random_proc_ = proc; | 720 generate_random_proc_ = proc; |
| 721 return old_proc; |
| 780 } | 722 } |
| 781 | 723 |
| 782 // static | 724 // static |
| 783 void HttpAuthHandlerNTLM::SetHostNameProc(HostNameProc proc) { | 725 HttpAuthHandlerNTLM::HostNameProc HttpAuthHandlerNTLM::SetHostNameProc( |
| 726 HostNameProc proc) { |
| 727 HostNameProc old_proc = get_host_name_proc_; |
| 784 get_host_name_proc_ = proc; | 728 get_host_name_proc_ = proc; |
| 729 return old_proc; |
| 785 } | 730 } |
| 786 | 731 |
| 787 // The NTLM challenge header looks like: | 732 // The NTLM challenge header looks like: |
| 788 // WWW-Authenticate: NTLM auth-data | 733 // WWW-Authenticate: NTLM auth-data |
| 789 bool HttpAuthHandlerNTLM::ParseChallenge( | 734 bool HttpAuthHandlerNTLM::ParseChallenge( |
| 790 std::string::const_iterator challenge_begin, | 735 std::string::const_iterator challenge_begin, |
| 791 std::string::const_iterator challenge_end) { | 736 std::string::const_iterator challenge_end) { |
| 792 scheme_ = "ntlm"; | 737 scheme_ = "ntlm"; |
| 793 score_ = 3; | 738 score_ = 3; |
| 794 properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED; | 739 properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED; |
| 795 auth_data_.clear(); | 740 auth_data_.clear(); |
| 796 | 741 |
| 797 // Verify the challenge's auth-scheme. | 742 // Verify the challenge's auth-scheme. |
| 798 HttpAuth::ChallengeTokenizer challenge_tok(challenge_begin, challenge_end); | 743 HttpAuth::ChallengeTokenizer challenge_tok(challenge_begin, challenge_end); |
| 799 if (!challenge_tok.valid() || | 744 if (!challenge_tok.valid() || |
| 800 !LowerCaseEqualsASCII(challenge_tok.scheme(), "ntlm")) | 745 !LowerCaseEqualsASCII(challenge_tok.scheme(), "ntlm")) |
| 801 return false; | 746 return false; |
| 802 | 747 |
| 803 // Extract the auth-data. We can't use challenge_tok.GetNext() because | 748 // Extract the auth-data. We can't use challenge_tok.GetNext() because |
| 804 // auth-data is base64-encoded and may contain '=' padding at the end, | 749 // auth-data is base64-encoded and may contain '=' padding at the end, |
| 805 // which would be mistaken for a name=value pair. | 750 // which would be mistaken for a name=value pair. |
| 806 challenge_begin += 4; // Skip over "NTLM". | 751 challenge_begin += 4; // Skip over "NTLM". |
| 807 HttpUtil::TrimLWS(&challenge_begin, &challenge_end); | 752 HttpUtil::TrimLWS(&challenge_begin, &challenge_end); |
| 808 | 753 |
| 809 auth_data_.assign(challenge_begin, challenge_end); | 754 auth_data_.assign(challenge_begin, challenge_end); |
| 810 | 755 |
| 811 return true; | 756 return true; |
| 812 } | 757 } |
| 813 | 758 |
| 759 int HttpAuthHandlerNTLM::GetNextToken(const void* in_token, |
| 760 uint32 in_token_len, |
| 761 void** out_token, |
| 762 uint32* out_token_len) { |
| 763 int rv; |
| 764 |
| 765 // If in_token is non-null, then assume it contains a type 2 message... |
| 766 if (in_token) { |
| 767 LogToken("in-token", in_token, in_token_len); |
| 768 std::string hostname = get_host_name_proc_(); |
| 769 if (hostname.empty()) |
| 770 return ERR_UNEXPECTED; |
| 771 uint8 rand_buf[8]; |
| 772 generate_random_proc_(rand_buf, 8); |
| 773 rv = GenerateType3Msg(domain_, username_, password_, hostname, rand_buf, |
| 774 in_token, in_token_len, out_token, out_token_len); |
| 775 } else { |
| 776 rv = GenerateType1Msg(out_token, out_token_len); |
| 777 } |
| 778 |
| 779 if (rv == OK) |
| 780 LogToken("out-token", *out_token, *out_token_len); |
| 781 |
| 782 return rv; |
| 783 } |
| 784 |
| 814 } // namespace net | 785 } // namespace net |
| OLD | NEW |