| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_gssapi_posix.h" | 5 #include "net/http/http_auth_gssapi_posix.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/base64.h" | 10 #include "base/base64.h" |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 // msg_ctx needs to be outside the loop because it is invoked multiple times. | 107 // msg_ctx needs to be outside the loop because it is invoked multiple times. |
| 108 OM_uint32 msg_ctx = 0; | 108 OM_uint32 msg_ctx = 0; |
| 109 std::string rv = StringPrintf("(0x%08X)", status); | 109 std::string rv = StringPrintf("(0x%08X)", status); |
| 110 | 110 |
| 111 // This loop should continue iterating until msg_ctx is 0 after the first | 111 // This loop should continue iterating until msg_ctx is 0 after the first |
| 112 // iteration. To be cautious and prevent an infinite loop, it stops after | 112 // iteration. To be cautious and prevent an infinite loop, it stops after |
| 113 // a finite number of iterations as well. As an added sanity check, no | 113 // a finite number of iterations as well. As an added sanity check, no |
| 114 // individual message may exceed |kMaxMsgLength|, and the final result | 114 // individual message may exceed |kMaxMsgLength|, and the final result |
| 115 // will not exceed |kMaxMsgLength|*2-1. | 115 // will not exceed |kMaxMsgLength|*2-1. |
| 116 for (int i = 0; i < kMaxDisplayIterations && rv.size() < kMaxMsgLength; | 116 for (int i = 0; i < kMaxDisplayIterations && rv.size() < kMaxMsgLength; |
| 117 ++i) { | 117 ++i) { |
| 118 OM_uint32 min_stat; | 118 OM_uint32 min_stat; |
| 119 gss_buffer_desc_struct msg = GSS_C_EMPTY_BUFFER; | 119 gss_buffer_desc_struct msg = GSS_C_EMPTY_BUFFER; |
| 120 OM_uint32 maj_stat = | 120 OM_uint32 maj_stat = |
| 121 gssapi_lib->display_status(&min_stat, status, status_code_type, | 121 gssapi_lib->display_status(&min_stat, status, status_code_type, |
| 122 GSS_C_NULL_OID, &msg_ctx, &msg); | 122 GSS_C_NULL_OID, &msg_ctx, &msg); |
| 123 if (maj_stat == GSS_S_COMPLETE) { | 123 if (maj_stat == GSS_S_COMPLETE) { |
| 124 int msg_len = (msg.length > kMaxMsgLength) ? | 124 int msg_len = (msg.length > kMaxMsgLength) ? |
| 125 static_cast<int>(kMaxMsgLength) : | 125 static_cast<int>(kMaxMsgLength) : |
| 126 static_cast<int>(msg.length); | 126 static_cast<int>(msg.length); |
| 127 if (msg_len > 0 && msg.value != NULL) { | 127 if (msg_len > 0 && msg.value != NULL) { |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 // Only return this library if we can bind the functions we need. | 475 // Only return this library if we can bind the functions we need. |
| 476 if (BindMethods(lib)) | 476 if (BindMethods(lib)) |
| 477 return lib; | 477 return lib; |
| 478 base::UnloadNativeLibrary(lib); | 478 base::UnloadNativeLibrary(lib); |
| 479 } | 479 } |
| 480 } | 480 } |
| 481 LOG(WARNING) << "Unable to find a compatible GSSAPI library"; | 481 LOG(WARNING) << "Unable to find a compatible GSSAPI library"; |
| 482 return NULL; | 482 return NULL; |
| 483 } | 483 } |
| 484 | 484 |
| 485 #define BIND(lib, x) \ | 485 #define BIND(lib, x) \ |
| 486 gss_##x##_type x = reinterpret_cast<gss_##x##_type>( \ | 486 gss_##x##_type x = reinterpret_cast<gss_##x##_type>( \ |
| 487 base::GetFunctionPointerFromNativeLibrary(lib, "gss_" #x)); \ | 487 base::GetFunctionPointerFromNativeLibrary(lib, "gss_" #x)); \ |
| 488 if (x == NULL) { \ | 488 if (x == NULL) { \ |
| 489 LOG(WARNING) << "Unable to bind function \"" << "gss_" #x << "\""; \ | 489 LOG(WARNING) << "Unable to bind function \"" << "gss_" #x << "\""; \ |
| 490 return false; \ | 490 return false; \ |
| 491 } | 491 } |
| 492 | 492 |
| 493 bool GSSAPISharedLibrary::BindMethods(base::NativeLibrary lib) { | 493 bool GSSAPISharedLibrary::BindMethods(base::NativeLibrary lib) { |
| 494 DCHECK(lib != NULL); | 494 DCHECK(lib != NULL); |
| 495 | 495 |
| 496 BIND(lib, import_name) | 496 BIND(lib, import_name); |
| 497 BIND(lib, release_name) | 497 BIND(lib, release_name); |
| 498 BIND(lib, release_buffer) | 498 BIND(lib, release_buffer); |
| 499 BIND(lib, display_name) | 499 BIND(lib, display_name); |
| 500 BIND(lib, display_status) | 500 BIND(lib, display_status); |
| 501 BIND(lib, init_sec_context) | 501 BIND(lib, init_sec_context); |
| 502 BIND(lib, wrap_size_limit) | 502 BIND(lib, wrap_size_limit); |
| 503 BIND(lib, delete_sec_context) | 503 BIND(lib, delete_sec_context); |
| 504 BIND(lib, inquire_context) | 504 BIND(lib, inquire_context); |
| 505 | 505 |
| 506 import_name_ = import_name; | 506 import_name_ = import_name; |
| 507 release_name_ = release_name; | 507 release_name_ = release_name; |
| 508 release_buffer_ = release_buffer; | 508 release_buffer_ = release_buffer; |
| 509 display_name_ = display_name; | 509 display_name_ = display_name; |
| 510 display_status_ = display_status; | 510 display_status_ = display_status; |
| 511 init_sec_context_ = init_sec_context; | 511 init_sec_context_ = init_sec_context; |
| 512 wrap_size_limit_ = wrap_size_limit; | 512 wrap_size_limit_ = wrap_size_limit; |
| 513 delete_sec_context_ = delete_sec_context; | 513 delete_sec_context_ = delete_sec_context; |
| 514 inquire_context_ = inquire_context; | 514 inquire_context_ = inquire_context; |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 const gss_ctx_id_t context_handle, | 631 const gss_ctx_id_t context_handle, |
| 632 gss_name_t* src_name, | 632 gss_name_t* src_name, |
| 633 gss_name_t* targ_name, | 633 gss_name_t* targ_name, |
| 634 OM_uint32* lifetime_rec, | 634 OM_uint32* lifetime_rec, |
| 635 gss_OID* mech_type, | 635 gss_OID* mech_type, |
| 636 OM_uint32* ctx_flags, | 636 OM_uint32* ctx_flags, |
| 637 int* locally_initiated, | 637 int* locally_initiated, |
| 638 int* open) { | 638 int* open) { |
| 639 DCHECK(initialized_); | 639 DCHECK(initialized_); |
| 640 return inquire_context_(minor_status, | 640 return inquire_context_(minor_status, |
| 641 context_handle, | 641 context_handle, |
| 642 src_name, | 642 src_name, |
| 643 targ_name, | 643 targ_name, |
| 644 lifetime_rec, | 644 lifetime_rec, |
| 645 mech_type, | 645 mech_type, |
| 646 ctx_flags, | 646 ctx_flags, |
| 647 locally_initiated, | 647 locally_initiated, |
| 648 open); | 648 open); |
| 649 } | 649 } |
| 650 GSSAPILibrary* GSSAPILibrary::GetDefault() { | 650 GSSAPILibrary* GSSAPILibrary::GetDefault() { |
| 651 return Singleton<GSSAPISharedLibrary>::get(); | 651 return Singleton<GSSAPISharedLibrary>::get(); |
| 652 } | 652 } |
| 653 | 653 |
| 654 ScopedSecurityContext::ScopedSecurityContext(GSSAPILibrary* gssapi_lib) | 654 ScopedSecurityContext::ScopedSecurityContext(GSSAPILibrary* gssapi_lib) |
| 655 : security_context_(GSS_C_NO_CONTEXT), | 655 : security_context_(GSS_C_NO_CONTEXT), |
| 656 gssapi_lib_(gssapi_lib) { | 656 gssapi_lib_(gssapi_lib) { |
| 657 DCHECK(gssapi_lib_); | 657 DCHECK(gssapi_lib_); |
| 658 } | 658 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 688 bool HttpAuthGSSAPI::Init() { | 688 bool HttpAuthGSSAPI::Init() { |
| 689 if (!library_) | 689 if (!library_) |
| 690 return false; | 690 return false; |
| 691 return library_->Init(); | 691 return library_->Init(); |
| 692 } | 692 } |
| 693 | 693 |
| 694 bool HttpAuthGSSAPI::NeedsIdentity() const { | 694 bool HttpAuthGSSAPI::NeedsIdentity() const { |
| 695 return decoded_server_auth_token_.empty(); | 695 return decoded_server_auth_token_.empty(); |
| 696 } | 696 } |
| 697 | 697 |
| 698 bool HttpAuthGSSAPI::IsFinalRound() const { | |
| 699 return !NeedsIdentity(); | |
| 700 } | |
| 701 | |
| 702 void HttpAuthGSSAPI::Delegate() { | 698 void HttpAuthGSSAPI::Delegate() { |
| 703 can_delegate_ = true; | 699 can_delegate_ = true; |
| 704 } | 700 } |
| 705 | 701 |
| 706 bool HttpAuthGSSAPI::ParseChallenge(HttpAuth::ChallengeTokenizer* tok) { | 702 HttpAuth::AuthorizationResult HttpAuthGSSAPI::ParseChallenge( |
| 703 HttpAuth::ChallengeTokenizer* tok) { |
| 707 // Verify the challenge's auth-scheme. | 704 // Verify the challenge's auth-scheme. |
| 708 if (!tok->valid() || | 705 if (!tok->valid() || |
| 709 !LowerCaseEqualsASCII(tok->scheme(), StringToLowerASCII(scheme_).c_str())) | 706 !LowerCaseEqualsASCII(tok->scheme(), StringToLowerASCII(scheme_).c_str())) |
| 710 return false; | 707 return HttpAuth::AUTHORIZATION_RESULT_INVALID; |
| 711 | 708 |
| 712 tok->set_expect_base64_token(true); | 709 tok->set_expect_base64_token(true); |
| 713 if (!tok->GetNext()) { | 710 if (!tok->GetNext()) { |
| 714 decoded_server_auth_token_.clear(); | 711 // If a context has already been established, an empty Negotiate challenge |
| 715 return true; | 712 // should be treated as a rejection of the current attempt. |
| 713 if (scoped_sec_context_.get() != GSS_C_NO_CONTEXT) |
| 714 return HttpAuth::AUTHORIZATION_RESULT_REJECT; |
| 715 DCHECK(decoded_server_auth_token_.empty()); |
| 716 return HttpAuth::AUTHORIZATION_RESULT_ACCEPT; |
| 717 } else { |
| 718 // If a context has not already been established, additional tokens should |
| 719 // not be present in the auth challenge. |
| 720 if (scoped_sec_context_.get() == GSS_C_NO_CONTEXT) |
| 721 return HttpAuth::AUTHORIZATION_RESULT_INVALID; |
| 716 } | 722 } |
| 717 | 723 |
| 724 // Make sure the additional token is base64 encoded. |
| 718 std::string encoded_auth_token = tok->value(); | 725 std::string encoded_auth_token = tok->value(); |
| 719 std::string decoded_auth_token; | 726 std::string decoded_auth_token; |
| 720 bool base64_rv = base::Base64Decode(encoded_auth_token, &decoded_auth_token); | 727 bool base64_rv = base::Base64Decode(encoded_auth_token, &decoded_auth_token); |
| 721 if (!base64_rv) { | 728 if (!base64_rv) |
| 722 LOG(ERROR) << "Base64 decoding of auth token failed."; | 729 return HttpAuth::AUTHORIZATION_RESULT_INVALID; |
| 723 return false; | |
| 724 } | |
| 725 decoded_server_auth_token_ = decoded_auth_token; | 730 decoded_server_auth_token_ = decoded_auth_token; |
| 726 return true; | 731 return HttpAuth::AUTHORIZATION_RESULT_ACCEPT; |
| 727 } | 732 } |
| 728 | 733 |
| 729 int HttpAuthGSSAPI::GenerateAuthToken(const string16* username, | 734 int HttpAuthGSSAPI::GenerateAuthToken(const string16* username, |
| 730 const string16* password, | 735 const string16* password, |
| 731 const std::wstring& spn, | 736 const std::wstring& spn, |
| 732 std::string* auth_token) { | 737 std::string* auth_token) { |
| 733 DCHECK(auth_token); | 738 DCHECK(auth_token); |
| 734 DCHECK(username == NULL && password == NULL); | 739 DCHECK(username == NULL && password == NULL); |
| 735 | 740 |
| 736 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; | 741 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; |
| 737 input_token.length = decoded_server_auth_token_.length(); | 742 input_token.length = decoded_server_auth_token_.length(); |
| 738 input_token.value = | 743 input_token.value = (input_token.length > 0) ? |
| 739 (input_token.length > 0) ? | 744 const_cast<char*>(decoded_server_auth_token_.data()) : |
| 740 const_cast<char*>(decoded_server_auth_token_.data()) : | 745 NULL; |
| 741 NULL; | |
| 742 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; | 746 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; |
| 743 ScopedBuffer scoped_output_token(&output_token, library_); | 747 ScopedBuffer scoped_output_token(&output_token, library_); |
| 744 int rv = GetNextSecurityToken(spn, &input_token, &output_token); | 748 int rv = GetNextSecurityToken(spn, &input_token, &output_token); |
| 745 if (rv != OK) | 749 if (rv != OK) |
| 746 return rv; | 750 return rv; |
| 747 | 751 |
| 748 // Base64 encode data in output buffer and prepend the scheme. | 752 // Base64 encode data in output buffer and prepend the scheme. |
| 749 std::string encode_input(static_cast<char*>(output_token.value), | 753 std::string encode_input(static_cast<char*>(output_token.value), |
| 750 output_token.length); | 754 output_token.length); |
| 751 std::string encode_output; | 755 std::string encode_output; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 907 minor_status) | 911 minor_status) |
| 908 << std::endl | 912 << std::endl |
| 909 << DescribeContext(library_, scoped_sec_context_.get()); | 913 << DescribeContext(library_, scoped_sec_context_.get()); |
| 910 return rv; | 914 return rv; |
| 911 } | 915 } |
| 912 | 916 |
| 913 return OK; | 917 return OK; |
| 914 } | 918 } |
| 915 | 919 |
| 916 } // namespace net | 920 } // namespace net |
| OLD | NEW |