diff options
author | asanka <asanka@chromium.org> | 2016-03-23 09:20:49 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-23 16:22:04 +0000 |
commit | 5ffd5d79244e6c9928ed465fcfed8a136d04140a (patch) | |
tree | 61b94a189d803d0d262244654252bf8fec7fb691 /net | |
parent | da4111853b1da632bf7566e3505f40ef9cca1a66 (diff) | |
download | chromium_src-5ffd5d79244e6c9928ed465fcfed8a136d04140a.zip chromium_src-5ffd5d79244e6c9928ed465fcfed8a136d04140a.tar.gz chromium_src-5ffd5d79244e6c9928ed465fcfed8a136d04140a.tar.bz2 |
[net/http auth] Support channel bindings for HTTP authentication.
Start using tls-server-end-point channel bindings for HTTP
authentication if a certificate is available. The current implementation
should work on Windows and Posix. Currently only SHA-256, SHA-384, and
SHA-512 are supported for generating channel bindings.
BUG=270219
R=rsleevi@chromium.org,davidben@chromium.org
Review URL: https://codereview.chromium.org/1408433006
Cr-Commit-Position: refs/heads/master@{#382858}
Diffstat (limited to 'net')
47 files changed, 957 insertions, 274 deletions
diff --git a/net/android/http_auth_negotiate_android.cc b/net/android/http_auth_negotiate_android.cc index 907cff3..764eb4c 100644 --- a/net/android/http_auth_negotiate_android.cc +++ b/net/android/http_auth_negotiate_android.cc @@ -101,6 +101,7 @@ HttpAuth::AuthorizationResult HttpAuthNegotiateAndroid::ParseChallenge( int HttpAuthNegotiateAndroid::GenerateAuthToken( const AuthCredentials* credentials, const std::string& spn, + const std::string& channel_bindings, std::string* auth_token, const net::CompletionCallback& callback) { if (prefs_->AuthAndroidNegotiateAccountType().empty()) { diff --git a/net/android/http_auth_negotiate_android.h b/net/android/http_auth_negotiate_android.h index 1b33726..af8163c 100644 --- a/net/android/http_auth_negotiate_android.h +++ b/net/android/http_auth_negotiate_android.h @@ -107,6 +107,7 @@ class NET_EXPORT_PRIVATE HttpAuthNegotiateAndroid { // credentials are used instead. int GenerateAuthToken(const AuthCredentials* credentials, const std::string& spn, + const std::string& channel_bindings, std::string* auth_token, const net::CompletionCallback& callback); diff --git a/net/android/http_auth_negotiate_android_unittest.cc b/net/android/http_auth_negotiate_android_unittest.cc index 8e3de79..b44547d 100644 --- a/net/android/http_auth_negotiate_android_unittest.cc +++ b/net/android/http_auth_negotiate_android_unittest.cc @@ -31,8 +31,9 @@ TEST(HttpAuthNegotiateAndroidTest, GenerateAuthToken) { EXPECT_TRUE(auth.Init()); TestCompletionCallback callback; - EXPECT_EQ(OK, callback.GetResult(auth.GenerateAuthToken( - nullptr, "Dummy", &auth_token, callback.callback()))); + EXPECT_EQ(OK, callback.GetResult( + auth.GenerateAuthToken(nullptr, "Dummy", std::string(), + &auth_token, callback.callback()))); EXPECT_EQ("Negotiate DummyToken", auth_token); diff --git a/net/cert/x509_util.cc b/net/cert/x509_util.cc index bbdc194..b0e343ac 100644 --- a/net/cert/x509_util.cc +++ b/net/cert/x509_util.cc @@ -8,6 +8,9 @@ #include "base/time/time.h" #include "crypto/ec_private_key.h" #include "crypto/rsa_private_key.h" +#include "net/base/hash_value.h" +#include "net/cert/internal/parse_certificate.h" +#include "net/cert/internal/signature_algorithm.h" #include "net/cert/x509_certificate.h" namespace net { diff --git a/net/cert/x509_util.h b/net/cert/x509_util.h index fb8c20f..bd25456 100644 --- a/net/cert/x509_util.h +++ b/net/cert/x509_util.h @@ -31,6 +31,12 @@ enum DigestAlgorithm { DIGEST_SHA256 }; +// Generate a 'tls-server-end-point' channel binding based on the specified +// certificate. Channel bindings are based on RFC 5929. +NET_EXPORT_PRIVATE bool GetTLSServerEndPointChannelBinding( + const X509Certificate& certificate, + std::string* token); + // Creates a public-private keypair and a self-signed certificate. // Subject, serial number and validity period are given as parameters. // The certificate is signed by the private key in |key|. The key length and diff --git a/net/cert/x509_util_nss.cc b/net/cert/x509_util_nss.cc index 2dbff2c..db6a97a 100644 --- a/net/cert/x509_util_nss.cc +++ b/net/cert/x509_util_nss.cc @@ -180,6 +180,12 @@ bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, return true; } +bool GetTLSServerEndPointChannelBinding(const X509Certificate& certificate, + std::string* token) { + NOTIMPLEMENTED(); + return false; +} + } // namespace x509_util } // namespace net diff --git a/net/cert/x509_util_openssl.cc b/net/cert/x509_util_openssl.cc index 5b6779a..2e8ef2e 100644 --- a/net/cert/x509_util_openssl.cc +++ b/net/cert/x509_util_openssl.cc @@ -6,6 +6,7 @@ #include <limits.h> #include <openssl/asn1.h> +#include <openssl/digest.h> #include <openssl/mem.h> #include <algorithm> @@ -19,7 +20,10 @@ #include "crypto/openssl_util.h" #include "crypto/rsa_private_key.h" #include "crypto/scoped_openssl_types.h" +#include "net/cert/internal/parse_certificate.h" +#include "net/cert/internal/signature_algorithm.h" #include "net/cert/x509_cert_types.h" +#include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" #include "net/ssl/scoped_openssl_types.h" @@ -303,6 +307,57 @@ bool GetDER(X509* x509, base::StringPiece* der_cache) { return true; } +bool GetTLSServerEndPointChannelBinding(const X509Certificate& certificate, + std::string* token) { + static const char kChannelBindingPrefix[] = "tls-server-end-point:"; + + std::string der_encoded_certificate; + if (!X509Certificate::GetDEREncoded(certificate.os_cert_handle(), + &der_encoded_certificate)) + return false; + + ParsedCertificate parsed_certificate; + if (!ParseCertificate(der::Input(base::StringPiece(der_encoded_certificate)), + &parsed_certificate)) + return false; + + scoped_ptr<SignatureAlgorithm> signature_algorithm = + SignatureAlgorithm::CreateFromDer( + parsed_certificate.signature_algorithm_tlv); + if (!signature_algorithm) + return false; + + const EVP_MD* digest_evp_md = nullptr; + switch (signature_algorithm->digest()) { + case net::DigestAlgorithm::Sha1: + case net::DigestAlgorithm::Sha256: + digest_evp_md = EVP_sha256(); + break; + + case net::DigestAlgorithm::Sha384: + digest_evp_md = EVP_sha384(); + break; + + case net::DigestAlgorithm::Sha512: + digest_evp_md = EVP_sha512(); + break; + } + if (!digest_evp_md) + return false; + + std::vector<uint8_t> digest(EVP_MAX_MD_SIZE); + unsigned int out_size = digest.size(); + if (!EVP_Digest(der_encoded_certificate.data(), + der_encoded_certificate.size(), digest.data(), &out_size, + digest_evp_md, nullptr)) + return false; + + digest.resize(out_size); + token->assign(kChannelBindingPrefix); + token->append(digest.begin(), digest.end()); + return true; +} + } // namespace x509_util } // namespace net diff --git a/net/cert/x509_util_unittest.cc b/net/cert/x509_util_unittest.cc index abce23a..6fabe00 100644 --- a/net/cert/x509_util_unittest.cc +++ b/net/cert/x509_util_unittest.cc @@ -188,6 +188,518 @@ TEST(X509UtilTest, CreateSelfSigned) { EXPECT_FALSE(cert->HasExpired()); } +#if defined(USE_OPENSSL) +// This is a test case based on +// http://blogs.msdn.com/b/openspecification/archive/2013/03/26/ntlm-and-channel-binding-hash-aka-exteneded-protection-for-authentication.aspx +// There doesn't seem to be too many public test vectors for channel bindings. +TEST(X509UtilTest, CreateChannelBindings_SHA1) { + // Certificate: + // Data: + // Version: 3 (0x2) + // Serial Number: + // (Negative)34:96:86:32:ae:8a:3a:48:b4:98:cf:7c:93:87:bb:d9 + // Signature Algorithm: sha1WithRSA + // ... + const uint8_t kCertificateDataDER[] = { + 0x30, 0x82, 0x02, 0x09, 0x30, 0x82, 0x01, 0x76, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x10, 0xcb, 0x69, 0x79, 0xcd, 0x51, 0x75, 0xc5, 0xb7, 0x4b, + 0x67, 0x30, 0x83, 0x6c, 0x78, 0x44, 0x27, 0x30, 0x09, 0x06, 0x05, 0x2b, + 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0b, 0x44, 0x43, 0x2d, 0x57, 0x53, + 0x32, 0x30, 0x30, 0x38, 0x52, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, + 0x31, 0x31, 0x31, 0x37, 0x30, 0x30, 0x35, 0x39, 0x32, 0x31, 0x5a, 0x17, + 0x0d, 0x33, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, + 0x39, 0x5a, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x0b, 0x44, 0x43, 0x2d, 0x57, 0x53, 0x32, 0x30, 0x30, 0x38, + 0x52, 0x32, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0x9b, 0x00, 0xf8, 0x1a, 0x2d, + 0x37, 0xc6, 0x8d, 0xa1, 0x39, 0x91, 0x46, 0xf3, 0x6a, 0x1b, 0xf9, 0x60, + 0x6c, 0xb3, 0x6c, 0xa0, 0xac, 0xed, 0x85, 0xe0, 0x3f, 0xdc, 0x92, 0x86, + 0x36, 0xbd, 0x64, 0xbf, 0x36, 0x51, 0xdb, 0x57, 0x3a, 0x8a, 0x82, 0x6b, + 0xd8, 0x94, 0x17, 0x7b, 0xd3, 0x91, 0x11, 0x98, 0xef, 0x19, 0x06, 0x52, + 0x30, 0x03, 0x73, 0x67, 0xc8, 0xed, 0x8e, 0xfa, 0x0b, 0x3d, 0x4c, 0xc9, + 0x10, 0x63, 0x9f, 0xcf, 0xb4, 0xcf, 0x39, 0xd8, 0xfe, 0x99, 0xeb, 0x5b, + 0x11, 0xf2, 0xfc, 0xfa, 0x86, 0x24, 0xd9, 0xff, 0xd9, 0x19, 0xf5, 0x69, + 0xb4, 0xdf, 0x5a, 0x5a, 0xc4, 0x94, 0xb4, 0xb0, 0x07, 0x25, 0x97, 0x13, + 0xad, 0x7e, 0x38, 0x14, 0xfb, 0xd6, 0x33, 0x65, 0x6f, 0xe6, 0xf7, 0x48, + 0x4b, 0x2d, 0xb3, 0x51, 0x2e, 0x6d, 0xc7, 0xea, 0x11, 0x76, 0x9a, 0x2b, + 0xf0, 0x00, 0x4d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x60, 0x30, 0x5e, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, + 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x47, 0x06, + 0x03, 0x55, 0x1d, 0x01, 0x04, 0x40, 0x30, 0x3e, 0x80, 0x10, 0xeb, 0x65, + 0x26, 0x03, 0x95, 0x4b, 0xd6, 0xc0, 0x54, 0x75, 0x78, 0x7c, 0xb6, 0x2a, + 0xa1, 0xbb, 0xa1, 0x18, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x0b, 0x44, 0x43, 0x2d, 0x57, 0x53, 0x32, 0x30, + 0x30, 0x38, 0x52, 0x32, 0x82, 0x10, 0xcb, 0x69, 0x79, 0xcd, 0x51, 0x75, + 0xc5, 0xb7, 0x4b, 0x67, 0x30, 0x83, 0x6c, 0x78, 0x44, 0x27, 0x30, 0x09, + 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x03, 0x81, 0x81, + 0x00, 0x7b, 0xfa, 0xfe, 0xee, 0x74, 0x05, 0xac, 0xbb, 0x79, 0xe9, 0xda, + 0xca, 0x00, 0x44, 0x96, 0x94, 0x71, 0x92, 0xb1, 0xdb, 0xc9, 0x9b, 0x71, + 0x29, 0xc0, 0xe4, 0x28, 0x5e, 0x6a, 0x50, 0x99, 0xcd, 0xa8, 0x17, 0xe4, + 0x56, 0xb9, 0xef, 0x7f, 0x02, 0x7d, 0x96, 0xa3, 0x48, 0x14, 0x72, 0x75, + 0x2f, 0xb0, 0xb5, 0x87, 0xee, 0x55, 0xe9, 0x6a, 0x6d, 0x28, 0x3c, 0xc1, + 0xfd, 0x00, 0xe4, 0x76, 0xe3, 0x80, 0x88, 0x78, 0x26, 0x0d, 0x6c, 0x8c, + 0xb8, 0x64, 0x61, 0x63, 0xb7, 0x13, 0x3a, 0xab, 0xc7, 0xdd, 0x1d, 0x0a, + 0xd7, 0x15, 0x45, 0xa1, 0xd6, 0xd9, 0x34, 0xc7, 0x21, 0x48, 0xfb, 0x43, + 0x87, 0x38, 0xda, 0x1f, 0x50, 0x47, 0xb1, 0xa5, 0x5c, 0x47, 0xed, 0x04, + 0x44, 0x97, 0xd3, 0xac, 0x74, 0x2d, 0xeb, 0x09, 0x77, 0x59, 0xbf, 0xa3, + 0x54, 0x5b, 0xde, 0x42, 0xd5, 0x23, 0x5a, 0x71, 0x9f}; + + const unsigned char kExpectedServerEndPointToken[] = { + 0x74, 0x6c, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2d, + 0x65, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x3a, 0xea, + 0x05, 0xfe, 0xfe, 0xcc, 0x6b, 0x0b, 0xd5, 0x71, 0xdb, 0xbc, 0x5b, + 0xaa, 0x3e, 0xd4, 0x53, 0x86, 0xd0, 0x44, 0x68, 0x35, 0xf7, 0xb7, + 0x4c, 0x85, 0x62, 0x1b, 0x99, 0x83, 0x47, 0x5f, 0x95, + }; + + scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes( + reinterpret_cast<const char*>(kCertificateDataDER), + sizeof(kCertificateDataDER)); + + std::string channel_bindings; + ASSERT_TRUE( + x509_util::GetTLSServerEndPointChannelBinding(*cert, &channel_bindings)); + + std::string expected_channel_bindings( + std::begin(kExpectedServerEndPointToken), + std::end(kExpectedServerEndPointToken)); + EXPECT_EQ(expected_channel_bindings, channel_bindings); +} + +TEST(X509UtilTest, CreateChannelBindings_SHA256) { + // Certificate: + // Data: + // Version: 3 (0x2) + // Serial Number: 14673274151129443507 (0xcba1f1191dfdecb3) + // Signature Algorithm: sha256WithRSAEncryption + // ... + const uint8_t kCertificateDataDER[] = { + 0x30, 0x82, 0x03, 0x8f, 0x30, 0x82, 0x02, 0x77, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x09, 0x00, 0xcb, 0xa1, 0xf1, 0x19, 0x1d, 0xfd, 0xec, 0xb3, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x0b, 0x05, 0x00, 0x30, 0x5e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x0b, 0x4d, 0x6d, 0x6d, 0x6b, 0x61, 0x79, 0x20, 0x49, 0x6e, 0x63, + 0x2e, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, + 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, + 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, + 0x37, 0x31, 0x39, 0x33, 0x39, 0x34, 0x34, 0x5a, 0x17, 0x0d, 0x31, 0x36, + 0x30, 0x34, 0x31, 0x36, 0x31, 0x39, 0x33, 0x39, 0x34, 0x34, 0x5a, 0x30, + 0x5e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, + 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0b, 0x4d, 0x6d, + 0x6d, 0x6b, 0x61, 0x79, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, + 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, + 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc6, 0x31, 0xfe, 0x13, + 0x0a, 0xb2, 0x87, 0xc0, 0xb9, 0xa4, 0xb9, 0x86, 0x98, 0x92, 0xc1, 0x48, + 0x41, 0x89, 0xd9, 0xe6, 0xe9, 0x36, 0x1a, 0xd6, 0x1c, 0xcb, 0x86, 0x3a, + 0xec, 0x34, 0x3a, 0xbf, 0x2a, 0xe7, 0x91, 0x33, 0xf4, 0x3e, 0xa4, 0x1b, + 0x9a, 0xc3, 0xa4, 0x66, 0xa0, 0x6d, 0xbf, 0x75, 0x44, 0x1a, 0x79, 0xda, + 0x23, 0x06, 0x5c, 0x07, 0x5c, 0x52, 0x84, 0x46, 0x40, 0xcf, 0x26, 0xa1, + 0x65, 0x65, 0x4e, 0x36, 0x1a, 0xd2, 0xc9, 0x40, 0x28, 0x1e, 0x6f, 0x4f, + 0x7e, 0xb7, 0x10, 0xcd, 0x55, 0x6c, 0xca, 0xf1, 0xfa, 0x66, 0xfb, 0x3e, + 0xb0, 0xf4, 0xc1, 0x92, 0xec, 0xec, 0x0c, 0x1c, 0x79, 0x23, 0x5d, 0xf6, + 0xc0, 0xed, 0xb7, 0x39, 0xa7, 0x59, 0x98, 0xa7, 0x9d, 0x9e, 0x3b, 0xe1, + 0x77, 0x8b, 0x2d, 0x2b, 0x02, 0x5f, 0x30, 0x46, 0xa9, 0x78, 0x47, 0x6f, + 0x05, 0x7d, 0xbc, 0x84, 0x37, 0x09, 0x40, 0x20, 0xba, 0x16, 0x96, 0x4c, + 0xfd, 0xea, 0x83, 0x3e, 0x50, 0xda, 0x24, 0xf4, 0x61, 0x52, 0xfe, 0x9b, + 0xd5, 0x71, 0x37, 0x18, 0x11, 0xe0, 0x7c, 0xbe, 0x98, 0x95, 0x6c, 0x61, + 0xab, 0x9b, 0xdc, 0x5c, 0x59, 0x7d, 0x85, 0x0c, 0xc5, 0x32, 0x07, 0x65, + 0x1e, 0x6a, 0x15, 0xe6, 0xbd, 0xc6, 0xbd, 0xd5, 0x91, 0xea, 0x9d, 0x2f, + 0x0f, 0xdf, 0xef, 0xff, 0x1e, 0x2d, 0x50, 0x44, 0xca, 0x38, 0x27, 0xe3, + 0x20, 0x79, 0x44, 0x47, 0x7a, 0xe3, 0xea, 0x7a, 0x70, 0x41, 0x26, 0x87, + 0xe0, 0x1a, 0x49, 0x1d, 0x62, 0x34, 0xe5, 0xde, 0xc3, 0xb3, 0x12, 0xb8, + 0xa2, 0xf9, 0xad, 0x1b, 0x6a, 0x0f, 0x04, 0xa8, 0xfb, 0xca, 0xe4, 0x01, + 0x6d, 0x77, 0x1f, 0x72, 0xff, 0x58, 0x49, 0x05, 0x1c, 0x1a, 0xb7, 0x76, + 0x29, 0x77, 0x93, 0xcc, 0x09, 0xe8, 0xb7, 0x03, 0x2f, 0x1b, 0xe2, 0xcd, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb7, 0x64, 0x60, 0xe7, + 0x6e, 0xb6, 0xaa, 0x25, 0x46, 0xe2, 0x8e, 0x98, 0xac, 0x81, 0xb0, 0xe7, + 0x10, 0x14, 0x85, 0x6d, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, + 0x18, 0x30, 0x16, 0x80, 0x14, 0xb7, 0x64, 0x60, 0xe7, 0x6e, 0xb6, 0xaa, + 0x25, 0x46, 0xe2, 0x8e, 0x98, 0xac, 0x81, 0xb0, 0xe7, 0x10, 0x14, 0x85, + 0x6d, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, + 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x44, + 0xc4, 0x46, 0x89, 0x69, 0x21, 0xd0, 0x81, 0x30, 0xe3, 0x38, 0xb8, 0x80, + 0xa5, 0x23, 0xd4, 0xfc, 0xe5, 0x12, 0x0f, 0xab, 0x01, 0x44, 0x67, 0xe4, + 0x59, 0x86, 0xd0, 0xa1, 0x8c, 0x2b, 0x36, 0xf0, 0x63, 0x51, 0xbe, 0x24, + 0xfa, 0xf3, 0x1d, 0xc9, 0xfd, 0x40, 0x99, 0x48, 0xea, 0x95, 0x6e, 0xab, + 0xcf, 0xeb, 0x2b, 0x2d, 0x4e, 0xd2, 0xdf, 0xb2, 0xb9, 0x18, 0x27, 0xe3, + 0xc9, 0x17, 0xde, 0x25, 0x6c, 0xcc, 0x80, 0x5a, 0xd5, 0x3b, 0xc5, 0xc8, + 0x3a, 0xc6, 0xcb, 0xa0, 0x33, 0xd3, 0x80, 0x20, 0x4e, 0x3f, 0x61, 0x67, + 0x16, 0x0e, 0xbc, 0xf3, 0x25, 0xe9, 0x62, 0xfa, 0x7f, 0x0e, 0x75, 0x11, + 0xcb, 0x68, 0x24, 0x34, 0x96, 0x1d, 0xb2, 0x88, 0xb7, 0xeb, 0x5e, 0x9c, + 0xc7, 0xa0, 0x3b, 0xcf, 0x4e, 0x3c, 0x7c, 0x6c, 0x29, 0x1b, 0xa5, 0x74, + 0x4d, 0x90, 0xe1, 0xd9, 0x6a, 0x6c, 0x54, 0x6b, 0xce, 0x3d, 0x70, 0x99, + 0xf0, 0x11, 0xc3, 0xda, 0xce, 0xe9, 0xba, 0xc4, 0x91, 0x97, 0xe7, 0x44, + 0x09, 0xa4, 0x39, 0x36, 0xb5, 0xff, 0x3a, 0xce, 0x5d, 0xf1, 0x0b, 0x03, + 0xab, 0xea, 0x0c, 0xe6, 0xbd, 0xd4, 0x43, 0xed, 0x8d, 0x9c, 0xcd, 0x8e, + 0x14, 0xf9, 0xa7, 0xc7, 0xdc, 0xe0, 0xd8, 0xe7, 0x37, 0xf5, 0x48, 0xe8, + 0x84, 0x4c, 0xcd, 0x70, 0x1b, 0xe5, 0x71, 0xa7, 0x4d, 0xc3, 0x03, 0x5e, + 0x50, 0x8a, 0xc4, 0x7c, 0x9c, 0xa4, 0x6f, 0x91, 0xfa, 0x9f, 0xdc, 0xef, + 0x2b, 0x42, 0xe7, 0xd0, 0x0d, 0x60, 0x72, 0x71, 0xe7, 0x13, 0xff, 0x43, + 0xcb, 0x64, 0x33, 0x37, 0x2e, 0xe9, 0x09, 0xeb, 0x7e, 0x8f, 0x15, 0x99, + 0xc9, 0x0d, 0xb0, 0xcb, 0xf0, 0x1f, 0x02, 0xf7, 0xb7, 0x3a, 0xa0, 0x6b, + 0x57, 0xb3, 0x33, 0x14, 0xdb, 0x06, 0x7f, 0x98, 0x6f, 0xc4, 0x32, 0xd5, + 0x14, 0x83, 0x7a}; + + const unsigned char kExpectedServerEndPointToken[] = { + 0x74, 0x6c, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2d, + 0x65, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x3a, 0x96, + 0x4c, 0xd0, 0x44, 0x53, 0x81, 0x0b, 0x35, 0x01, 0x05, 0x54, 0x02, + 0x15, 0x79, 0xac, 0x74, 0x3c, 0xa4, 0x91, 0xa2, 0xb7, 0x60, 0xbe, + 0x75, 0x57, 0x0e, 0xaf, 0xa3, 0x10, 0xbf, 0xf1, 0xbb, + }; + + scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes( + reinterpret_cast<const char*>(kCertificateDataDER), + sizeof(kCertificateDataDER)); + + std::string channel_bindings; + ASSERT_TRUE( + x509_util::GetTLSServerEndPointChannelBinding(*cert, &channel_bindings)); + + std::string expected_channel_bindings( + std::begin(kExpectedServerEndPointToken), + std::end(kExpectedServerEndPointToken)); + EXPECT_EQ(expected_channel_bindings, channel_bindings); +} + +TEST(X509UtilTest, CreateChannelBindings_SHA384) { + // Certificate: + // Data: + // Version: 3 (0x2) + // Serial Number: 10071585730232401378 (0x8bc575dc2f653de2) + // Signature Algorithm: sha384WithRSAEncryption + // ... + const uint8_t kCertificateDataDER[] = { + 0x30, 0x82, 0x03, 0xe1, 0x30, 0x82, 0x02, 0xc9, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x09, 0x00, 0x8b, 0xc5, 0x75, 0xdc, 0x2f, 0x65, 0x3d, 0xe2, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x0c, 0x05, 0x00, 0x30, 0x81, 0x86, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, + 0x69, 0x64, 0x67, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x0b, 0x4d, 0x6d, 0x6d, 0x6b, 0x61, 0x79, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, + 0x1d, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, + 0x31, 0x36, 0x30, 0x33, 0x31, 0x37, 0x31, 0x39, 0x35, 0x36, 0x34, 0x39, + 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x36, 0x31, 0x39, 0x35, + 0x36, 0x34, 0x39, 0x5a, 0x30, 0x81, 0x86, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x0c, 0x0b, 0x4d, 0x6d, 0x6d, 0x6b, 0x61, 0x79, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x0c, 0x1d, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x18, 0x30, 0x16, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, + 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, + 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xb4, 0xfa, 0x6c, 0xe7, 0xac, 0x91, + 0xa4, 0x00, 0xe1, 0xe8, 0xed, 0x5b, 0xe5, 0x86, 0x6b, 0x3d, 0x1d, 0x87, + 0xf7, 0x49, 0x5a, 0xda, 0x67, 0x65, 0x34, 0x57, 0x7b, 0x70, 0x71, 0x11, + 0xbd, 0xee, 0xfe, 0x01, 0x91, 0xb6, 0x43, 0x11, 0x0f, 0xec, 0x3f, 0x2f, + 0x05, 0xdb, 0x28, 0x44, 0x7e, 0x9c, 0x2b, 0xbb, 0xe9, 0x49, 0x2b, 0x62, + 0x1e, 0x8b, 0x4c, 0xf9, 0xa8, 0x2f, 0xfb, 0x24, 0x83, 0x13, 0xeb, 0x7f, + 0x52, 0x4c, 0xbb, 0xc5, 0x89, 0x6c, 0xe4, 0x22, 0xc0, 0x0c, 0x71, 0xda, + 0xb2, 0x36, 0xae, 0xc8, 0xe5, 0x10, 0x8f, 0x4a, 0x68, 0x65, 0xc3, 0x07, + 0xb5, 0xcf, 0xec, 0x08, 0xd9, 0x4b, 0x13, 0x4a, 0x25, 0x56, 0xec, 0x74, + 0x4d, 0xb3, 0xb5, 0x77, 0x3f, 0xf9, 0xa5, 0x0b, 0x15, 0x80, 0xf9, 0xe7, + 0x01, 0x4b, 0x73, 0x6a, 0x1e, 0xc8, 0xb0, 0x7a, 0x58, 0x13, 0x25, 0x50, + 0x40, 0x7e, 0x5c, 0x5d, 0xff, 0x2b, 0x9d, 0xf5, 0x43, 0xd2, 0xed, 0xca, + 0x87, 0xe3, 0x4e, 0x9f, 0x25, 0xa7, 0x75, 0xe9, 0x48, 0x7e, 0xb9, 0x38, + 0x74, 0x3f, 0x30, 0x6b, 0xec, 0x94, 0xb8, 0x0f, 0x00, 0x41, 0x60, 0xaa, + 0x48, 0x7d, 0x17, 0x65, 0x1a, 0x9a, 0x0d, 0x49, 0x18, 0xe8, 0x72, 0xbb, + 0x16, 0x37, 0xa0, 0x65, 0x0c, 0xe4, 0x69, 0x0f, 0x93, 0xca, 0x80, 0x7e, + 0xf6, 0x90, 0xbd, 0xf2, 0x86, 0xa3, 0xb6, 0x81, 0x7c, 0xe3, 0x40, 0x7a, + 0x65, 0x33, 0x71, 0xfd, 0x8c, 0xe6, 0xf6, 0x63, 0xcf, 0x40, 0xdd, 0x29, + 0xf2, 0x15, 0x25, 0x96, 0x1a, 0xa5, 0x14, 0x1e, 0xa2, 0xfd, 0x53, 0xb8, + 0xbc, 0x20, 0x10, 0x87, 0xcb, 0x8e, 0x24, 0xa9, 0x47, 0x60, 0x47, 0xcc, + 0xb2, 0x2e, 0xe5, 0x0f, 0x3e, 0x2c, 0x22, 0x9a, 0x1b, 0x46, 0x5a, 0xe4, + 0x2b, 0x7f, 0x4a, 0xab, 0x33, 0x49, 0xea, 0xd8, 0x6a, 0xd5, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x0f, 0x62, 0xc9, 0x94, 0xc0, 0x00, + 0x55, 0x51, 0x60, 0x36, 0xce, 0xd6, 0x4d, 0x6b, 0x5e, 0x20, 0x02, 0x6c, + 0x2e, 0xed, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, + 0x16, 0x80, 0x14, 0x0f, 0x62, 0xc9, 0x94, 0xc0, 0x00, 0x55, 0x51, 0x60, + 0x36, 0xce, 0xd6, 0x4d, 0x6b, 0x5e, 0x20, 0x02, 0x6c, 0x2e, 0xed, 0x30, + 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, + 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x31, 0x7f, 0xcd, + 0x8b, 0xf1, 0x9c, 0x87, 0x59, 0xed, 0xe2, 0x36, 0x18, 0x84, 0x1c, 0x54, + 0x4e, 0x92, 0x45, 0xaf, 0xe9, 0xa1, 0x78, 0x89, 0x6e, 0xad, 0xec, 0x51, + 0xf9, 0x81, 0x70, 0xd9, 0x94, 0x01, 0xa9, 0x2a, 0x0d, 0x5f, 0xda, 0x83, + 0x49, 0x32, 0x24, 0x7e, 0xfd, 0x73, 0x97, 0xa2, 0x05, 0xd4, 0xf1, 0xb7, + 0x3f, 0xa0, 0x49, 0xbc, 0x0c, 0x85, 0x3e, 0xd3, 0x15, 0x67, 0xef, 0x5f, + 0xfb, 0xbe, 0x0d, 0x2a, 0x97, 0xcd, 0xaa, 0x24, 0x1e, 0x5a, 0xdd, 0x47, + 0xcf, 0x70, 0xe4, 0x93, 0xe6, 0xc3, 0xad, 0x78, 0x84, 0x60, 0xfa, 0x16, + 0x2e, 0xcc, 0x98, 0x88, 0xde, 0x80, 0xbb, 0x8f, 0x46, 0xfd, 0x59, 0x95, + 0xb4, 0x0b, 0x07, 0x8a, 0x67, 0x04, 0x10, 0xbd, 0x32, 0xb0, 0xa2, 0xfe, + 0x0f, 0xe0, 0x3e, 0x49, 0x84, 0x89, 0xc6, 0x18, 0xd9, 0xca, 0xdd, 0x63, + 0x0d, 0x55, 0x46, 0x56, 0xd1, 0x83, 0xcb, 0x0d, 0x23, 0x21, 0xb3, 0x59, + 0xa9, 0xd5, 0x56, 0x83, 0x4f, 0xf0, 0x92, 0x0b, 0xcc, 0xed, 0x93, 0x02, + 0xe7, 0x07, 0x92, 0x15, 0x90, 0x18, 0x78, 0xc9, 0xf4, 0x59, 0x0e, 0xbe, + 0xaa, 0x3e, 0x91, 0xb7, 0x81, 0xa2, 0x0c, 0x28, 0x04, 0xde, 0x78, 0xb0, + 0xd1, 0x54, 0x90, 0x8f, 0x3c, 0xfd, 0x2e, 0x36, 0x6e, 0xfe, 0x7b, 0xf6, + 0xce, 0x65, 0xae, 0x99, 0xa5, 0x38, 0x29, 0x4b, 0x13, 0x2f, 0x01, 0xa8, + 0xb0, 0xd0, 0x43, 0x22, 0x01, 0xd1, 0x71, 0x35, 0x93, 0xcf, 0x1e, 0x9e, + 0x05, 0x03, 0x05, 0xff, 0xfc, 0x35, 0x34, 0x6f, 0x49, 0x04, 0xe6, 0x58, + 0xa6, 0x0a, 0xb6, 0x13, 0x67, 0xd8, 0x1e, 0xe7, 0x33, 0x0f, 0x51, 0xb1, + 0x5c, 0x75, 0x1c, 0xea, 0x2b, 0x94, 0xec, 0x32, 0x7e, 0xb0, 0x8c, 0xb7, + 0x63, 0xf4, 0x83, 0x58, 0x3e, 0x47, 0xb7, 0x92, 0x67, 0x2c, 0xd5, 0xdb, + 0x48}; + + const unsigned char kExpectedServerEndPointToken[] = { + 0x74, 0x6c, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2d, 0x65, + 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x3a, 0x9c, 0xd9, 0x91, + 0xd4, 0x57, 0x1b, 0x64, 0x9d, 0x84, 0x31, 0xfd, 0xda, 0x3d, 0xaa, 0x2e, + 0x26, 0xab, 0xee, 0x40, 0x6b, 0x95, 0x36, 0x82, 0xc4, 0x5f, 0xad, 0xc1, + 0x26, 0x29, 0x72, 0xda, 0xe6, 0xfd, 0xa6, 0xd8, 0x0e, 0xab, 0xa2, 0xca, + 0x7d, 0x7d, 0x18, 0xa8, 0xee, 0x80, 0x26, 0xb2, 0x1f, + }; + + scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes( + reinterpret_cast<const char*>(kCertificateDataDER), + sizeof(kCertificateDataDER)); + + std::string channel_bindings; + ASSERT_TRUE( + x509_util::GetTLSServerEndPointChannelBinding(*cert, &channel_bindings)); + + std::string expected_channel_bindings( + std::begin(kExpectedServerEndPointToken), + std::end(kExpectedServerEndPointToken)); + EXPECT_EQ(expected_channel_bindings, channel_bindings); +} + +TEST(X509UtilTest, CreateChannelBindings_SHA512) { + // Certificate: + // Data: + // Version: 3 (0x2) + // Serial Number: 15197703563697605045 (0xd2e916decbe249b5) + // Signature Algorithm: sha512WithRSAEncryption + // ... + const uint8_t kCertificateDataDER[] = { + 0x30, 0x82, 0x03, 0x81, 0x30, 0x82, 0x02, 0x69, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x09, 0x00, 0xd2, 0xe9, 0x16, 0xde, 0xcb, 0xe2, 0x49, 0xb5, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x0d, 0x05, 0x00, 0x30, 0x57, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x04, 0x42, 0x6c, 0x61, 0x68, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, + 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, + 0x31, 0x36, 0x30, 0x33, 0x31, 0x37, 0x32, 0x30, 0x31, 0x33, 0x31, 0x30, + 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x36, 0x32, 0x30, 0x31, + 0x33, 0x31, 0x30, 0x5a, 0x30, 0x57, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, 0x10, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, + 0x69, 0x64, 0x67, 0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x0c, 0x04, 0x42, 0x6c, 0x61, 0x68, 0x31, 0x18, 0x30, 0x16, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, + 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, + 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd3, 0xec, 0x61, 0x08, 0xbd, 0x91, + 0x94, 0x07, 0xaf, 0xf1, 0xf5, 0xeb, 0x84, 0x6d, 0x4b, 0x42, 0x0b, 0x40, + 0xb6, 0x6a, 0x51, 0x4d, 0x41, 0xde, 0x1c, 0xad, 0xf2, 0xcb, 0x73, 0xdb, + 0x41, 0x54, 0xd2, 0x13, 0xd6, 0xe9, 0x9b, 0xbe, 0x49, 0x3c, 0x6a, 0xeb, + 0x16, 0xa1, 0xee, 0x88, 0xbf, 0x58, 0xe6, 0x25, 0x52, 0x84, 0xdd, 0x3d, + 0x62, 0x34, 0x22, 0x81, 0x98, 0x55, 0x0d, 0xce, 0x6e, 0xf1, 0x72, 0xae, + 0x70, 0x34, 0x51, 0x4b, 0x54, 0xc8, 0x79, 0xe3, 0x57, 0xab, 0x24, 0xc0, + 0x29, 0x67, 0x38, 0xb1, 0x7f, 0x71, 0x32, 0x60, 0x08, 0x34, 0xa1, 0x92, + 0x6d, 0x78, 0xd6, 0x16, 0x73, 0x68, 0x32, 0x8b, 0xf8, 0x95, 0xa5, 0x79, + 0xfb, 0xa5, 0xd3, 0x8d, 0xb2, 0xa4, 0x4d, 0xc3, 0x22, 0xff, 0x2f, 0xae, + 0x6f, 0x12, 0xc9, 0xa6, 0xad, 0xe3, 0x6d, 0xc7, 0x40, 0x9b, 0x6a, 0xba, + 0x3c, 0x8c, 0xf3, 0x85, 0xa6, 0xc0, 0xbd, 0x49, 0xb6, 0x4f, 0xed, 0xaf, + 0x10, 0xb4, 0x17, 0x26, 0x40, 0x21, 0x01, 0xb7, 0xa9, 0xf0, 0x06, 0x98, + 0xfa, 0x03, 0x09, 0xe1, 0xfc, 0x7e, 0xcd, 0x70, 0x09, 0xcb, 0x19, 0x00, + 0x0a, 0x3c, 0x3a, 0xd8, 0x95, 0xfc, 0xd7, 0x2e, 0x92, 0x06, 0x25, 0x03, + 0xbd, 0x3f, 0x05, 0xf4, 0x89, 0x23, 0x41, 0x08, 0xc8, 0x3c, 0x62, 0xdc, + 0x25, 0xed, 0x01, 0x68, 0xf3, 0x75, 0x4d, 0xc5, 0xc2, 0xb0, 0x36, 0xb3, + 0x0f, 0x78, 0x4a, 0x2c, 0xa7, 0xbb, 0x13, 0x38, 0x09, 0xfd, 0x49, 0x95, + 0x99, 0x4c, 0x23, 0x36, 0x0a, 0x0f, 0x70, 0xbe, 0x02, 0xc3, 0x50, 0x30, + 0xb4, 0xaa, 0x7d, 0x47, 0x42, 0xbe, 0x62, 0x59, 0xbe, 0x88, 0xc4, 0x96, + 0x42, 0x63, 0xf3, 0x27, 0x09, 0x30, 0x9e, 0x58, 0xe6, 0xbe, 0x12, 0x2b, + 0x22, 0x11, 0x72, 0x65, 0x6c, 0x47, 0x50, 0x8c, 0x69, 0x0b, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, + 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x40, 0x1f, 0x60, 0x96, 0x13, 0x3e, + 0xb4, 0x93, 0x65, 0x71, 0x0e, 0x1b, 0xa3, 0xe6, 0x25, 0x21, 0xd6, 0x90, + 0x69, 0xed, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, + 0x16, 0x80, 0x14, 0x40, 0x1f, 0x60, 0x96, 0x13, 0x3e, 0xb4, 0x93, 0x65, + 0x71, 0x0e, 0x1b, 0xa3, 0xe6, 0x25, 0x21, 0xd6, 0x90, 0x69, 0xed, 0x30, + 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, + 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x0d, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x03, 0x4e, 0x0b, + 0xdd, 0x81, 0xe9, 0xf9, 0x91, 0x92, 0xa2, 0x77, 0xd0, 0x8f, 0x73, 0xb6, + 0x28, 0x7d, 0x3e, 0x2f, 0x36, 0x25, 0x01, 0x0f, 0x66, 0x14, 0x4d, 0x98, + 0x9d, 0x90, 0x08, 0x41, 0xfa, 0xe0, 0x8e, 0x15, 0xb6, 0xf9, 0x2c, 0x67, + 0x02, 0x31, 0x79, 0xa4, 0x2f, 0xb7, 0xf0, 0xf2, 0xfa, 0x28, 0xcf, 0xe5, + 0x71, 0x57, 0xd2, 0x18, 0xd5, 0xbd, 0x2b, 0xa8, 0x88, 0x10, 0xaf, 0xe9, + 0x68, 0x97, 0xb0, 0x04, 0x3f, 0x07, 0x5d, 0xb0, 0xc6, 0xfd, 0x34, 0xf0, + 0x14, 0xea, 0x81, 0xf5, 0x00, 0xd7, 0xe5, 0x0b, 0xde, 0x9a, 0x78, 0x93, + 0xe9, 0x64, 0x38, 0x93, 0x53, 0x57, 0x5c, 0x22, 0x1d, 0xec, 0xec, 0x77, + 0xc9, 0xed, 0x79, 0x8b, 0x85, 0xe6, 0xf2, 0xb0, 0x11, 0x34, 0x25, 0x20, + 0xdb, 0x3a, 0x82, 0x72, 0x15, 0x6e, 0xbb, 0x2b, 0x6c, 0xad, 0x26, 0x4d, + 0xb4, 0x2b, 0xd4, 0xd5, 0x45, 0x19, 0x6f, 0x3c, 0xd3, 0x42, 0x53, 0xdb, + 0x70, 0x6b, 0xd1, 0x9f, 0x24, 0x40, 0x55, 0xad, 0x64, 0x7e, 0x66, 0x80, + 0x45, 0xfb, 0x30, 0x97, 0x20, 0x3d, 0x3e, 0x14, 0xfe, 0x88, 0x0d, 0xd9, + 0x3a, 0x7e, 0x30, 0x5c, 0x75, 0x87, 0x59, 0x37, 0xe7, 0xb9, 0xff, 0x3d, + 0xf8, 0x47, 0xe4, 0xb7, 0xa6, 0xcc, 0x62, 0xc8, 0xfa, 0x55, 0x93, 0xe8, + 0xe4, 0x33, 0x29, 0x33, 0x91, 0xeb, 0x16, 0x95, 0xdc, 0x63, 0xaf, 0x5e, + 0x9b, 0x0c, 0xa4, 0x99, 0x20, 0x90, 0x80, 0x1c, 0xbe, 0x9f, 0x22, 0x93, + 0x21, 0xe1, 0x1c, 0x16, 0x92, 0x42, 0x42, 0x67, 0xfb, 0xf3, 0x31, 0x8c, + 0x78, 0x41, 0x43, 0xed, 0x5f, 0x09, 0x0b, 0x21, 0x72, 0x40, 0x95, 0xdb, + 0xd7, 0x8d, 0x2a, 0xe1, 0x52, 0x03, 0x57, 0xc8, 0x7b, 0x15, 0x90, 0x92, + 0xdf, 0x07, 0x11, 0xfb, 0xf7, 0x25, 0xbe, 0xcb, 0x0b, 0xfa, 0xa6, 0x34, + 0x61, + }; + + const unsigned char kExpectedServerEndPointToken[] = { + 0x74, 0x6c, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2d, + 0x65, 0x6e, 0x64, 0x2d, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x3a, 0x2c, + 0x33, 0xc9, 0xee, 0x30, 0xa1, 0x99, 0xdc, 0x19, 0x48, 0x0a, 0xec, + 0xc5, 0x1d, 0x94, 0xc7, 0x84, 0x3d, 0xc7, 0x9e, 0x51, 0xee, 0xbc, + 0x23, 0x33, 0xfd, 0xeb, 0x20, 0x78, 0x3b, 0x93, 0xe8, 0xe6, 0x78, + 0x10, 0xd7, 0x5e, 0x37, 0x48, 0x04, 0x07, 0x5f, 0x57, 0xe6, 0x16, + 0xe2, 0x45, 0x44, 0xa3, 0x71, 0x8c, 0xef, 0x95, 0x08, 0x6b, 0x0c, + 0xaa, 0x65, 0x51, 0x51, 0x60, 0x4f, 0x58, 0x28, + }; + + scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes( + reinterpret_cast<const char*>(kCertificateDataDER), + sizeof(kCertificateDataDER)); + + std::string channel_bindings; + ASSERT_TRUE( + x509_util::GetTLSServerEndPointChannelBinding(*cert, &channel_bindings)); + + std::string expected_channel_bindings( + std::begin(kExpectedServerEndPointToken), + std::end(kExpectedServerEndPointToken)); + EXPECT_EQ(expected_channel_bindings, channel_bindings); +} + +TEST(X509UtilTest, CreateChannelBindings_Unsupported_MD4) { + // Certificate: + // Data: + // Version: 3 (0x2) + // Serial Number: 12629177056471137087 (0xaf43d99ee079bb3f) + // Signature Algorithm: md4WithRSAEncryption + // ... + const uint8_t kCertificateDataDER[] = { + 0x30, 0x82, 0x03, 0x87, 0x30, 0x82, 0x02, 0x6f, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x09, 0x00, 0xaf, 0x43, 0xd9, 0x9e, 0xe0, 0x79, 0xbb, 0x3f, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x03, 0x05, 0x00, 0x30, 0x5a, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, 0x12, 0x30, 0x10, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, + 0x1e, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x33, 0x31, 0x37, 0x32, 0x30, 0x31, + 0x39, 0x35, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x36, 0x30, 0x34, 0x31, 0x36, + 0x32, 0x30, 0x31, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x5a, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x4d, 0x41, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x10, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, + 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, + 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xaf, 0xf8, 0xa5, 0xba, 0x20, 0x40, 0xcd, 0x60, 0x88, 0x1f, 0x27, 0x34, + 0x57, 0x2f, 0x1b, 0xc9, 0xfc, 0xf3, 0x0b, 0x9f, 0xb3, 0xb8, 0x26, 0x67, + 0x78, 0x79, 0x2b, 0xfe, 0x68, 0xa3, 0x95, 0x8c, 0x40, 0x6f, 0x80, 0x8b, + 0x15, 0x8f, 0x0b, 0x4c, 0x66, 0x8d, 0x17, 0x32, 0x6a, 0xa0, 0x57, 0x74, + 0x2d, 0x31, 0xc4, 0x8e, 0xa4, 0x76, 0x6b, 0xff, 0x93, 0x05, 0x44, 0x9b, + 0xe9, 0xf2, 0x81, 0x1e, 0x3b, 0x2e, 0x05, 0x67, 0x01, 0x85, 0x5a, 0xed, + 0xad, 0xc8, 0x55, 0x4b, 0x8e, 0x80, 0x1e, 0x7a, 0x5a, 0xbd, 0xc2, 0x8e, + 0x5f, 0x4f, 0x3a, 0x52, 0xda, 0x2d, 0x86, 0x0d, 0x6b, 0xaf, 0xe2, 0x12, + 0xd1, 0x6e, 0x15, 0x78, 0xb5, 0x06, 0x1c, 0xa2, 0xb4, 0xda, 0x3c, 0xfe, + 0x8b, 0x4c, 0x70, 0x5c, 0xc5, 0x5c, 0x86, 0xf6, 0x95, 0x01, 0x88, 0x44, + 0x99, 0xd2, 0x97, 0x47, 0xdb, 0xdb, 0x4f, 0x6d, 0x1a, 0xd1, 0x1d, 0x74, + 0x0b, 0x89, 0x5c, 0x05, 0x19, 0xe7, 0xe7, 0x17, 0xee, 0xb5, 0xf8, 0x75, + 0x96, 0x95, 0x5a, 0xfd, 0x37, 0x4d, 0xa1, 0xda, 0x5c, 0xf6, 0x5c, 0x60, + 0xa1, 0x04, 0x92, 0xa5, 0x42, 0x02, 0xbd, 0x40, 0xb3, 0x1e, 0xab, 0x28, + 0x0b, 0x28, 0x79, 0x92, 0xdc, 0x23, 0xde, 0xad, 0x28, 0x06, 0xba, 0x93, + 0x28, 0x3f, 0xf4, 0x6a, 0x10, 0x11, 0xf1, 0xe4, 0x92, 0x5b, 0x65, 0xce, + 0x0f, 0x13, 0x34, 0x87, 0xb6, 0xa4, 0x1d, 0xe3, 0x4a, 0xea, 0xc8, 0xcf, + 0x4e, 0x21, 0xf2, 0x70, 0x18, 0x9f, 0x3a, 0x62, 0x43, 0x70, 0x89, 0xb9, + 0xca, 0xab, 0xa6, 0xb1, 0x55, 0x42, 0x3d, 0x25, 0x35, 0xd6, 0xa2, 0x77, + 0x0f, 0x66, 0x88, 0xd2, 0x43, 0x6b, 0xfa, 0x3c, 0xa3, 0xcf, 0xa1, 0x56, + 0x84, 0xe5, 0x9b, 0x25, 0xff, 0x02, 0xb6, 0x9d, 0xaf, 0x6a, 0x4d, 0x8c, + 0xf8, 0x3e, 0xf7, 0xe5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, + 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, + 0x62, 0xf2, 0x1f, 0xd6, 0x29, 0xfa, 0x61, 0x88, 0x4c, 0x36, 0x39, 0xed, + 0x9f, 0x8e, 0xcf, 0x3b, 0xdc, 0x90, 0x04, 0xa5, 0x30, 0x1f, 0x06, 0x03, + 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x62, 0xf2, 0x1f, + 0xd6, 0x29, 0xfa, 0x61, 0x88, 0x4c, 0x36, 0x39, 0xed, 0x9f, 0x8e, 0xcf, + 0x3b, 0xdc, 0x90, 0x04, 0xa5, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x03, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x01, 0x00, 0x9e, 0x36, 0xff, 0xf5, 0x77, 0x46, 0x80, 0x22, 0xc4, + 0x01, 0x05, 0x69, 0x84, 0xd1, 0xdc, 0x0c, 0xce, 0xda, 0x2f, 0x21, 0x11, + 0x9a, 0x80, 0x24, 0x81, 0xea, 0x1b, 0x1a, 0xb9, 0x5d, 0x70, 0x60, 0xaf, + 0xbc, 0xca, 0xdb, 0xc4, 0x10, 0x6e, 0x17, 0xdb, 0x58, 0x11, 0x0c, 0xec, + 0x0e, 0xdd, 0xf8, 0xbf, 0x42, 0x27, 0x2d, 0x06, 0x75, 0x25, 0xc0, 0xdb, + 0xb0, 0x35, 0x0c, 0x66, 0xfb, 0xfd, 0x0e, 0xb9, 0x16, 0x9e, 0x34, 0xaf, + 0xdb, 0x72, 0x6e, 0xb3, 0x6d, 0x5e, 0xb2, 0xf0, 0x6d, 0x46, 0x32, 0xba, + 0x35, 0xb5, 0x3b, 0xc5, 0x72, 0xb7, 0x1c, 0x88, 0x6a, 0x84, 0xc2, 0xde, + 0x1d, 0x45, 0x30, 0x41, 0x3d, 0xc5, 0xbb, 0x0a, 0x78, 0xe9, 0xef, 0x59, + 0xc6, 0xbc, 0x0c, 0x9d, 0x36, 0x1f, 0xc8, 0xb1, 0x1b, 0xd3, 0x1c, 0xec, + 0x57, 0x69, 0x8b, 0xcb, 0x1b, 0x93, 0x99, 0x2e, 0xab, 0x8d, 0xd7, 0x63, + 0xc5, 0x1f, 0x58, 0x9d, 0x06, 0x8e, 0xf1, 0x47, 0x64, 0xc5, 0xf3, 0x03, + 0x8d, 0x2c, 0x8a, 0x99, 0x2c, 0xe6, 0x89, 0x87, 0xb2, 0x42, 0xdd, 0x18, + 0xf0, 0xc9, 0xdb, 0x6c, 0xee, 0x3e, 0x5e, 0xc5, 0x75, 0xc7, 0x45, 0xd3, + 0xd0, 0xaa, 0xf7, 0x0d, 0xac, 0xaa, 0x4c, 0xb4, 0xa4, 0xa2, 0xb7, 0xfc, + 0x65, 0xb0, 0x2e, 0x83, 0xbd, 0x7a, 0x65, 0xfb, 0x1b, 0x92, 0x3f, 0x8d, + 0x47, 0x0c, 0xbb, 0x4a, 0x38, 0xc5, 0x67, 0x87, 0x8e, 0x79, 0xd6, 0x48, + 0xc7, 0xf2, 0x92, 0xdb, 0x6e, 0xf9, 0x54, 0x01, 0xed, 0xdb, 0xbd, 0xe0, + 0x12, 0x18, 0xd9, 0xcf, 0x36, 0x5d, 0x7e, 0xe9, 0xb9, 0x27, 0x09, 0x80, + 0x1a, 0x2f, 0xb9, 0x58, 0xc6, 0x6f, 0xa2, 0x42, 0x7a, 0x7b, 0x20, 0xf2, + 0xc9, 0x85, 0x54, 0x11, 0xa2, 0xe3, 0x31, 0x0f, 0x71, 0x6a, 0xea, 0x0e, + 0xef, 0xba, 0x6d, 0x5e, 0x88, 0x01, 0xaf, + }; + + scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes( + reinterpret_cast<const char*>(kCertificateDataDER), + sizeof(kCertificateDataDER)); + + std::string channel_bindings; + ASSERT_FALSE( + x509_util::GetTLSServerEndPointChannelBinding(*cert, &channel_bindings)); + EXPECT_TRUE(channel_bindings.empty()); +} +#endif + } // namespace x509_util } // namespace net diff --git a/net/http/http_auth.cc b/net/http/http_auth.cc index f17b502..570d8f7 100644 --- a/net/http/http_auth.cc +++ b/net/http/http_auth.cc @@ -24,7 +24,8 @@ HttpAuth::Identity::Identity() : source(IDENT_SRC_NONE), invalid(true) {} // static void HttpAuth::ChooseBestChallenge( HttpAuthHandlerFactory* http_auth_handler_factory, - const HttpResponseHeaders* headers, + const HttpResponseHeaders& response_headers, + const SSLInfo& ssl_info, Target target, const GURL& origin, const std::set<Scheme>& disabled_schemes, @@ -38,10 +39,10 @@ void HttpAuth::ChooseBestChallenge( const std::string header_name = GetChallengeHeaderName(target); std::string cur_challenge; size_t iter = 0; - while (headers->EnumerateHeader(&iter, header_name, &cur_challenge)) { + while (response_headers.EnumerateHeader(&iter, header_name, &cur_challenge)) { scoped_ptr<HttpAuthHandler> cur; int rv = http_auth_handler_factory->CreateAuthHandlerFromString( - cur_challenge, target, origin, net_log, &cur); + cur_challenge, target, ssl_info, origin, net_log, &cur); if (rv != OK) { VLOG(1) << "Unable to create AuthHandler. Status: " << ErrorToString(rv) << " Challenge: " << cur_challenge; @@ -57,12 +58,11 @@ void HttpAuth::ChooseBestChallenge( // static HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse( HttpAuthHandler* handler, - const HttpResponseHeaders* headers, + const HttpResponseHeaders& response_headers, Target target, const std::set<Scheme>& disabled_schemes, std::string* challenge_used) { DCHECK(handler); - DCHECK(headers); DCHECK(challenge_used); challenge_used->clear(); HttpAuth::Scheme current_scheme = handler->auth_scheme(); @@ -74,7 +74,7 @@ HttpAuth::AuthorizationResult HttpAuth::HandleChallengeResponse( std::string challenge; HttpAuth::AuthorizationResult authorization_result = HttpAuth::AUTHORIZATION_RESULT_INVALID; - while (headers->EnumerateHeader(&iter, header_name, &challenge)) { + while (response_headers.EnumerateHeader(&iter, header_name, &challenge)) { HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end()); if (!base::LowerCaseEqualsASCII(props.scheme(), current_scheme_name.c_str())) diff --git a/net/http/http_auth.h b/net/http/http_auth.h index 5a2c7ac..f804a4d 100644 --- a/net/http/http_auth.h +++ b/net/http/http_auth.h @@ -21,6 +21,7 @@ class BoundNetLog; class HttpAuthHandler; class HttpAuthHandlerFactory; class HttpResponseHeaders; +class SSLInfo; // Utility class for http authentication. class NET_EXPORT_PRIVATE HttpAuth { @@ -122,18 +123,22 @@ class NET_EXPORT_PRIVATE HttpAuth { // Returns a string representation of an authentication Scheme. static const char* SchemeToString(Scheme scheme); - // Iterate through the challenge headers, and pick the best one that - // we support. Obtains the implementation class for handling the challenge, - // and passes it back in |*handler|. If no supported challenge was found, - // |*handler| is set to NULL. + // Iterate through |response_headers|, and pick the best one that we support. + // Obtains the implementation class for handling the challenge, and passes it + // back in |*handler|. If no supported challenge was found, |*handler| is set + // to NULL. // // |disabled_schemes| is the set of schemes that we should not use. // // |origin| is used by the NTLM and Negotiation authentication scheme to - // construct the service principal name. It is ignored by other schemes. + // construct the service principal name. It is ignored by other schemes. + // + // |ssl_info| is passed through to the scheme specific authentication handlers + // to use as appropriate. static void ChooseBestChallenge( HttpAuthHandlerFactory* http_auth_handler_factory, - const HttpResponseHeaders* headers, + const HttpResponseHeaders& response_headers, + const SSLInfo& ssl_info, Target target, const GURL& origin, const std::set<Scheme>& disabled_schemes, @@ -150,7 +155,7 @@ class NET_EXPORT_PRIVATE HttpAuth { // |handler| must be non-NULL, and is the HttpAuthHandler from the previous // authentication round. // - // |headers| must be non-NULL and contain the new HTTP response. + // |response_headers| must contain the new HTTP response. // // |target| specifies whether the authentication challenge response came // from a server or a proxy. @@ -163,7 +168,7 @@ class NET_EXPORT_PRIVATE HttpAuth { // the value is cleared. static AuthorizationResult HandleChallengeResponse( HttpAuthHandler* handler, - const HttpResponseHeaders* headers, + const HttpResponseHeaders& response_headers, Target target, const std::set<Scheme>& disabled_schemes, std::string* challenge_used); diff --git a/net/http/http_auth_cache_unittest.cc b/net/http/http_auth_cache_unittest.cc index 18866ea..cb7d640 100644 --- a/net/http/http_auth_cache_unittest.cc +++ b/net/http/http_auth_cache_unittest.cc @@ -38,7 +38,8 @@ class MockAuthHandler : public HttpAuthHandler { } protected: - bool Init(HttpAuthChallengeTokenizer* challenge) override { + bool Init(HttpAuthChallengeTokenizer* challenge, + const SSLInfo& ssl_info) override { return false; // Unused. } diff --git a/net/http/http_auth_controller.cc b/net/http/http_auth_controller.cc index 5c3d3a5..fa7d5ae 100644 --- a/net/http/http_auth_controller.cc +++ b/net/http/http_auth_controller.cc @@ -24,35 +24,6 @@ namespace net { namespace { -// Returns a log message for all the response headers related to the auth -// challenge. -std::string AuthChallengeLogMessage(HttpResponseHeaders* headers) { - std::string msg; - std::string header_val; - size_t iter = 0; - while (headers->EnumerateHeader(&iter, "proxy-authenticate", &header_val)) { - msg.append("\n Has header Proxy-Authenticate: "); - msg.append(header_val); - } - - iter = 0; - while (headers->EnumerateHeader(&iter, "www-authenticate", &header_val)) { - msg.append("\n Has header WWW-Authenticate: "); - msg.append(header_val); - } - - // RFC 4559 requires that a proxy indicate its support of NTLM/Negotiate - // authentication with a "Proxy-Support: Session-Based-Authentication" - // response header. - iter = 0; - while (headers->EnumerateHeader(&iter, "proxy-support", &header_val)) { - msg.append("\n Has header Proxy-Support: "); - msg.append(header_val); - } - - return msg; -} - enum AuthEvent { AUTH_EVENT_START = 0, AUTH_EVENT_REJECT, @@ -247,15 +218,13 @@ void HttpAuthController::AddAuthorizationHeader( int HttpAuthController::HandleAuthChallenge( scoped_refptr<HttpResponseHeaders> headers, + const SSLInfo& ssl_info, bool do_not_send_server_auth, bool establishing_tunnel, const BoundNetLog& net_log) { DCHECK(CalledOnValidThread()); DCHECK(headers.get()); DCHECK(auth_origin_.is_valid()); - VLOG(1) << "The " << HttpAuth::GetAuthTargetString(target_) << " " - << auth_origin_ << " requested auth " - << AuthChallengeLogMessage(headers.get()); // Give the existing auth handler first try at the authentication headers. // This will also evict the entry in the HttpAuthCache if the previous @@ -263,12 +232,8 @@ int HttpAuthController::HandleAuthChallenge( // case. if (HaveAuth()) { std::string challenge_used; - HttpAuth::AuthorizationResult result = - HttpAuth::HandleChallengeResponse(handler_.get(), - headers.get(), - target_, - disabled_schemes_, - &challenge_used); + HttpAuth::AuthorizationResult result = HttpAuth::HandleChallengeResponse( + handler_.get(), *headers, target_, disabled_schemes_, &challenge_used); switch (result) { case HttpAuth::AUTHORIZATION_RESULT_ACCEPT: break; @@ -317,24 +282,15 @@ int HttpAuthController::HandleAuthChallenge( do { if (!handler_.get() && can_send_auth) { // Find the best authentication challenge that we support. - HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, - headers.get(), - target_, - auth_origin_, - disabled_schemes_, - net_log, - &handler_); + HttpAuth::ChooseBestChallenge(http_auth_handler_factory_, *headers, + ssl_info, target_, auth_origin_, + disabled_schemes_, net_log, &handler_); if (handler_.get()) HistogramAuthEvent(handler_.get(), AUTH_EVENT_START); } if (!handler_.get()) { if (establishing_tunnel) { - LOG(ERROR) << "Can't perform auth to the " - << HttpAuth::GetAuthTargetString(target_) << " " - << auth_origin_ << " when establishing a tunnel" - << AuthChallengeLogMessage(headers.get()); - // We are establishing a tunnel, we can't show the error page because an // active network attacker could control its contents. Instead, we just // fail to establish the tunnel. diff --git a/net/http/http_auth_controller.h b/net/http/http_auth_controller.h index b7d6e94..9b016f7 100644 --- a/net/http/http_auth_controller.h +++ b/net/http/http_auth_controller.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -26,6 +26,7 @@ class HttpAuthHandlerFactory; class HttpAuthCache; class HttpRequestHeaders; struct HttpRequestInfo; +class SSLInfo; class NET_EXPORT_PRIVATE HttpAuthController : public base::RefCounted<HttpAuthController>, @@ -55,6 +56,7 @@ class NET_EXPORT_PRIVATE HttpAuthController // |HandleAuthChallenge()| returns OK on success, or a network error code // otherwise. It may also populate |auth_info_|. virtual int HandleAuthChallenge(scoped_refptr<HttpResponseHeaders> headers, + const SSLInfo& ssl_info, bool do_not_send_server_auth, bool establishing_tunnel, const BoundNetLog& net_log); diff --git a/net/http/http_auth_controller_unittest.cc b/net/http/http_auth_controller_unittest.cc index cd97d29..b3d1ca3 100644 --- a/net/http/http_auth_controller_unittest.cc +++ b/net/http/http_auth_controller_unittest.cc @@ -14,6 +14,7 @@ #include "net/http/http_response_headers.h" #include "net/http/http_util.h" #include "net/log/net_log.h" +#include "net/ssl/ssl_info.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -72,8 +73,9 @@ void RunSingleRoundAuthTest(HandlerRunMode run_mode, new HttpAuthController(HttpAuth::AUTH_PROXY, GURL("http://example.com"), &dummy_auth_cache, &auth_handler_factory)); - ASSERT_EQ(OK, - controller->HandleAuthChallenge(headers, false, false, dummy_log)); + SSLInfo null_ssl_info; + ASSERT_EQ(OK, controller->HandleAuthChallenge(headers, null_ssl_info, false, + false, dummy_log)); ASSERT_TRUE(controller->HaveAuthHandler()); controller->ResetAuth(AuthCredentials()); EXPECT_TRUE(controller->HaveAuth()); @@ -128,8 +130,9 @@ TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) { } protected: - bool Init(HttpAuthChallengeTokenizer* challenge) override { - HttpAuthHandlerMock::Init(challenge); + bool Init(HttpAuthChallengeTokenizer* challenge, + const SSLInfo& ssl_info) override { + HttpAuthHandlerMock::Init(challenge, ssl_info); set_allows_default_credentials(true); set_allows_explicit_credentials(false); set_connection_based(true); @@ -209,8 +212,9 @@ TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) { new HttpAuthController(HttpAuth::AUTH_SERVER, GURL("http://example.com"), &dummy_auth_cache, &auth_handler_factory)); - ASSERT_EQ(OK, - controller->HandleAuthChallenge(headers, false, false, dummy_log)); + SSLInfo null_ssl_info; + ASSERT_EQ(OK, controller->HandleAuthChallenge(headers, null_ssl_info, false, + false, dummy_log)); ASSERT_TRUE(controller->HaveAuthHandler()); controller->ResetAuth(AuthCredentials()); EXPECT_TRUE(controller->HaveAuth()); @@ -222,8 +226,8 @@ TEST(HttpAuthControllerTest, NoExplicitCredentialsAllowed) { // Once a token is generated, simulate the receipt of a server response // indicating that the authentication attempt was rejected. - ASSERT_EQ(OK, - controller->HandleAuthChallenge(headers, false, false, dummy_log)); + ASSERT_EQ(OK, controller->HandleAuthChallenge(headers, null_ssl_info, false, + false, dummy_log)); ASSERT_TRUE(controller->HaveAuthHandler()); controller->ResetAuth(AuthCredentials(base::ASCIIToUTF16("Hello"), base::string16())); diff --git a/net/http/http_auth_gssapi_posix.cc b/net/http/http_auth_gssapi_posix.cc index d70d884..40fbd63 100644 --- a/net/http/http_auth_gssapi_posix.cc +++ b/net/http/http_auth_gssapi_posix.cc @@ -700,6 +700,7 @@ HttpAuth::AuthorizationResult HttpAuthGSSAPI::ParseChallenge( int HttpAuthGSSAPI::GenerateAuthToken(const AuthCredentials* credentials, const std::string& spn, + const std::string& channel_bindings, std::string* auth_token, const CompletionCallback& /*callback*/) { DCHECK(auth_token); @@ -711,7 +712,8 @@ int HttpAuthGSSAPI::GenerateAuthToken(const AuthCredentials* credentials, NULL; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; ScopedBuffer scoped_output_token(&output_token, library_); - int rv = GetNextSecurityToken(spn, &input_token, &output_token); + int rv = + GetNextSecurityToken(spn, channel_bindings, &input_token, &output_token); if (rv != OK) return rv; @@ -819,6 +821,7 @@ int MapInitSecContextStatusToError(OM_uint32 major_status) { } int HttpAuthGSSAPI::GetNextSecurityToken(const std::string& spn, + const std::string& channel_bindings, gss_buffer_t in_token, gss_buffer_t out_token) { // Create a name for the principal @@ -843,24 +846,32 @@ int HttpAuthGSSAPI::GetNextSecurityToken(const std::string& spn, } ScopedName scoped_name(principal_name, library_); + std::vector<char> channel_bindings_data; + scoped_ptr<gss_channel_bindings_struct> gss_channel_bindings; + if (!channel_bindings.empty()) { + gss_channel_bindings.reset(new gss_channel_bindings_struct); + memset(gss_channel_bindings.get(), 0, sizeof(gss_channel_bindings_struct)); + channel_bindings_data.assign(channel_bindings.begin(), + channel_bindings.end()); + gss_channel_bindings->application_data.value = channel_bindings_data.data(); + gss_channel_bindings->application_data.length = + channel_bindings_data.size(); + } + // Continue creating a security context. OM_uint32 req_flags = 0; if (can_delegate_) req_flags |= GSS_C_DELEG_FLAG; major_status = library_->init_sec_context( - &minor_status, - GSS_C_NO_CREDENTIAL, - scoped_sec_context_.receive(), - principal_name, - gss_oid_, - req_flags, - GSS_C_INDEFINITE, - GSS_C_NO_CHANNEL_BINDINGS, + &minor_status, GSS_C_NO_CREDENTIAL, scoped_sec_context_.receive(), + principal_name, gss_oid_, req_flags, GSS_C_INDEFINITE, + gss_channel_bindings ? gss_channel_bindings.get() + : GSS_C_NO_CHANNEL_BINDINGS, in_token, - NULL, // actual_mech_type + nullptr, // actual_mech_type out_token, - NULL, // ret flags - NULL); + nullptr, // ret flags + nullptr); rv = MapInitSecContextStatusToError(major_status); if (rv != OK) { LOG(ERROR) << "Problem initializing context. \n" diff --git a/net/http/http_auth_gssapi_posix.h b/net/http/http_auth_gssapi_posix.h index cf4dcd5..6a65761 100644 --- a/net/http/http_auth_gssapi_posix.h +++ b/net/http/http_auth_gssapi_posix.h @@ -272,6 +272,7 @@ class NET_EXPORT_PRIVATE HttpAuthGSSAPI { // credentials are used instead. int GenerateAuthToken(const AuthCredentials* credentials, const std::string& spn, + const std::string& channel_bindings, std::string* auth_token, const CompletionCallback& callback); @@ -282,6 +283,7 @@ class NET_EXPORT_PRIVATE HttpAuthGSSAPI { private: int GetNextSecurityToken(const std::string& spn, + const std::string& channel_bindings, gss_buffer_t in_token, gss_buffer_t out_token); diff --git a/net/http/http_auth_gssapi_posix_unittest.cc b/net/http/http_auth_gssapi_posix_unittest.cc index 6334fbe..8208701 100644 --- a/net/http/http_auth_gssapi_posix_unittest.cc +++ b/net/http/http_auth_gssapi_posix_unittest.cc @@ -209,7 +209,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_TwoRounds) { EstablishInitialContext(&mock_library); std::string auth_token; EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", - &auth_token, + std::string(), &auth_token, base::Bind(&UnexpectedCallback))); std::string second_challenge_text = "Negotiate Zm9vYmFy"; @@ -247,7 +247,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_MissingTokenSecondRound) { EstablishInitialContext(&mock_library); std::string auth_token; EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", - &auth_token, + std::string(), &auth_token, base::Bind(&UnexpectedCallback))); std::string second_challenge_text = "Negotiate"; HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(), @@ -271,7 +271,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_NonBase64EncodedToken) { EstablishInitialContext(&mock_library); std::string auth_token; EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", - &auth_token, + std::string(), &auth_token, base::Bind(&UnexpectedCallback))); std::string second_challenge_text = "Negotiate =happyjoy="; HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(), diff --git a/net/http/http_auth_handler.cc b/net/http/http_auth_handler.cc index 4de2226..32af2d2 100644 --- a/net/http/http_auth_handler.cc +++ b/net/http/http_auth_handler.cc @@ -22,11 +22,11 @@ HttpAuthHandler::HttpAuthHandler() HttpAuthHandler::~HttpAuthHandler() { } -bool HttpAuthHandler::InitFromChallenge( - HttpAuthChallengeTokenizer* challenge, - HttpAuth::Target target, - const GURL& origin, - const BoundNetLog& net_log) { +bool HttpAuthHandler::InitFromChallenge(HttpAuthChallengeTokenizer* challenge, + HttpAuth::Target target, + const SSLInfo& ssl_info, + const GURL& origin, + const BoundNetLog& net_log) { origin_ = origin; target_ = target; score_ = -1; @@ -34,7 +34,7 @@ bool HttpAuthHandler::InitFromChallenge( net_log_ = net_log; auth_challenge_ = challenge->challenge_text(); - bool ok = Init(challenge); + bool ok = Init(challenge, ssl_info); // Init() is expected to set the scheme, realm, score, and properties. The // realm may be empty. diff --git a/net/http/http_auth_handler.h b/net/http/http_auth_handler.h index 1aee795..4a6cb79 100644 --- a/net/http/http_auth_handler.h +++ b/net/http/http_auth_handler.h @@ -16,6 +16,7 @@ namespace net { class HttpAuthChallengeTokenizer; struct HttpRequestInfo; +class SSLInfo; // HttpAuthHandler is the interface for the authentication schemes // (basic, digest, NTLM, Negotiate). @@ -32,6 +33,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandler { // for later use, and are not part of the initial challenge. bool InitFromChallenge(HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, const BoundNetLog& net_log); @@ -148,9 +150,14 @@ class NET_EXPORT_PRIVATE HttpAuthHandler { // |challenge| must be non-NULL and have already tokenized the // authentication scheme, but none of the tokens occurring after the // authentication scheme. + // + // If the request was sent over an encrypted connection, |ssl_info| is valid + // and describes the connection. + // // Implementations are expected to initialize the following members: // scheme_, realm_, score_, properties_ - virtual bool Init(HttpAuthChallengeTokenizer* challenge) = 0; + virtual bool Init(HttpAuthChallengeTokenizer* challenge, + const SSLInfo& ssl_info) = 0; // |GenerateAuthTokenImpl()} is the auth-scheme specific implementation // of generating the next auth token. Callers should use |GenerateAuthToken()| diff --git a/net/http/http_auth_handler_basic.cc b/net/http/http_auth_handler_basic.cc index 4536785..c5a1d23 100644 --- a/net/http/http_auth_handler_basic.cc +++ b/net/http/http_auth_handler_basic.cc @@ -53,7 +53,8 @@ bool ParseRealm(const HttpAuthChallengeTokenizer& tokenizer, } // namespace -bool HttpAuthHandlerBasic::Init(HttpAuthChallengeTokenizer* challenge) { +bool HttpAuthHandlerBasic::Init(HttpAuthChallengeTokenizer* challenge, + const SSLInfo& ssl_info) { auth_scheme_ = HttpAuth::AUTH_SCHEME_BASIC; score_ = 1; properties_ = 0; @@ -109,6 +110,7 @@ HttpAuthHandlerBasic::Factory::~Factory() { int HttpAuthHandlerBasic::Factory::CreateAuthHandler( HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int digest_nonce_count, @@ -117,7 +119,8 @@ int HttpAuthHandlerBasic::Factory::CreateAuthHandler( // TODO(cbentzel): Move towards model of parsing in the factory // method and only constructing when valid. scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerBasic()); - if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) + if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin, + net_log)) return ERR_INVALID_RESPONSE; handler->swap(tmp_handler); return OK; diff --git a/net/http/http_auth_handler_basic.h b/net/http/http_auth_handler_basic.h index 186caf6..9ad311a 100644 --- a/net/http/http_auth_handler_basic.h +++ b/net/http/http_auth_handler_basic.h @@ -23,6 +23,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerBasic : public HttpAuthHandler { int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int digest_nonce_count, @@ -34,7 +35,8 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerBasic : public HttpAuthHandler { HttpAuthChallengeTokenizer* challenge) override; protected: - bool Init(HttpAuthChallengeTokenizer* challenge) override; + bool Init(HttpAuthChallengeTokenizer* challenge, + const SSLInfo& ssl_info) override; int GenerateAuthTokenImpl(const AuthCredentials* credentials, const HttpRequestInfo* request, diff --git a/net/http/http_auth_handler_basic_unittest.cc b/net/http/http_auth_handler_basic_unittest.cc index e6a9818..0b0e115 100644 --- a/net/http/http_auth_handler_basic_unittest.cc +++ b/net/http/http_auth_handler_basic_unittest.cc @@ -12,6 +12,7 @@ #include "net/http/http_auth_challenge_tokenizer.h" #include "net/http/http_auth_handler_basic.h" #include "net/http/http_request_info.h" +#include "net/ssl/ssl_info.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -34,9 +35,11 @@ TEST(HttpAuthHandlerBasicTest, GenerateAuthToken) { HttpAuthHandlerBasic::Factory factory; for (size_t i = 0; i < arraysize(tests); ++i) { std::string challenge = "Basic realm=\"Atlantis\""; + SSLInfo null_ssl_info; scoped_ptr<HttpAuthHandler> basic; EXPECT_EQ(OK, factory.CreateAuthHandlerFromString( - challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog(), &basic)); + challenge, HttpAuth::AUTH_SERVER, null_ssl_info, origin, + BoundNetLog(), &basic)); AuthCredentials credentials(base::ASCIIToUTF16(tests[i].username), base::ASCIIToUTF16(tests[i].password)); HttpRequestInfo request_info; @@ -86,10 +89,11 @@ TEST(HttpAuthHandlerBasicTest, HandleAnotherChallenge) { GURL origin("http://www.example.com"); HttpAuthHandlerBasic::Factory factory; + SSLInfo null_ssl_info; scoped_ptr<HttpAuthHandler> basic; EXPECT_EQ(OK, factory.CreateAuthHandlerFromString( - tests[0].challenge, HttpAuth::AUTH_SERVER, origin, - BoundNetLog(), &basic)); + tests[0].challenge, HttpAuth::AUTH_SERVER, null_ssl_info, + origin, BoundNetLog(), &basic)); for (size_t i = 0; i < arraysize(tests); ++i) { std::string challenge(tests[i].challenge); @@ -186,9 +190,11 @@ TEST(HttpAuthHandlerBasicTest, InitFromChallenge) { GURL origin("http://www.example.com"); for (size_t i = 0; i < arraysize(tests); ++i) { std::string challenge = tests[i].challenge; + SSLInfo null_ssl_info; scoped_ptr<HttpAuthHandler> basic; int rv = factory.CreateAuthHandlerFromString( - challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog(), &basic); + challenge, HttpAuth::AUTH_SERVER, null_ssl_info, origin, BoundNetLog(), + &basic); EXPECT_EQ(tests[i].expected_rv, rv); if (rv == OK) EXPECT_EQ(tests[i].expected_realm, basic->realm()); diff --git a/net/http/http_auth_handler_digest.cc b/net/http/http_auth_handler_digest.cc index 3590b8e..eb03ad7 100644 --- a/net/http/http_auth_handler_digest.cc +++ b/net/http/http_auth_handler_digest.cc @@ -93,6 +93,7 @@ void HttpAuthHandlerDigest::Factory::set_nonce_generator( int HttpAuthHandlerDigest::Factory::CreateAuthHandler( HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int digest_nonce_count, @@ -102,7 +103,8 @@ int HttpAuthHandlerDigest::Factory::CreateAuthHandler( // method and only constructing when valid. scoped_ptr<HttpAuthHandler> tmp_handler( new HttpAuthHandlerDigest(digest_nonce_count, nonce_generator_.get())); - if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) + if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin, + net_log)) return ERR_INVALID_RESPONSE; handler->swap(tmp_handler); return OK; @@ -135,7 +137,8 @@ HttpAuth::AuthorizationResult HttpAuthHandlerDigest::HandleAnotherChallenge( HttpAuth::AUTHORIZATION_RESULT_REJECT; } -bool HttpAuthHandlerDigest::Init(HttpAuthChallengeTokenizer* challenge) { +bool HttpAuthHandlerDigest::Init(HttpAuthChallengeTokenizer* challenge, + const SSLInfo& ssl_info) { return ParseChallenge(challenge); } diff --git a/net/http/http_auth_handler_digest.h b/net/http/http_auth_handler_digest.h index 27cdfcd..2b98946 100644 --- a/net/http/http_auth_handler_digest.h +++ b/net/http/http_auth_handler_digest.h @@ -67,6 +67,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerDigest : public HttpAuthHandler { int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int digest_nonce_count, @@ -81,7 +82,8 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerDigest : public HttpAuthHandler { HttpAuthChallengeTokenizer* challenge) override; protected: - bool Init(HttpAuthChallengeTokenizer* challenge) override; + bool Init(HttpAuthChallengeTokenizer* challenge, + const SSLInfo& ssl_info) override; int GenerateAuthTokenImpl(const AuthCredentials* credentials, const HttpRequestInfo* request, diff --git a/net/http/http_auth_handler_digest_unittest.cc b/net/http/http_auth_handler_digest_unittest.cc index 89f3010..92e3455 100644 --- a/net/http/http_auth_handler_digest_unittest.cc +++ b/net/http/http_auth_handler_digest_unittest.cc @@ -11,6 +11,7 @@ #include "net/http/http_auth_challenge_tokenizer.h" #include "net/http/http_auth_handler_digest.h" #include "net/http/http_request_info.h" +#include "net/ssl/ssl_info.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -52,9 +53,11 @@ bool RespondToChallenge(HttpAuth::Target target, scoped_ptr<HttpAuthHandler> handler; // Create a handler for a particular challenge. + SSLInfo null_ssl_info; GURL url_origin(target == HttpAuth::AUTH_SERVER ? request_url : proxy_name); int rv_create = factory->CreateAuthHandlerFromString( - challenge, target, url_origin.GetOrigin(), BoundNetLog(), &handler); + challenge, target, null_ssl_info, url_origin.GetOrigin(), BoundNetLog(), + &handler); if (rv_create != OK || handler.get() == NULL) { ADD_FAILURE() << "Unable to create auth handler."; return false; @@ -351,12 +354,11 @@ TEST(HttpAuthHandlerDigestTest, ParseChallenge) { scoped_ptr<HttpAuthHandlerDigest::Factory> factory( new HttpAuthHandlerDigest::Factory()); for (size_t i = 0; i < arraysize(tests); ++i) { + SSLInfo null_ssl_info; scoped_ptr<HttpAuthHandler> handler; - int rv = factory->CreateAuthHandlerFromString(tests[i].challenge, - HttpAuth::AUTH_SERVER, - origin, - BoundNetLog(), - &handler); + int rv = factory->CreateAuthHandlerFromString( + tests[i].challenge, HttpAuth::AUTH_SERVER, null_ssl_info, origin, + BoundNetLog(), &handler); if (tests[i].parsed_success) { EXPECT_EQ(OK, rv); } else { @@ -516,12 +518,11 @@ TEST(HttpAuthHandlerDigestTest, AssembleCredentials) { scoped_ptr<HttpAuthHandlerDigest::Factory> factory( new HttpAuthHandlerDigest::Factory()); for (size_t i = 0; i < arraysize(tests); ++i) { + SSLInfo null_ssl_info; scoped_ptr<HttpAuthHandler> handler; - int rv = factory->CreateAuthHandlerFromString(tests[i].challenge, - HttpAuth::AUTH_SERVER, - origin, - BoundNetLog(), - &handler); + int rv = factory->CreateAuthHandlerFromString( + tests[i].challenge, HttpAuth::AUTH_SERVER, null_ssl_info, origin, + BoundNetLog(), &handler); EXPECT_EQ(OK, rv); ASSERT_TRUE(handler != NULL); @@ -547,9 +548,10 @@ TEST(HttpAuthHandlerDigest, HandleAnotherChallenge) { std::string default_challenge = "Digest realm=\"Oblivion\", nonce=\"nonce-value\""; GURL origin("intranet.google.com"); + SSLInfo null_ssl_info; int rv = factory->CreateAuthHandlerFromString( - default_challenge, HttpAuth::AUTH_SERVER, origin, BoundNetLog(), - &handler); + default_challenge, HttpAuth::AUTH_SERVER, null_ssl_info, origin, + BoundNetLog(), &handler); EXPECT_EQ(OK, rv); ASSERT_TRUE(handler.get() != NULL); HttpAuthChallengeTokenizer tok_default(default_challenge.begin(), diff --git a/net/http/http_auth_handler_factory.cc b/net/http/http_auth_handler_factory.cc index c03792f..af682e1 100644 --- a/net/http/http_auth_handler_factory.cc +++ b/net/http/http_auth_handler_factory.cc @@ -14,6 +14,7 @@ #include "net/http/http_auth_handler_ntlm.h" #include "net/http/http_auth_preferences.h" #include "net/http/http_auth_scheme.h" +#include "net/ssl/ssl_info.h" #if defined(USE_KERBEROS) #include "net/http/http_auth_handler_negotiate.h" @@ -24,12 +25,13 @@ namespace net { int HttpAuthHandlerFactory::CreateAuthHandlerFromString( const std::string& challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, const BoundNetLog& net_log, scoped_ptr<HttpAuthHandler>* handler) { HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end()); - return CreateAuthHandler(&props, target, origin, CREATE_CHALLENGE, 1, - net_log, handler); + return CreateAuthHandler(&props, target, ssl_info, origin, CREATE_CHALLENGE, + 1, net_log, handler); } int HttpAuthHandlerFactory::CreatePreemptiveAuthHandlerFromString( @@ -40,8 +42,10 @@ int HttpAuthHandlerFactory::CreatePreemptiveAuthHandlerFromString( const BoundNetLog& net_log, scoped_ptr<HttpAuthHandler>* handler) { HttpAuthChallengeTokenizer props(challenge.begin(), challenge.end()); - return CreateAuthHandler(&props, target, origin, CREATE_PREEMPTIVE, - digest_nonce_count, net_log, handler); + SSLInfo null_ssl_info; + return CreateAuthHandler(&props, target, null_ssl_info, origin, + CREATE_PREEMPTIVE, digest_nonce_count, net_log, + handler); } namespace { @@ -161,6 +165,7 @@ HttpAuthHandlerRegistryFactory::Create(const HttpAuthPreferences* prefs, int HttpAuthHandlerRegistryFactory::CreateAuthHandler( HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int digest_nonce_count, @@ -178,8 +183,9 @@ int HttpAuthHandlerRegistryFactory::CreateAuthHandler( return ERR_UNSUPPORTED_AUTH_SCHEME; } DCHECK(it->second); - return it->second->CreateAuthHandler(challenge, target, origin, reason, - digest_nonce_count, net_log, handler); + return it->second->CreateAuthHandler(challenge, target, ssl_info, origin, + reason, digest_nonce_count, net_log, + handler); } } // namespace net diff --git a/net/http/http_auth_handler_factory.h b/net/http/http_auth_handler_factory.h index a98f9d7..60ec3f9 100644 --- a/net/http/http_auth_handler_factory.h +++ b/net/http/http_auth_handler_factory.h @@ -73,6 +73,9 @@ class NET_EXPORT HttpAuthHandlerFactory { // scheme, and indicates the number of handlers generated for a particular // server nonce challenge. // + // |ssl_info| is valid if the authentication session is being established over + // a secure connection. + // // For the NTLM and Negotiate handlers: // If |origin| does not match the authentication method's filters for // the specified |target|, ERR_INVALID_AUTH_CREDENTIALS is returned. @@ -81,6 +84,7 @@ class NET_EXPORT HttpAuthHandlerFactory { // |*challenge| should not be reused after a call to |CreateAuthHandler()|, virtual int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason create_reason, int digest_nonce_count, @@ -94,6 +98,7 @@ class NET_EXPORT HttpAuthHandlerFactory { // more details on return values. int CreateAuthHandlerFromString(const std::string& challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, const BoundNetLog& net_log, scoped_ptr<HttpAuthHandler>* handler); @@ -177,6 +182,7 @@ class NET_EXPORT HttpAuthHandlerRegistryFactory // based on the first token in |challenge|. int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int digest_nonce_count, diff --git a/net/http/http_auth_handler_factory_unittest.cc b/net/http/http_auth_handler_factory_unittest.cc index b73e47b..6d85121 100644 --- a/net/http/http_auth_handler_factory_unittest.cc +++ b/net/http/http_auth_handler_factory_unittest.cc @@ -10,6 +10,7 @@ #include "net/http/http_auth_scheme.h" #include "net/http/mock_allow_http_auth_preferences.h" #include "net/http/url_security_manager.h" +#include "net/ssl/ssl_info.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -24,6 +25,7 @@ class MockHttpAuthHandlerFactory : public HttpAuthHandlerFactory { int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int nonce_count, @@ -40,6 +42,7 @@ class MockHttpAuthHandlerFactory : public HttpAuthHandlerFactory { } // namespace TEST(HttpAuthHandlerFactoryTest, RegistryFactory) { + SSLInfo null_ssl_info; HttpAuthHandlerRegistryFactory registry_factory; GURL gurl("www.google.com"); const int kBasicReturnCode = ERR_INVALID_SPDY_STREAM; @@ -59,42 +62,43 @@ TEST(HttpAuthHandlerFactoryTest, RegistryFactory) { // No schemes should be supported in the beginning. EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, registry_factory.CreateAuthHandlerFromString( - "Basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler)); + "Basic", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, + BoundNetLog(), &handler)); // Test what happens with a single scheme. registry_factory.RegisterSchemeFactory("Basic", mock_factory_basic); - EXPECT_EQ(kBasicReturnCode, - registry_factory.CreateAuthHandlerFromString( - "Basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler)); + EXPECT_EQ(kBasicReturnCode, registry_factory.CreateAuthHandlerFromString( + "Basic", HttpAuth::AUTH_SERVER, null_ssl_info, + gurl, BoundNetLog(), &handler)); EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, registry_factory.CreateAuthHandlerFromString( - "Digest", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), - &handler)); + "Digest", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, + BoundNetLog(), &handler)); // Test multiple schemes registry_factory.RegisterSchemeFactory("Digest", mock_factory_digest); - EXPECT_EQ(kBasicReturnCode, - registry_factory.CreateAuthHandlerFromString( - "Basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler)); + EXPECT_EQ(kBasicReturnCode, registry_factory.CreateAuthHandlerFromString( + "Basic", HttpAuth::AUTH_SERVER, null_ssl_info, + gurl, BoundNetLog(), &handler)); EXPECT_EQ(kDigestReturnCode, registry_factory.CreateAuthHandlerFromString( - "Digest", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), - &handler)); + "Digest", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, + BoundNetLog(), &handler)); // Test case-insensitivity - EXPECT_EQ(kBasicReturnCode, - registry_factory.CreateAuthHandlerFromString( - "basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler)); + EXPECT_EQ(kBasicReturnCode, registry_factory.CreateAuthHandlerFromString( + "basic", HttpAuth::AUTH_SERVER, null_ssl_info, + gurl, BoundNetLog(), &handler)); // Test replacement of existing auth scheme registry_factory.RegisterSchemeFactory("Digest", mock_factory_digest_replace); - EXPECT_EQ(kBasicReturnCode, - registry_factory.CreateAuthHandlerFromString( - "Basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler)); + EXPECT_EQ(kBasicReturnCode, registry_factory.CreateAuthHandlerFromString( + "Basic", HttpAuth::AUTH_SERVER, null_ssl_info, + gurl, BoundNetLog(), &handler)); EXPECT_EQ(kDigestReturnCodeReplace, registry_factory.CreateAuthHandlerFromString( - "Digest", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), - &handler)); + "Digest", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, + BoundNetLog(), &handler)); } TEST(HttpAuthHandlerFactoryTest, DefaultFactory) { @@ -106,14 +110,12 @@ TEST(HttpAuthHandlerFactoryTest, DefaultFactory) { &http_auth_preferences); GURL server_origin("http://www.example.com"); GURL proxy_origin("http://cache.example.com:3128"); + SSLInfo null_ssl_info; { scoped_ptr<HttpAuthHandler> handler; int rv = http_auth_handler_factory->CreateAuthHandlerFromString( - "Basic realm=\"FooBar\"", - HttpAuth::AUTH_SERVER, - server_origin, - BoundNetLog(), - &handler); + "Basic realm=\"FooBar\"", HttpAuth::AUTH_SERVER, null_ssl_info, + server_origin, BoundNetLog(), &handler); EXPECT_EQ(OK, rv); ASSERT_FALSE(handler.get() == NULL); EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, handler->auth_scheme()); @@ -125,22 +127,16 @@ TEST(HttpAuthHandlerFactoryTest, DefaultFactory) { { scoped_ptr<HttpAuthHandler> handler; int rv = http_auth_handler_factory->CreateAuthHandlerFromString( - "UNSUPPORTED realm=\"FooBar\"", - HttpAuth::AUTH_SERVER, - server_origin, - BoundNetLog(), - &handler); + "UNSUPPORTED realm=\"FooBar\"", HttpAuth::AUTH_SERVER, null_ssl_info, + server_origin, BoundNetLog(), &handler); EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, rv); EXPECT_TRUE(handler.get() == NULL); } { scoped_ptr<HttpAuthHandler> handler; int rv = http_auth_handler_factory->CreateAuthHandlerFromString( - "Digest realm=\"FooBar\", nonce=\"xyz\"", - HttpAuth::AUTH_PROXY, - proxy_origin, - BoundNetLog(), - &handler); + "Digest realm=\"FooBar\", nonce=\"xyz\"", HttpAuth::AUTH_PROXY, + null_ssl_info, proxy_origin, BoundNetLog(), &handler); EXPECT_EQ(OK, rv); ASSERT_FALSE(handler.get() == NULL); EXPECT_EQ(HttpAuth::AUTH_SCHEME_DIGEST, handler->auth_scheme()); @@ -152,11 +148,8 @@ TEST(HttpAuthHandlerFactoryTest, DefaultFactory) { { scoped_ptr<HttpAuthHandler> handler; int rv = http_auth_handler_factory->CreateAuthHandlerFromString( - "NTLM", - HttpAuth::AUTH_SERVER, - server_origin, - BoundNetLog(), - &handler); + "NTLM", HttpAuth::AUTH_SERVER, null_ssl_info, server_origin, + BoundNetLog(), &handler); EXPECT_EQ(OK, rv); ASSERT_FALSE(handler.get() == NULL); EXPECT_EQ(HttpAuth::AUTH_SCHEME_NTLM, handler->auth_scheme()); @@ -168,11 +161,8 @@ TEST(HttpAuthHandlerFactoryTest, DefaultFactory) { { scoped_ptr<HttpAuthHandler> handler; int rv = http_auth_handler_factory->CreateAuthHandlerFromString( - "Negotiate", - HttpAuth::AUTH_SERVER, - server_origin, - BoundNetLog(), - &handler); + "Negotiate", HttpAuth::AUTH_SERVER, null_ssl_info, server_origin, + BoundNetLog(), &handler); // Note the default factory doesn't support Kerberos on Android #if defined(USE_KERBEROS) && !defined(OS_ANDROID) EXPECT_EQ(OK, rv); diff --git a/net/http/http_auth_handler_mock.cc b/net/http/http_auth_handler_mock.cc index 04a09e4..513cbb6 100644 --- a/net/http/http_auth_handler_mock.cc +++ b/net/http/http_auth_handler_mock.cc @@ -101,7 +101,8 @@ bool HttpAuthHandlerMock::AllowsExplicitCredentials() { return allows_explicit_credentials_; } -bool HttpAuthHandlerMock::Init(HttpAuthChallengeTokenizer* challenge) { +bool HttpAuthHandlerMock::Init(HttpAuthChallengeTokenizer* challenge, + const SSLInfo& ssl_info) { auth_scheme_ = HttpAuth::AUTH_SCHEME_MOCK; score_ = 1; properties_ = connection_based_ ? IS_CONNECTION_BASED : 0; @@ -167,6 +168,7 @@ void HttpAuthHandlerMock::Factory::AddMockHandler( int HttpAuthHandlerMock::Factory::CreateAuthHandler( HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int nonce_count, @@ -178,7 +180,8 @@ int HttpAuthHandlerMock::Factory::CreateAuthHandler( std::vector<scoped_ptr<HttpAuthHandler>>& handlers = handlers_[target]; handlers.erase(handlers.begin()); if (do_init_from_challenge_ && - !tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) + !tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin, + net_log)) return ERR_INVALID_RESPONSE; handler->swap(tmp_handler); return OK; diff --git a/net/http/http_auth_handler_mock.h b/net/http/http_auth_handler_mock.h index 2677526..41aaa2d 100644 --- a/net/http/http_auth_handler_mock.h +++ b/net/http/http_auth_handler_mock.h @@ -45,6 +45,7 @@ class HttpAuthHandlerMock : public HttpAuthHandler { // HttpAuthHandlerFactory: int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int nonce_count, @@ -95,7 +96,8 @@ class HttpAuthHandlerMock : public HttpAuthHandler { bool AllowsExplicitCredentials() override; protected: - bool Init(HttpAuthChallengeTokenizer* challenge) override; + bool Init(HttpAuthChallengeTokenizer* challenge, + const SSLInfo& ssl_info) override; int GenerateAuthTokenImpl(const AuthCredentials* credentials, const HttpRequestInfo* request, diff --git a/net/http/http_auth_handler_negotiate.cc b/net/http/http_auth_handler_negotiate.cc index 864a703..1ca6d54 100644 --- a/net/http/http_auth_handler_negotiate.cc +++ b/net/http/http_auth_handler_negotiate.cc @@ -7,16 +7,39 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "base/values.h" #include "net/base/address_family.h" #include "net/base/net_errors.h" +#include "net/cert/x509_util.h" #include "net/dns/host_resolver.h" #include "net/dns/single_request_host_resolver.h" #include "net/http/http_auth_filter.h" #include "net/http/http_auth_preferences.h" +#include "net/log/net_log.h" +#include "net/ssl/ssl_info.h" namespace net { +namespace { + +scoped_ptr<base::Value> NetLogParameterChannelBindings( + const std::string& channel_binding_token, + NetLogCaptureMode capture_mode) { + scoped_ptr<base::DictionaryValue> dict; + if (!capture_mode.include_socket_bytes()) + return std::move(dict); + + dict.reset(new base::DictionaryValue()); + dict->SetString("token", base::HexEncode(channel_binding_token.data(), + channel_binding_token.size())); + return std::move(dict); +} + +} // namespace + HttpAuthHandlerNegotiate::Factory::Factory() : resolver_(NULL), #if defined(OS_WIN) @@ -36,6 +59,7 @@ void HttpAuthHandlerNegotiate::Factory::set_host_resolver( int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler( HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int digest_nonce_count, @@ -78,7 +102,8 @@ int HttpAuthHandlerNegotiate::Factory::CreateAuthHandler( scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNegotiate( auth_library_.get(), http_auth_preferences(), resolver_)); #endif - if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) + if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin, + net_log)) return ERR_INVALID_RESPONSE; handler->swap(tmp_handler); return OK; @@ -185,7 +210,8 @@ bool HttpAuthHandlerNegotiate::AllowsExplicitCredentials() { // The Negotiate challenge header looks like: // WWW-Authenticate: NEGOTIATE auth-data -bool HttpAuthHandlerNegotiate::Init(HttpAuthChallengeTokenizer* challenge) { +bool HttpAuthHandlerNegotiate::Init(HttpAuthChallengeTokenizer* challenge, + const SSLInfo& ssl_info) { #if defined(OS_POSIX) if (!auth_system_.Init()) { VLOG(1) << "can't initialize GSSAPI library"; @@ -203,9 +229,21 @@ bool HttpAuthHandlerNegotiate::Init(HttpAuthChallengeTokenizer* challenge) { auth_scheme_ = HttpAuth::AUTH_SCHEME_NEGOTIATE; score_ = 4; properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED; + HttpAuth::AuthorizationResult auth_result = auth_system_.ParseChallenge(challenge); - return (auth_result == HttpAuth::AUTHORIZATION_RESULT_ACCEPT); + if (auth_result != HttpAuth::AUTHORIZATION_RESULT_ACCEPT) + return false; + + // Try to extract channel bindings. + if (ssl_info.is_valid()) + x509_util::GetTLSServerEndPointChannelBinding(*ssl_info.cert, + &channel_bindings_); + if (!channel_bindings_.empty()) + net_log_.AddEvent( + NetLog::TYPE_AUTH_CHANNEL_BINDINGS, + base::Bind(&NetLogParameterChannelBindings, channel_bindings_)); + return true; } int HttpAuthHandlerNegotiate::GenerateAuthTokenImpl( @@ -319,7 +357,7 @@ int HttpAuthHandlerNegotiate::DoGenerateAuthToken() { next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE; AuthCredentials* credentials = has_credentials_ ? &credentials_ : NULL; return auth_system_.GenerateAuthToken( - credentials, spn_, auth_token_, + credentials, spn_, channel_bindings_, auth_token_, base::Bind(&HttpAuthHandlerNegotiate::OnIOComplete, base::Unretained(this))); } diff --git a/net/http/http_auth_handler_negotiate.h b/net/http/http_auth_handler_negotiate.h index 1d74431..abdbe93 100644 --- a/net/http/http_auth_handler_negotiate.h +++ b/net/http/http_auth_handler_negotiate.h @@ -63,6 +63,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNegotiate : public HttpAuthHandler { // HttpAuthHandlerFactory overrides int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int digest_nonce_count, @@ -104,7 +105,8 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNegotiate : public HttpAuthHandler { bool AllowsExplicitCredentials() override; protected: - bool Init(HttpAuthChallengeTokenizer* challenge) override; + bool Init(HttpAuthChallengeTokenizer* challenge, + const SSLInfo& ssl_info) override; int GenerateAuthTokenImpl(const AuthCredentials* credentials, const HttpRequestInfo* request, @@ -142,6 +144,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNegotiate : public HttpAuthHandler { bool has_credentials_; AuthCredentials credentials_; std::string spn_; + std::string channel_bindings_; // Things which vary each round. CompletionCallback callback_; diff --git a/net/http/http_auth_handler_negotiate_unittest.cc b/net/http/http_auth_handler_negotiate_unittest.cc index fd46716..57a7b7e 100644 --- a/net/http/http_auth_handler_negotiate_unittest.cc +++ b/net/http/http_auth_handler_negotiate_unittest.cc @@ -13,6 +13,10 @@ #include "net/dns/mock_host_resolver.h" #include "net/http/http_request_info.h" #include "net/http/mock_allow_http_auth_preferences.h" +#include "net/ssl/ssl_info.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + #if defined(OS_ANDROID) #include "net/android/dummy_spnego_authenticator.h" #elif defined(OS_WIN) @@ -20,8 +24,6 @@ #elif defined(OS_POSIX) #include "net/http/mock_gssapi_library_posix.h" #endif -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/platform_test.h" namespace net { @@ -189,10 +191,11 @@ class HttpAuthHandlerNegotiateTest : public PlatformTest { #endif // defined(OS_POSIX) - int CreateHandler(bool disable_cname_lookup, bool use_port, - bool synchronous_resolve_mode, - const std::string& url_string, - scoped_ptr<HttpAuthHandlerNegotiate>* handler) { + int CreateHandler(bool disable_cname_lookup, + bool use_port, + bool synchronous_resolve_mode, + const std::string& url_string, + scoped_ptr<HttpAuthHandlerNegotiate>* handler) { http_auth_preferences_->set_negotiate_disable_cname_lookup( disable_cname_lookup); http_auth_preferences_->set_negotiate_enable_port(use_port); @@ -205,11 +208,10 @@ class HttpAuthHandlerNegotiateTest : public PlatformTest { // after creating the handler, and make sure that generic_handler // no longer holds on to the HttpAuthHandlerNegotiate object. scoped_ptr<HttpAuthHandler> generic_handler; - int rv = factory_->CreateAuthHandlerFromString("Negotiate", - HttpAuth::AUTH_SERVER, - gurl, - BoundNetLog(), - &generic_handler); + SSLInfo null_ssl_info; + int rv = factory_->CreateAuthHandlerFromString( + "Negotiate", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, BoundNetLog(), + &generic_handler); if (rv != OK) return rv; HttpAuthHandlerNegotiate* negotiate_handler = diff --git a/net/http/http_auth_handler_ntlm.cc b/net/http/http_auth_handler_ntlm.cc index bc65807..cecf3b2 100644 --- a/net/http/http_auth_handler_ntlm.cc +++ b/net/http/http_auth_handler_ntlm.cc @@ -12,8 +12,10 @@ #include "base/strings/utf_string_conversions.h" #include "net/base/net_errors.h" #include "net/base/url_util.h" +#include "net/cert/x509_util.h" #include "net/http/http_auth_challenge_tokenizer.h" #include "net/http/http_auth_scheme.h" +#include "net/http/http_response_info.h" namespace net { @@ -22,11 +24,16 @@ HttpAuth::AuthorizationResult HttpAuthHandlerNTLM::HandleAnotherChallenge( return ParseChallenge(challenge, false); } -bool HttpAuthHandlerNTLM::Init(HttpAuthChallengeTokenizer* tok) { +bool HttpAuthHandlerNTLM::Init(HttpAuthChallengeTokenizer* tok, + const SSLInfo& ssl_info) { auth_scheme_ = HttpAuth::AUTH_SCHEME_NTLM; score_ = 3; properties_ = ENCRYPTS_IDENTITY | IS_CONNECTION_BASED; + if (ssl_info.is_valid()) + x509_util::GetTLSServerEndPointChannelBinding(*ssl_info.cert, + &channel_bindings_); + return ParseChallenge(tok, true) == HttpAuth::AUTHORIZATION_RESULT_ACCEPT; } @@ -35,7 +42,7 @@ int HttpAuthHandlerNTLM::GenerateAuthTokenImpl( const CompletionCallback& callback, std::string* auth_token) { #if defined(NTLM_SSPI) return auth_sspi_.GenerateAuthToken(credentials, CreateSPN(origin_), - auth_token, callback); + channel_bindings_, auth_token, callback); #else // !defined(NTLM_SSPI) // TODO(cbentzel): Shouldn't be hitting this case. if (!credentials) { diff --git a/net/http/http_auth_handler_ntlm.h b/net/http/http_auth_handler_ntlm.h index d71b498..58e2993 100644 --- a/net/http/http_auth_handler_ntlm.h +++ b/net/http/http_auth_handler_ntlm.h @@ -45,6 +45,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler { int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int digest_nonce_count, @@ -117,7 +118,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler { // It does nothing in the portable implementation. int InitializeBeforeFirstChallenge(); - bool Init(HttpAuthChallengeTokenizer* tok) override; + bool Init(HttpAuthChallengeTokenizer* tok, const SSLInfo& ssl_info) override; int GenerateAuthTokenImpl(const AuthCredentials* credentials, const HttpRequestInfo* request, @@ -159,6 +160,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler { base::string16 domain_; AuthCredentials credentials_; + std::string channel_bindings_; // The base64-encoded string following "NTLM" in the "WWW-Authenticate" or // "Proxy-Authenticate" response header. diff --git a/net/http/http_auth_handler_ntlm_portable.cc b/net/http/http_auth_handler_ntlm_portable.cc index baec351..b5a4882 100644 --- a/net/http/http_auth_handler_ntlm_portable.cc +++ b/net/http/http_auth_handler_ntlm_portable.cc @@ -714,6 +714,7 @@ int HttpAuthHandlerNTLM::GetNextToken(const void* in_token, int HttpAuthHandlerNTLM::Factory::CreateAuthHandler( HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int digest_nonce_count, @@ -726,7 +727,8 @@ int HttpAuthHandlerNTLM::Factory::CreateAuthHandler( // NOTE: Default credentials are not supported for the portable implementation // of NTLM. scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNTLM); - if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) + if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin, + net_log)) return ERR_INVALID_RESPONSE; handler->swap(tmp_handler); return OK; diff --git a/net/http/http_auth_handler_ntlm_win.cc b/net/http/http_auth_handler_ntlm_win.cc index 58e563b..ed4cdf6 100644 --- a/net/http/http_auth_handler_ntlm_win.cc +++ b/net/http/http_auth_handler_ntlm_win.cc @@ -52,6 +52,7 @@ HttpAuthHandlerNTLM::Factory::~Factory() { int HttpAuthHandlerNTLM::Factory::CreateAuthHandler( HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int digest_nonce_count, @@ -71,7 +72,8 @@ int HttpAuthHandlerNTLM::Factory::CreateAuthHandler( // method and only constructing when valid. scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNTLM( sspi_library_.get(), max_token_length_, http_auth_preferences())); - if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log)) + if (!tmp_handler->InitFromChallenge(challenge, target, ssl_info, origin, + net_log)) return ERR_INVALID_RESPONSE; handler->swap(tmp_handler); return OK; diff --git a/net/http/http_auth_handler_unittest.cc b/net/http/http_auth_handler_unittest.cc index 5757bb6..1bb384f 100644 --- a/net/http/http_auth_handler_unittest.cc +++ b/net/http/http_auth_handler_unittest.cc @@ -14,6 +14,7 @@ #include "net/log/test_net_log.h" #include "net/log/test_net_log_entry.h" #include "net/log/test_net_log_util.h" +#include "net/ssl/ssl_info.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -43,7 +44,8 @@ TEST(HttpAuthHandlerTest, NetLog) { BoundNetLog bound_net_log( BoundNetLog::Make(&test_net_log, NetLog::SOURCE_NONE)); - mock_handler.InitFromChallenge(&tokenizer, target, + SSLInfo empty_ssl_info; + mock_handler.InitFromChallenge(&tokenizer, target, empty_ssl_info, origin, bound_net_log); mock_handler.SetGenerateExpectation(async, rv); mock_handler.GenerateAuthToken(&credentials, &request, diff --git a/net/http/http_auth_sspi_win.cc b/net/http/http_auth_sspi_win.cc index f59ce4d..a2929fb 100644 --- a/net/http/http_auth_sspi_win.cc +++ b/net/http/http_auth_sspi_win.cc @@ -292,6 +292,7 @@ HttpAuth::AuthorizationResult HttpAuthSSPI::ParseChallenge( int HttpAuthSSPI::GenerateAuthToken(const AuthCredentials* credentials, const std::string& spn, + const std::string& channel_bindings, std::string* auth_token, const CompletionCallback& /*callback*/) { // Initial challenge. @@ -305,12 +306,9 @@ int HttpAuthSSPI::GenerateAuthToken(const AuthCredentials* credentials, void* out_buf; int out_buf_len; int rv = GetNextSecurityToken( - spn, - static_cast<void *>(const_cast<char *>( - decoded_server_auth_token_.c_str())), - decoded_server_auth_token_.length(), - &out_buf, - &out_buf_len); + spn, channel_bindings, + static_cast<void*>(const_cast<char*>(decoded_server_auth_token_.c_str())), + decoded_server_auth_token_.length(), &out_buf, &out_buf_len); if (rv != OK) return rv; @@ -344,27 +342,27 @@ int HttpAuthSSPI::OnFirstRound(const AuthCredentials* credentials) { return rv; } -int HttpAuthSSPI::GetNextSecurityToken( - const std::string& spn, - const void* in_token, - int in_token_len, - void** out_token, - int* out_token_len) { - CtxtHandle* ctxt_ptr; +int HttpAuthSSPI::GetNextSecurityToken(const std::string& spn, + const std::string& channel_bindings, + const void* in_token, + int in_token_len, + void** out_token, + int* out_token_len) { + CtxtHandle* ctxt_ptr = nullptr; SecBufferDesc in_buffer_desc, out_buffer_desc; - SecBufferDesc* in_buffer_desc_ptr; - SecBuffer in_buffer, out_buffer; + SecBufferDesc* in_buffer_desc_ptr = nullptr; + SecBuffer in_buffers[2], out_buffer; + in_buffer_desc.ulVersion = SECBUFFER_VERSION; + in_buffer_desc.cBuffers = 0; + in_buffer_desc.pBuffers = in_buffers; if (in_token_len > 0) { // Prepare input buffer. - in_buffer_desc.ulVersion = SECBUFFER_VERSION; - in_buffer_desc.cBuffers = 1; - in_buffer_desc.pBuffers = &in_buffer; - in_buffer.BufferType = SECBUFFER_TOKEN; - in_buffer.cbBuffer = in_token_len; - in_buffer.pvBuffer = const_cast<void*>(in_token); + SecBuffer& sec_buffer = in_buffers[in_buffer_desc.cBuffers++]; + sec_buffer.BufferType = SECBUFFER_TOKEN; + sec_buffer.cbBuffer = in_token_len; + sec_buffer.pvBuffer = const_cast<void*>(in_token); ctxt_ptr = &ctxt_; - in_buffer_desc_ptr = &in_buffer_desc; } else { // If there is no input token, then we are starting a new authentication // sequence. If we have already initialized our security context, then @@ -373,10 +371,33 @@ int HttpAuthSSPI::GetNextSecurityToken( NOTREACHED(); return ERR_UNEXPECTED; } - ctxt_ptr = NULL; - in_buffer_desc_ptr = NULL; } + std::vector<char> sec_channel_bindings_buffer; + if (!channel_bindings.empty()) { + sec_channel_bindings_buffer.reserve(sizeof(SEC_CHANNEL_BINDINGS) + + channel_bindings.size()); + sec_channel_bindings_buffer.resize(sizeof(SEC_CHANNEL_BINDINGS)); + SEC_CHANNEL_BINDINGS* bindings_desc = + reinterpret_cast<SEC_CHANNEL_BINDINGS*>( + &sec_channel_bindings_buffer.front()); + bindings_desc->cbApplicationDataLength = channel_bindings.size(); + bindings_desc->dwApplicationDataOffset = sizeof(SEC_CHANNEL_BINDINGS); + sec_channel_bindings_buffer.insert(sec_channel_bindings_buffer.end(), + channel_bindings.begin(), + channel_bindings.end()); + DCHECK_EQ(sizeof(SEC_CHANNEL_BINDINGS) + channel_bindings.size(), + sec_channel_bindings_buffer.size()); + + SecBuffer& sec_buffer = in_buffers[in_buffer_desc.cBuffers++]; + sec_buffer.BufferType = SECBUFFER_CHANNEL_BINDINGS; + sec_buffer.cbBuffer = sec_channel_bindings_buffer.size(); + sec_buffer.pvBuffer = &sec_channel_bindings_buffer.front(); + } + + if (in_buffer_desc.cBuffers > 0) + in_buffer_desc_ptr = &in_buffer_desc; + // Prepare output buffer. out_buffer_desc.ulVersion = SECBUFFER_VERSION; out_buffer_desc.cBuffers = 1; @@ -397,18 +418,18 @@ int HttpAuthSSPI::GetNextSecurityToken( DWORD context_attribute; base::string16 spn16 = base::ASCIIToUTF16(spn); SECURITY_STATUS status = library_->InitializeSecurityContext( - &cred_, // phCredential - ctxt_ptr, // phContext + &cred_, // phCredential + ctxt_ptr, // phContext const_cast<base::char16*>(spn16.c_str()), // pszTargetName - context_flags, // fContextReq - 0, // Reserved1 (must be 0) - SECURITY_NATIVE_DREP, // TargetDataRep - in_buffer_desc_ptr, // pInput - 0, // Reserved2 (must be 0) - &ctxt_, // phNewContext - &out_buffer_desc, // pOutput - &context_attribute, // pfContextAttr - NULL); // ptsExpiry + context_flags, // fContextReq + 0, // Reserved1 (must be 0) + SECURITY_NATIVE_DREP, // TargetDataRep + in_buffer_desc_ptr, // pInput + 0, // Reserved2 (must be 0) + &ctxt_, // phNewContext + &out_buffer_desc, // pOutput + &context_attribute, // pfContextAttr + nullptr); // ptsExpiry int rv = MapInitializeSecurityContextStatusToError(status); if (rv != OK) { ResetSecurityContext(); diff --git a/net/http/http_auth_sspi_win.h b/net/http/http_auth_sspi_win.h index 1d524fa..32f30dd 100644 --- a/net/http/http_auth_sspi_win.h +++ b/net/http/http_auth_sspi_win.h @@ -146,6 +146,7 @@ class NET_EXPORT_PRIVATE HttpAuthSSPI { // credentials are used instead. int GenerateAuthToken(const AuthCredentials* credentials, const std::string& spn, + const std::string& channel_bindings, std::string* auth_token, const CompletionCallback& callback); @@ -157,12 +158,12 @@ class NET_EXPORT_PRIVATE HttpAuthSSPI { private: int OnFirstRound(const AuthCredentials* credentials); - int GetNextSecurityToken( - const std::string& spn, - const void* in_token, - int in_token_len, - void** out_token, - int* out_token_len); + int GetNextSecurityToken(const std::string& spn, + const std::string& channing_bindings, + const void* in_token, + int in_token_len, + void** out_token, + int* out_token_len); void ResetSecurityContext(); diff --git a/net/http/http_auth_sspi_win_unittest.cc b/net/http/http_auth_sspi_win_unittest.cc index 0bb90ff..c284173 100644 --- a/net/http/http_auth_sspi_win_unittest.cc +++ b/net/http/http_auth_sspi_win_unittest.cc @@ -89,7 +89,7 @@ TEST(HttpAuthSSPITest, ParseChallenge_TwoRounds) { // Generate an auth token and create another thing. std::string auth_token; EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", - &auth_token, + std::string(), &auth_token, base::Bind(&UnexpectedCallback))); std::string second_challenge_text = "Negotiate Zm9vYmFy"; @@ -126,7 +126,7 @@ TEST(HttpAuthSSPITest, ParseChallenge_MissingTokenSecondRound) { std::string auth_token; EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", - &auth_token, + std::string(), &auth_token, base::Bind(&UnexpectedCallback))); std::string second_challenge_text = "Negotiate"; HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(), @@ -149,7 +149,7 @@ TEST(HttpAuthSSPITest, ParseChallenge_NonBase64EncodedToken) { std::string auth_token; EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com", - &auth_token, + std::string(), &auth_token, base::Bind(&UnexpectedCallback))); std::string second_challenge_text = "Negotiate =happyjoy="; HttpAuthChallengeTokenizer second_challenge(second_challenge_text.begin(), diff --git a/net/http/http_auth_unittest.cc b/net/http/http_auth_unittest.cc index c550803..82b3741 100644 --- a/net/http/http_auth_unittest.cc +++ b/net/http/http_auth_unittest.cc @@ -20,6 +20,7 @@ #include "net/http/http_response_headers.h" #include "net/http/http_util.h" #include "net/http/mock_allow_http_auth_preferences.h" +#include "net/ssl/ssl_info.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -33,10 +34,9 @@ HttpAuthHandlerMock* CreateMockHandler(bool connection_based) { HttpAuthChallengeTokenizer challenge(challenge_text.begin(), challenge_text.end()); GURL origin("www.example.com"); - EXPECT_TRUE(auth_handler->InitFromChallenge(&challenge, - HttpAuth::AUTH_SERVER, - origin, - BoundNetLog())); + SSLInfo null_ssl_info; + EXPECT_TRUE(auth_handler->InitFromChallenge( + &challenge, HttpAuth::AUTH_SERVER, null_ssl_info, origin, BoundNetLog())); return auth_handler; } @@ -54,12 +54,9 @@ HttpAuth::AuthorizationResult HandleChallengeResponse( std::set<HttpAuth::Scheme> disabled_schemes; scoped_refptr<HttpResponseHeaders> headers( HeadersFromResponseText(headers_text)); - return HttpAuth::HandleChallengeResponse( - mock_handler.get(), - headers.get(), - HttpAuth::AUTH_SERVER, - disabled_schemes, - challenge_used); + return HttpAuth::HandleChallengeResponse(mock_handler.get(), *headers, + HttpAuth::AUTH_SERVER, + disabled_schemes, challenge_used); } } // namespace @@ -136,14 +133,11 @@ TEST(HttpAuthTest, ChooseBestChallenge) { scoped_refptr<HttpResponseHeaders> headers( HeadersFromResponseText(headers_with_status_line)); + SSLInfo null_ssl_info; scoped_ptr<HttpAuthHandler> handler; - HttpAuth::ChooseBestChallenge(http_auth_handler_factory.get(), - headers.get(), - HttpAuth::AUTH_SERVER, - origin, - disabled_schemes, - BoundNetLog(), - &handler); + HttpAuth::ChooseBestChallenge(http_auth_handler_factory.get(), *headers, + null_ssl_info, HttpAuth::AUTH_SERVER, origin, + disabled_schemes, BoundNetLog(), &handler); if (handler.get()) { EXPECT_EQ(tests[i].challenge_scheme, handler->auth_scheme()); diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 1947594..5f7c4bd 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -1203,13 +1203,13 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) { session_->http_stream_factory()->ProcessAlternativeServices( session_, response_.headers.get(), HostPortPair::FromURL(request_->url)); + if (IsSecureRequest()) + stream_->GetSSLInfo(&response_.ssl_info); + int rv = HandleAuthChallenge(); if (rv != OK) return rv; - if (IsSecureRequest()) - stream_->GetSSLInfo(&response_.ssl_info); - headers_valid_ = true; return OK; } @@ -1665,10 +1665,11 @@ int HttpNetworkTransaction::HandleAuthChallenge() { return ERR_UNEXPECTED_PROXY_AUTH; int rv = auth_controllers_[target]->HandleAuthChallenge( - headers, (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false, + headers, response_.ssl_info, + (request_->load_flags & LOAD_DO_NOT_SEND_AUTH_DATA) != 0, false, net_log_); if (auth_controllers_[target]->HaveAuthHandler()) - pending_auth_target_ = target; + pending_auth_target_ = target; scoped_refptr<AuthChallengeInfo> auth_info = auth_controllers_[target]->auth_info(); diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index d54b498..3ebe1cb 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc @@ -11513,6 +11513,7 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) { HttpAuthHandlerMock::Factory* auth_factory( new HttpAuthHandlerMock::Factory()); session_deps_.http_auth_handler_factory.reset(auth_factory); + SSLInfo empty_ssl_info; const TestConfig& test_config = test_configs[i]; // Set up authentication handlers as necessary. @@ -11524,7 +11525,7 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) { HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(), auth_challenge.end()); auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY, - origin, BoundNetLog()); + empty_ssl_info, origin, BoundNetLog()); auth_handler->SetGenerateExpectation( test_config.proxy_auth_timing == AUTH_ASYNC, test_config.proxy_auth_rv); @@ -11538,7 +11539,7 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) { HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(), auth_challenge.end()); auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER, - origin, BoundNetLog()); + empty_ssl_info, origin, BoundNetLog()); auth_handler->SetGenerateExpectation( test_config.server_auth_timing == AUTH_ASYNC, test_config.server_auth_rv); @@ -11647,8 +11648,9 @@ TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) { GURL origin("http://www.example.com"); HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(), auth_challenge.end()); + SSLInfo empty_ssl_info; auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER, - origin, BoundNetLog()); + empty_ssl_info, origin, BoundNetLog()); auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER); int rv = OK; diff --git a/net/http/proxy_client_socket.cc b/net/http/proxy_client_socket.cc index 3a7947c..ffdbec8 100644 --- a/net/http/proxy_client_socket.cc +++ b/net/http/proxy_client_socket.cc @@ -58,7 +58,8 @@ int ProxyClientSocket::HandleProxyAuthChallenge(HttpAuthController* auth, HttpResponseInfo* response, const BoundNetLog& net_log) { DCHECK(response->headers.get()); - int rv = auth->HandleAuthChallenge(response->headers, false, true, net_log); + int rv = auth->HandleAuthChallenge(response->headers, response->ssl_info, + false, true, net_log); response->auth_challenge = auth->auth_info(); if (rv == OK) return ERR_PROXY_AUTH_REQUESTED; diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h index d3dd30f..1e469d6 100644 --- a/net/log/net_log_event_type_list.h +++ b/net/log/net_log_event_type_list.h @@ -1872,6 +1872,9 @@ EVENT_TYPE(AUTH_PROXY) // The time spent authentication to the server. EVENT_TYPE(AUTH_SERVER) +// The channel bindings generated for the connection. +EVENT_TYPE(AUTH_CHANNEL_BINDINGS) + // ------------------------------------------------------------------------ // HTML5 Application Cache // ------------------------------------------------------------------------ diff --git a/net/url_request/url_request_context_builder_unittest.cc b/net/url_request/url_request_context_builder_unittest.cc index e4f04f5..a2706d4 100644 --- a/net/url_request/url_request_context_builder_unittest.cc +++ b/net/url_request/url_request_context_builder_unittest.cc @@ -10,6 +10,7 @@ #include "net/http/http_auth_challenge_tokenizer.h" #include "net/http/http_auth_handler.h" #include "net/http/http_auth_handler_factory.h" +#include "net/ssl/ssl_info.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_test_util.h" @@ -33,6 +34,7 @@ class MockHttpAuthHandlerFactory : public HttpAuthHandlerFactory { int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge, HttpAuth::Target target, + const SSLInfo& ssl_info, const GURL& origin, CreateReason reason, int nonce_count, @@ -98,11 +100,13 @@ TEST_F(URLRequestContextBuilderTest, DefaultHttpAuthHandlerFactory) { GURL gurl("www.google.com"); scoped_ptr<HttpAuthHandler> handler; scoped_ptr<URLRequestContext> context(builder_.Build()); + SSLInfo null_ssl_info; // Verify that the default basic handler is present EXPECT_EQ(OK, context->http_auth_handler_factory()->CreateAuthHandlerFromString( - "basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler)); + "basic", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, + BoundNetLog(), &handler)); } TEST_F(URLRequestContextBuilderTest, CustomHttpAuthHandlerFactory) { @@ -112,24 +116,24 @@ TEST_F(URLRequestContextBuilderTest, CustomHttpAuthHandlerFactory) { builder_.SetHttpAuthHandlerFactory(make_scoped_ptr( new MockHttpAuthHandlerFactory("ExtraScheme", kBasicReturnCode))); scoped_ptr<URLRequestContext> context(builder_.Build()); + SSLInfo null_ssl_info; // Verify that a handler is returned for a custom scheme. EXPECT_EQ(kBasicReturnCode, context->http_auth_handler_factory()->CreateAuthHandlerFromString( - "ExtraScheme", - HttpAuth::AUTH_SERVER, - gurl, - BoundNetLog(), - &handler)); + "ExtraScheme", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, + BoundNetLog(), &handler)); // Verify that the default basic handler isn't present EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, context->http_auth_handler_factory()->CreateAuthHandlerFromString( - "basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler)); + "basic", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, + BoundNetLog(), &handler)); // Verify that a handler isn't returned for a bogus scheme. EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, context->http_auth_handler_factory()->CreateAuthHandlerFromString( - "Bogus", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler)); + "Bogus", HttpAuth::AUTH_SERVER, null_ssl_info, gurl, + BoundNetLog(), &handler)); } } // namespace |