summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorasanka <asanka@chromium.org>2016-03-23 09:20:49 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-23 16:22:04 +0000
commit5ffd5d79244e6c9928ed465fcfed8a136d04140a (patch)
tree61b94a189d803d0d262244654252bf8fec7fb691 /net
parentda4111853b1da632bf7566e3505f40ef9cca1a66 (diff)
downloadchromium_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')
-rw-r--r--net/android/http_auth_negotiate_android.cc1
-rw-r--r--net/android/http_auth_negotiate_android.h1
-rw-r--r--net/android/http_auth_negotiate_android_unittest.cc5
-rw-r--r--net/cert/x509_util.cc3
-rw-r--r--net/cert/x509_util.h6
-rw-r--r--net/cert/x509_util_nss.cc6
-rw-r--r--net/cert/x509_util_openssl.cc55
-rw-r--r--net/cert/x509_util_unittest.cc512
-rw-r--r--net/http/http_auth.cc12
-rw-r--r--net/http/http_auth.h21
-rw-r--r--net/http/http_auth_cache_unittest.cc3
-rw-r--r--net/http/http_auth_controller.cc56
-rw-r--r--net/http/http_auth_controller.h4
-rw-r--r--net/http/http_auth_controller_unittest.cc20
-rw-r--r--net/http/http_auth_gssapi_posix.cc35
-rw-r--r--net/http/http_auth_gssapi_posix.h2
-rw-r--r--net/http/http_auth_gssapi_posix_unittest.cc6
-rw-r--r--net/http/http_auth_handler.cc12
-rw-r--r--net/http/http_auth_handler.h9
-rw-r--r--net/http/http_auth_handler_basic.cc7
-rw-r--r--net/http/http_auth_handler_basic.h4
-rw-r--r--net/http/http_auth_handler_basic_unittest.cc14
-rw-r--r--net/http/http_auth_handler_digest.cc7
-rw-r--r--net/http/http_auth_handler_digest.h4
-rw-r--r--net/http/http_auth_handler_digest_unittest.cc28
-rw-r--r--net/http/http_auth_handler_factory.cc18
-rw-r--r--net/http/http_auth_handler_factory.h6
-rw-r--r--net/http/http_auth_handler_factory_unittest.cc78
-rw-r--r--net/http/http_auth_handler_mock.cc7
-rw-r--r--net/http/http_auth_handler_mock.h4
-rw-r--r--net/http/http_auth_handler_negotiate.cc46
-rw-r--r--net/http/http_auth_handler_negotiate.h5
-rw-r--r--net/http/http_auth_handler_negotiate_unittest.cc24
-rw-r--r--net/http/http_auth_handler_ntlm.cc11
-rw-r--r--net/http/http_auth_handler_ntlm.h4
-rw-r--r--net/http/http_auth_handler_ntlm_portable.cc4
-rw-r--r--net/http/http_auth_handler_ntlm_win.cc4
-rw-r--r--net/http/http_auth_handler_unittest.cc4
-rw-r--r--net/http/http_auth_sspi_win.cc91
-rw-r--r--net/http/http_auth_sspi_win.h13
-rw-r--r--net/http/http_auth_sspi_win_unittest.cc6
-rw-r--r--net/http/http_auth_unittest.cc28
-rw-r--r--net/http/http_network_transaction.cc11
-rw-r--r--net/http/http_network_transaction_unittest.cc8
-rw-r--r--net/http/proxy_client_socket.cc3
-rw-r--r--net/log/net_log_event_type_list.h3
-rw-r--r--net/url_request/url_request_context_builder_unittest.cc20
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