diff options
author | Ben Murdoch <benm@google.com> | 2013-08-08 10:24:53 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2013-08-08 10:24:53 +0100 |
commit | bb1529ce867d8845a77ec7cdf3e3003ef1771a40 (patch) | |
tree | f78d0de03cc8aed1a934d921636a0beb8d164378 /net | |
parent | c95505573d864f17cabf515e32f5b8e0831ae237 (diff) | |
download | chromium_org-bb1529ce867d8845a77ec7cdf3e3003ef1771a40.tar.gz |
Merge from Chromium at DEPS revision r216370
This commit was generated by merge_to_master.py.
Change-Id: I739228187a6f1df6c28c5761160e593a49891113
Diffstat (limited to 'net')
50 files changed, 1299 insertions, 874 deletions
diff --git a/net/cert/cert_verify_proc_nss.cc b/net/cert/cert_verify_proc_nss.cc index 120f091d7b..f63297e83c 100644 --- a/net/cert/cert_verify_proc_nss.cc +++ b/net/cert/cert_verify_proc_nss.cc @@ -162,10 +162,6 @@ CertStatus MapCertErrorToCertStatus(int err) { void GetCertChainInfo(CERTCertList* cert_list, CERTCertificate* root_cert, CertVerifyResult* verify_result) { - // NOTE: Using a NSS library before 3.12.3.1 will crash below. To see the - // NSS version currently in use: - // 1. use ldd on the chrome executable for NSS's location (ie. libnss3.so*) - // 2. use ident libnss3.so* for the library's version DCHECK(cert_list); CERTCertificate* verified_cert = NULL; @@ -367,31 +363,6 @@ SECStatus PKIXVerifyCert(CERTCertificate* cert_handle, bool use_crl = check_revocation; bool use_ocsp = check_revocation; - // These CAs have multiple keys, which trigger two bugs in NSS's CRL code. - // 1. NSS may use one key to verify a CRL signed with another key, - // incorrectly concluding that the CRL's signature is invalid. - // Hopefully this bug will be fixed in NSS 3.12.9. - // 2. NSS considers all certificates issued by the CA as revoked when it - // receives a CRL with an invalid signature. This overly strict policy - // has been relaxed in NSS 3.12.7. See - // https://bugzilla.mozilla.org/show_bug.cgi?id=562542. - // So we have to turn off CRL checking for these CAs. See - // http://crbug.com/55695. - static const char* const kMultipleKeyCA[] = { - "CN=Microsoft Secure Server Authority," - "DC=redmond,DC=corp,DC=microsoft,DC=com", - "CN=Microsoft Secure Server Authority", - }; - - if (!NSS_VersionCheck("3.12.7")) { - for (size_t i = 0; i < arraysize(kMultipleKeyCA); ++i) { - if (strcmp(cert_handle->issuerName, kMultipleKeyCA[i]) == 0) { - use_crl = false; - break; - } - } - } - PRUint64 revocation_method_flags = CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD | CERT_REV_M_ALLOW_NETWORK_FETCHING | diff --git a/net/cert/jwk_serializer.h b/net/cert/jwk_serializer.h new file mode 100644 index 0000000000..7a12a36624 --- /dev/null +++ b/net/cert/jwk_serializer.h @@ -0,0 +1,30 @@ +// Copyright 2013 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. + +#ifndef NET_CERT_JWK_SERIALIZER_H_ +#define NET_CERT_JWK_SERIALIZER_H_ + +#include "base/strings/string_piece.h" +#include "net/base/net_export.h" + +namespace base { +class DictionaryValue; +} + +namespace net { + +namespace JwkSerializer { + +// Converts a subject public key info from DER to JWK. +// See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-13 for +// the output format. +NET_EXPORT_PRIVATE bool ConvertSpkiFromDerToJwk( + const base::StringPiece& spki_der, + base::DictionaryValue* public_key_jwk); + +} // namespace JwkSerializer + +} // namespace net + +#endif // NET_CERT_JWK_SERIALIZER_H_ diff --git a/net/cert/jwk_serializer_nss.cc b/net/cert/jwk_serializer_nss.cc new file mode 100644 index 0000000000..0259c5c515 --- /dev/null +++ b/net/cert/jwk_serializer_nss.cc @@ -0,0 +1,118 @@ +// Copyright 2013 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. + +#include "net/cert/jwk_serializer.h" + +#include <cert.h> +#include <keyhi.h> +#include <nss.h> + +#include "base/base64.h" +#include "base/values.h" +#include "crypto/nss_util.h" +#include "crypto/scoped_nss_types.h" + +namespace net { + +namespace JwkSerializer { + +namespace { + +bool ConvertEcPrime256v1PublicKeyInfoToJwk( + CERTSubjectPublicKeyInfo* spki, + base::DictionaryValue* public_key_jwk) { + static const int kPrime256v1EncodingType = 4; + static const int kPrime256v1PublicKeyLength = 64; + // The public key value is encoded as 0x04 + 64 bytes of public key. + // NSS gives the length as the bit length. + if (spki->subjectPublicKey.len != (kPrime256v1PublicKeyLength + 1) * 8 || + spki->subjectPublicKey.data[0] != kPrime256v1EncodingType) + return false; + + public_key_jwk->SetString("alg", "EC"); + public_key_jwk->SetString("crv", "P-256"); + + base::StringPiece x( + reinterpret_cast<char*>(spki->subjectPublicKey.data + 1), + kPrime256v1PublicKeyLength / 2); + std::string x_b64; + base::Base64Encode(x, &x_b64); + public_key_jwk->SetString("x", x_b64); + + base::StringPiece y( + reinterpret_cast<char*>(spki->subjectPublicKey.data + 1 + + kPrime256v1PublicKeyLength / 2), + kPrime256v1PublicKeyLength / 2); + std::string y_b64; + base::Base64Encode(y, &y_b64); + public_key_jwk->SetString("y", y_b64); + return true; +} + +bool ConvertEcPublicKeyInfoToJwk( + CERTSubjectPublicKeyInfo* spki, + base::DictionaryValue* public_key_jwk) { + // 1.2.840.10045.3.1.7 + // (iso.member-body.us.ansi-x9-62.ellipticCurve.primeCurve.prime256v1) + // (This includes the DER-encoded type (OID) and length: parameters can be + // anything, so the DER type isn't implied, and NSS includes it.) + static const unsigned char kPrime256v1[] = { + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 + }; + if (spki->algorithm.parameters.len == sizeof(kPrime256v1) && + !memcmp(spki->algorithm.parameters.data, kPrime256v1, + sizeof(kPrime256v1))) { + return ConvertEcPrime256v1PublicKeyInfoToJwk(spki, public_key_jwk); + } + // TODO(juanlang): other curves + return false; +} + +typedef scoped_ptr_malloc< + CERTSubjectPublicKeyInfo, + crypto::NSSDestroyer<CERTSubjectPublicKeyInfo, + SECKEY_DestroySubjectPublicKeyInfo> > + ScopedCERTSubjectPublicKeyInfo; + +} // namespace + +bool ConvertSpkiFromDerToJwk( + const base::StringPiece& spki_der, + base::DictionaryValue* public_key_jwk) { + public_key_jwk->Clear(); + + crypto::EnsureNSSInit(); + + if (!NSS_IsInitialized()) + return false; + + SECItem sec_item; + sec_item.data = const_cast<unsigned char*>( + reinterpret_cast<const unsigned char*>(spki_der.data())); + sec_item.len = spki_der.size(); + ScopedCERTSubjectPublicKeyInfo spki( + SECKEY_DecodeDERSubjectPublicKeyInfo(&sec_item)); + if (!spki) + return false; + + // 1.2.840.10045.2 + // (iso.member-body.us.ansi-x9-62.id-ecPublicKey) + // (This omits the ASN.1 encoding of the type (OID) and length: the fact that + // this is an OID is already clear, and NSS omits it here.) + static const unsigned char kIdEcPublicKey[] = { + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01 + }; + bool rv = false; + if (spki->algorithm.algorithm.len == sizeof(kIdEcPublicKey) && + !memcmp(spki->algorithm.algorithm.data, kIdEcPublicKey, + sizeof(kIdEcPublicKey))) { + rv = ConvertEcPublicKeyInfoToJwk(spki.get(), public_key_jwk); + } + // TODO(juanlang): other algorithms + return rv; +} + +} // namespace JwkSerializer + +} // namespace net diff --git a/net/cert/jwk_serializer_openssl.cc b/net/cert/jwk_serializer_openssl.cc new file mode 100644 index 0000000000..ef15b4bcfa --- /dev/null +++ b/net/cert/jwk_serializer_openssl.cc @@ -0,0 +1,22 @@ +// Copyright 2013 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. + +#include "base/logging.h" +#include "net/cert/jwk_serializer.h" + +namespace net { + +namespace JwkSerializer { + +bool ConvertSpkiFromDerToJwk( + const base::StringPiece& spki_der, + base::DictionaryValue* public_key_jwk) { + // TODO(juanlang): implement + NOTIMPLEMENTED(); + return false; +} + +} // namespace JwkSerializer + +} // namespace net diff --git a/net/cert/jwk_serializer_unittest.cc b/net/cert/jwk_serializer_unittest.cc new file mode 100644 index 0000000000..37b8002951 --- /dev/null +++ b/net/cert/jwk_serializer_unittest.cc @@ -0,0 +1,148 @@ +// Copyright 2013 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. + +#include "net/cert/jwk_serializer.h" + +#include "base/base64.h" +#include "base/values.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +// This is the ASN.1 prefix for a P-256 public key. Specifically it's: +// SEQUENCE +// SEQUENCE +// OID id-ecPublicKey +// OID prime256v1 +// BIT STRING, length 66, 0 trailing bits: 0x04 +// +// The 0x04 in the BIT STRING is the prefix for an uncompressed, X9.62 +// public key. Following that are the two field elements as 32-byte, +// big-endian numbers, as required by the Channel ID. +static const unsigned char kP256SpkiPrefix[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04 +}; +static const unsigned int kEcPointSize = 32U; + +// This is a valid P-256 public key. +static const unsigned char kSpkiEc[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, + 0x29, 0x5d, 0x6e, 0xfe, 0x33, 0x77, 0x26, 0xea, + 0x5b, 0xa4, 0xe6, 0x1b, 0x34, 0x6e, 0x7b, 0xa0, + 0xa3, 0x8f, 0x33, 0x49, 0xa0, 0x9c, 0xae, 0x98, + 0xbd, 0x46, 0x0d, 0xf6, 0xd4, 0x5a, 0xdc, 0x8a, + 0x1f, 0x8a, 0xb2, 0x20, 0x51, 0xb7, 0xd2, 0x87, + 0x0d, 0x53, 0x7e, 0x5d, 0x94, 0xa3, 0xe0, 0x34, + 0x16, 0xa1, 0xcc, 0x10, 0x48, 0xcd, 0x70, 0x9c, + 0x05, 0xd3, 0xd2, 0xca, 0xdf, 0x44, 0x2f, 0xf4 +}; + +// This is a P-256 public key with 0 X and Y values. +static const unsigned char kSpkiEcWithZeroXY[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +#if !defined(USE_OPENSSL) + +TEST(JwkSerializerNSSTest, ConvertSpkiFromDerToJwkEc) { + base::StringPiece spki; + base::DictionaryValue public_key_jwk; + + EXPECT_FALSE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk)); + EXPECT_TRUE(public_key_jwk.empty()); + + // Test the result of a "normal" point on this curve. + spki.set(reinterpret_cast<const char*>(kSpkiEc), sizeof(kSpkiEc)); + EXPECT_TRUE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk)); + + std::string string_value; + EXPECT_TRUE(public_key_jwk.GetString("alg", &string_value)); + EXPECT_STREQ("EC", string_value.c_str()); + EXPECT_TRUE(public_key_jwk.GetString("crv", &string_value)); + EXPECT_STREQ("P-256", string_value.c_str()); + + EXPECT_TRUE(public_key_jwk.GetString("x", &string_value)); + std::string decoded_coordinate; + EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate)); + EXPECT_EQ(kEcPointSize, decoded_coordinate.size()); + EXPECT_EQ(0, + memcmp(decoded_coordinate.data(), + kSpkiEc + sizeof(kP256SpkiPrefix), + kEcPointSize)); + + EXPECT_TRUE(public_key_jwk.GetString("y", &string_value)); + EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate)); + EXPECT_EQ(kEcPointSize, decoded_coordinate.size()); + EXPECT_EQ(0, + memcmp(decoded_coordinate.data(), + kSpkiEc + sizeof(kP256SpkiPrefix) + kEcPointSize, + kEcPointSize)); + + // Test the result of a corner case: leading 0s in the x, y coordinates are + // not trimmed, but the point is fixed-length encoded. + spki.set(reinterpret_cast<const char*>(kSpkiEcWithZeroXY), + sizeof(kSpkiEcWithZeroXY)); + EXPECT_TRUE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk)); + + EXPECT_TRUE(public_key_jwk.GetString("alg", &string_value)); + EXPECT_STREQ("EC", string_value.c_str()); + EXPECT_TRUE(public_key_jwk.GetString("crv", &string_value)); + EXPECT_STREQ("P-256", string_value.c_str()); + + EXPECT_TRUE(public_key_jwk.GetString("x", &string_value)); + EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate)); + EXPECT_EQ(kEcPointSize, decoded_coordinate.size()); + EXPECT_EQ(0, + memcmp(decoded_coordinate.data(), + kSpkiEcWithZeroXY + sizeof(kP256SpkiPrefix), + kEcPointSize)); + + EXPECT_TRUE(public_key_jwk.GetString("y", &string_value)); + EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate)); + EXPECT_EQ(kEcPointSize, decoded_coordinate.size()); + EXPECT_EQ(0, + memcmp(decoded_coordinate.data(), + kSpkiEcWithZeroXY + sizeof(kP256SpkiPrefix) + kEcPointSize, + kEcPointSize)); +} + +#else + +// For OpenSSL, JwkSerializer::ConvertSpkiFromDerToJwk() is not yet implemented +// and should return false. This unit test ensures that a stub implementation +// is present. +TEST(JwkSerializerOpenSSLTest, ConvertSpkiFromDerToJwkNotImplemented) { + base::StringPiece spki; + base::DictionaryValue public_key_jwk; + + // The empty SPKI is trivially non-convertible... + EXPECT_FALSE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk)); + EXPECT_TRUE(public_key_jwk.empty()); + // but even a valid SPKI is non-convertible via the stub OpenSSL + // implementation. + spki.set(reinterpret_cast<const char*>(kSpkiEc), sizeof(kSpkiEc)); + EXPECT_FALSE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk)); + EXPECT_TRUE(public_key_jwk.empty()); +} + +#endif // !defined(USE_OPENSSL) + +} // namespace net diff --git a/net/disk_cache/simple/simple_entry_impl.cc b/net/disk_cache/simple/simple_entry_impl.cc index 7bef5f0aea..3c3ec7daff 100644 --- a/net/disk_cache/simple/simple_entry_impl.cc +++ b/net/disk_cache/simple/simple_entry_impl.cc @@ -125,14 +125,6 @@ void AdjustOpenEntryCountBy(int offset) { g_open_entry_count); } -bool OperationsConflict(int index1, int offset1, int length1, bool truncate1, - int index2, int offset2, int length2, bool truncate2) { - int end1 = truncate1 ? INT_MAX : offset1 + length1; - int end2 = truncate2 ? INT_MAX : offset2 + length2; - bool ranges_intersect = (offset1 < end2 && offset2 < end1); - return (index1 == index2 && ranges_intersect); -} - } // namespace namespace disk_cache { @@ -220,11 +212,8 @@ int SimpleEntryImpl::OpenEntry(Entry** out_entry, return net::ERR_FAILED; } - EnqueueOperation(base::Bind(&SimpleEntryImpl::OpenEntryInternal, - this, - have_index, - callback, - out_entry)); + pending_operations_.push(SimpleEntryOperation::OpenOperation( + this, have_index, callback, out_entry)); RunNextOperationIfNeeded(); return net::ERR_IO_PENDING; } @@ -243,18 +232,12 @@ int SimpleEntryImpl::CreateEntry(Entry** out_entry, net_log_.AddEvent(net::NetLog::TYPE_SIMPLE_CACHE_ENTRY_CREATE_OPTIMISTIC); ReturnEntryToCaller(out_entry); - EnqueueOperation(base::Bind(&SimpleEntryImpl::CreateEntryInternal, - this, - have_index, - CompletionCallback(), - static_cast<Entry**>(NULL))); + pending_operations_.push(SimpleEntryOperation::CreateOperation( + this, have_index, CompletionCallback(), static_cast<Entry**>(NULL))); ret_value = net::OK; } else { - EnqueueOperation(base::Bind(&SimpleEntryImpl::CreateEntryInternal, - this, - have_index, - callback, - out_entry)); + pending_operations_.push(SimpleEntryOperation::CreateOperation( + this, have_index, callback, out_entry)); ret_value = net::ERR_IO_PENDING; } @@ -305,7 +288,7 @@ void SimpleEntryImpl::Close() { return; } - EnqueueOperation(base::Bind(&SimpleEntryImpl::CloseInternal, this)); + pending_operations_.push(SimpleEntryOperation::CloseOperation(this)); DCHECK(!HasOneRef()); Release(); // Balanced in ReturnEntryToCaller(). RunNextOperationIfNeeded(); @@ -368,16 +351,10 @@ int SimpleEntryImpl::ReadData(int stream_index, // TODO(felipeg): Optimization: Add support for truly parallel read // operations. - EnqueueReadOperation(base::Bind(&SimpleEntryImpl::ReadDataInternal, - this, - stream_index, - offset, - make_scoped_refptr(buf), - buf_len, - callback), - stream_index, - offset, - buf_len); + bool alone_in_queue = + pending_operations_.size() == 0 && state_ == STATE_READY; + pending_operations_.push(SimpleEntryOperation::ReadOperation( + this, stream_index, offset, buf_len, buf, callback, alone_in_queue)); RunNextOperationIfNeeded(); return net::ERR_IO_PENDING; } @@ -462,13 +439,14 @@ int SimpleEntryImpl::WriteData(int stream_index, } } - EnqueueWriteOperation(optimistic, - stream_index, - offset, - op_buf.get(), - buf_len, - truncate, - op_callback); + pending_operations_.push(SimpleEntryOperation::WriteOperation(this, + stream_index, + offset, + buf_len, + op_buf.get(), + truncate, + optimistic, + op_callback)); return ret_value; } @@ -521,9 +499,6 @@ int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { return net::ERR_FAILED; } -SimpleEntryImpl::LastQueuedOpInfo::LastQueuedOpInfo() - : is_optimistic_write(false), is_write(false), is_read(false) {} - SimpleEntryImpl::~SimpleEntryImpl() { DCHECK(io_thread_checker_.CalledOnValidThread()); DCHECK_EQ(0U, pending_operations_.size()); @@ -570,96 +545,49 @@ void SimpleEntryImpl::RunNextOperationIfNeeded() { UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.EntryOperationsPending", pending_operations_.size(), 0, 100, 20); if (!pending_operations_.empty() && state_ != STATE_IO_PENDING) { - base::Closure operation = pending_operations_.front(); + scoped_ptr<SimpleEntryOperation> operation( + new SimpleEntryOperation(pending_operations_.front())); pending_operations_.pop(); - operation.Run(); - // |this| may have been deleted. - } -} - -void SimpleEntryImpl::EnqueueOperation(const base::Closure& operation) { - last_op_info_.is_read = false; - last_op_info_.is_write = false; - last_op_info_.is_optimistic_write = false; - pending_operations_.push(operation); -} - -void SimpleEntryImpl::EnqueueReadOperation(const base::Closure& operation, - int index, - int offset, - int length) { - bool parallelizable_read = last_op_info_.is_read && - (!pending_operations_.empty() || state_ == STATE_IO_PENDING); - UMA_HISTOGRAM_BOOLEAN("SimpleCache.ReadIsParallelizable", - parallelizable_read); - last_op_info_.is_read = true; - last_op_info_.is_write = false; - last_op_info_.is_optimistic_write = false; - last_op_info_.io_index = index; - last_op_info_.io_offset = offset; - last_op_info_.io_length = length; - pending_operations_.push(operation); -} - -void SimpleEntryImpl::EnqueueWriteOperation( - bool optimistic, - int index, - int offset, - net::IOBuffer* buf, - int length, - bool truncate, - const CompletionCallback& callback) { - // Used in histograms, please only add entries at the end. - enum WriteDependencyType { - WRITE_OPTIMISTIC = 0, - WRITE_FOLLOWS_CONFLICTING_OPTIMISTIC = 1, - WRITE_FOLLOWS_NON_CONFLICTING_OPTIMISTIC = 2, - WRITE_FOLLOWS_CONFLICTING_WRITE = 3, - WRITE_FOLLOWS_NON_CONFLICTING_WRITE = 4, - WRITE_FOLLOWS_CONFLICTING_READ = 5, - WRITE_FOLLOWS_NON_CONFLICTING_READ = 6, - WRITE_FOLLOWS_OTHER = 7, - WRITE_DEPENDENCY_TYPE_MAX = 8, - }; - - WriteDependencyType type = WRITE_FOLLOWS_OTHER; - if (optimistic) { - type = WRITE_OPTIMISTIC; - } else if (last_op_info_.is_read || last_op_info_.is_write) { - bool conflicting = OperationsConflict( - index, offset, length, truncate, - last_op_info_.io_index, - last_op_info_.io_offset, last_op_info_.io_length, - last_op_info_.truncate && last_op_info_.is_write); - - if (last_op_info_.is_optimistic_write) { - type = conflicting ? WRITE_FOLLOWS_CONFLICTING_OPTIMISTIC - : WRITE_FOLLOWS_NON_CONFLICTING_OPTIMISTIC; - } else if (last_op_info_.is_read) { - type = conflicting ? WRITE_FOLLOWS_CONFLICTING_READ - : WRITE_FOLLOWS_NON_CONFLICTING_READ; - } else { - type = conflicting ? WRITE_FOLLOWS_CONFLICTING_WRITE - : WRITE_FOLLOWS_NON_CONFLICTING_WRITE; + switch (operation->type()) { + case SimpleEntryOperation::TYPE_OPEN: + OpenEntryInternal(operation->have_index(), + operation->callback(), + operation->out_entry()); + break; + case SimpleEntryOperation::TYPE_CREATE: + CreateEntryInternal(operation->have_index(), + operation->callback(), + operation->out_entry()); + break; + case SimpleEntryOperation::TYPE_CLOSE: + CloseInternal(); + break; + case SimpleEntryOperation::TYPE_READ: + RecordReadIsParallelizable(*operation); + ReadDataInternal(operation->index(), + operation->offset(), + operation->buf(), + operation->length(), + operation->callback()); + break; + case SimpleEntryOperation::TYPE_WRITE: + RecordWriteDependencyType(*operation); + WriteDataInternal(operation->index(), + operation->offset(), + operation->buf(), + operation->length(), + operation->callback(), + operation->truncate()); + break; + default: + NOTREACHED(); } + // The operation is kept for histograms. Makes sure it does not leak + // resources. + executing_operation_.swap(operation); + executing_operation_->ReleaseReferences(); + // |this| may have been deleted. } - UMA_HISTOGRAM_ENUMERATION( - "SimpleCache.WriteDependencyType", type, WRITE_DEPENDENCY_TYPE_MAX); - last_op_info_.is_read = false; - last_op_info_.is_write = true; - last_op_info_.is_optimistic_write = optimistic; - last_op_info_.io_index = index; - last_op_info_.io_offset = offset; - last_op_info_.io_length = length; - last_op_info_.truncate = truncate; - pending_operations_.push(base::Bind(&SimpleEntryImpl::WriteDataInternal, - this, - index, - offset, - make_scoped_refptr(buf), - length, - callback, - truncate)); } void SimpleEntryImpl::OpenEntryInternal(bool have_index, @@ -1204,4 +1132,56 @@ int64 SimpleEntryImpl::GetDiskUsage() const { return file_size; } +void SimpleEntryImpl::RecordReadIsParallelizable( + const SimpleEntryOperation& operation) const { + if (!executing_operation_) + return; + // TODO(clamy): The values of this histogram should be changed to something + // more useful. + bool parallelizable_read = + !operation.alone_in_queue() && + executing_operation_->type() == SimpleEntryOperation::TYPE_READ; + UMA_HISTOGRAM_BOOLEAN("SimpleCache.ReadIsParallelizable", + parallelizable_read); +} + +void SimpleEntryImpl::RecordWriteDependencyType( + const SimpleEntryOperation& operation) const { + if (!executing_operation_) + return; + // Used in histograms, please only add entries at the end. + enum WriteDependencyType { + WRITE_OPTIMISTIC = 0, + WRITE_FOLLOWS_CONFLICTING_OPTIMISTIC = 1, + WRITE_FOLLOWS_NON_CONFLICTING_OPTIMISTIC = 2, + WRITE_FOLLOWS_CONFLICTING_WRITE = 3, + WRITE_FOLLOWS_NON_CONFLICTING_WRITE = 4, + WRITE_FOLLOWS_CONFLICTING_READ = 5, + WRITE_FOLLOWS_NON_CONFLICTING_READ = 6, + WRITE_FOLLOWS_OTHER = 7, + WRITE_DEPENDENCY_TYPE_MAX = 8, + }; + + WriteDependencyType type = WRITE_FOLLOWS_OTHER; + if (operation.optimistic()) { + type = WRITE_OPTIMISTIC; + } else if (executing_operation_->type() == SimpleEntryOperation::TYPE_READ || + executing_operation_->type() == SimpleEntryOperation::TYPE_WRITE) { + bool conflicting = executing_operation_->ConflictsWith(operation); + + if (executing_operation_->type() == SimpleEntryOperation::TYPE_READ) { + type = conflicting ? WRITE_FOLLOWS_CONFLICTING_READ + : WRITE_FOLLOWS_NON_CONFLICTING_READ; + } else if (executing_operation_->optimistic()) { + type = conflicting ? WRITE_FOLLOWS_CONFLICTING_OPTIMISTIC + : WRITE_FOLLOWS_NON_CONFLICTING_OPTIMISTIC; + } else { + type = conflicting ? WRITE_FOLLOWS_CONFLICTING_WRITE + : WRITE_FOLLOWS_NON_CONFLICTING_WRITE; + } + } + UMA_HISTOGRAM_ENUMERATION( + "SimpleCache.WriteDependencyType", type, WRITE_DEPENDENCY_TYPE_MAX); +} + } // namespace disk_cache diff --git a/net/disk_cache/simple/simple_entry_impl.h b/net/disk_cache/simple/simple_entry_impl.h index be28fb89cd..7eb8914e87 100644 --- a/net/disk_cache/simple/simple_entry_impl.h +++ b/net/disk_cache/simple/simple_entry_impl.h @@ -16,6 +16,7 @@ #include "net/base/net_log.h" #include "net/disk_cache/disk_cache.h" #include "net/disk_cache/simple/simple_entry_format.h" +#include "net/disk_cache/simple/simple_entry_operation.h" namespace base { class TaskRunner; @@ -129,22 +130,6 @@ class SimpleEntryImpl : public Entry, public base::RefCounted<SimpleEntryImpl>, CRC_CHECK_MAX = 4, }; - // Used in histograms. - struct LastQueuedOpInfo { - LastQueuedOpInfo(); - - // Used for SimpleCache.WriteDependencyType. - int io_index; - int io_offset; - int io_length; - bool is_optimistic_write; - bool is_write; - bool truncate; - - // Used for SimpleCache.ReadIsParallelizable histogram. - bool is_read; - }; - virtual ~SimpleEntryImpl(); // Sets entry to STATE_UNINITIALIZED. @@ -169,24 +154,6 @@ class SimpleEntryImpl : public Entry, public base::RefCounted<SimpleEntryImpl>, // the last reference. void RunNextOperationIfNeeded(); - // Adds a non read operation to the queue of operations. - void EnqueueOperation(const base::Closure& operation); - - // Adds a read operation to the queue of operations. - void EnqueueReadOperation(const base::Closure& operation, - int index, - int offset, - int length); - - // Adds a write operation to the queue of operations. - void EnqueueWriteOperation(bool optimistic, - int index, - int offset, - net::IOBuffer* buf, - int length, - bool truncate, - const CompletionCallback& callback); - void OpenEntryInternal(bool have_index, const CompletionCallback& callback, Entry** out_entry); @@ -263,6 +230,10 @@ class SimpleEntryImpl : public Entry, public base::RefCounted<SimpleEntryImpl>, int64 GetDiskUsage() const; + // Used to report histograms. + void RecordReadIsParallelizable(const SimpleEntryOperation& operation) const; + void RecordWriteDependencyType(const SimpleEntryOperation& operation) const; + // All nonstatic SimpleEntryImpl methods should always be called on the IO // thread, in all cases. |io_thread_checker_| documents and enforces this. base::ThreadChecker io_thread_checker_; @@ -307,11 +278,11 @@ class SimpleEntryImpl : public Entry, public base::RefCounted<SimpleEntryImpl>, // is false (i.e. when an operation is not pending on the worker pool). SimpleSynchronousEntry* synchronous_entry_; - std::queue<base::Closure> pending_operations_; + std::queue<SimpleEntryOperation> pending_operations_; net::BoundNetLog net_log_; - LastQueuedOpInfo last_op_info_; + scoped_ptr<SimpleEntryOperation> executing_operation_; }; } // namespace disk_cache diff --git a/net/disk_cache/simple/simple_entry_operation.cc b/net/disk_cache/simple/simple_entry_operation.cc new file mode 100644 index 0000000000..81d5f7c888 --- /dev/null +++ b/net/disk_cache/simple/simple_entry_operation.cc @@ -0,0 +1,184 @@ +// Copyright 2013 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. + +#include "net/disk_cache/simple/simple_entry_operation.h" + +#include "base/logging.h" +#include "net/base/io_buffer.h" +#include "net/disk_cache/disk_cache.h" +#include "net/disk_cache/simple/simple_entry_impl.h" + +namespace disk_cache { + +SimpleEntryOperation::SimpleEntryOperation(const SimpleEntryOperation& other) + : entry_(other.entry_.get()), + buf_(other.buf_), + callback_(other.callback_), + out_entry_(other.out_entry_), + offset_(other.offset_), + length_(other.length_), + type_(other.type_), + have_index_(other.have_index_), + index_(other.index_), + truncate_(other.truncate_), + optimistic_(other.optimistic_), + alone_in_queue_(other.alone_in_queue_) { +} + +SimpleEntryOperation::~SimpleEntryOperation() {} + +// Static. +SimpleEntryOperation SimpleEntryOperation::OpenOperation( + SimpleEntryImpl* entry, + bool have_index, + const CompletionCallback& callback, + Entry** out_entry) { + return SimpleEntryOperation(entry, + NULL, + callback, + out_entry, + 0, + 0, + TYPE_OPEN, + have_index, + 0, + false, + false, + false); +} + +// Static. +SimpleEntryOperation SimpleEntryOperation::CreateOperation( + SimpleEntryImpl* entry, + bool have_index, + const CompletionCallback& callback, + Entry** out_entry) { + return SimpleEntryOperation(entry, + NULL, + callback, + out_entry, + 0, + 0, + TYPE_CREATE, + have_index, + 0, + false, + false, + false); +} + +// Static. +SimpleEntryOperation SimpleEntryOperation::CloseOperation( + SimpleEntryImpl* entry) { + return SimpleEntryOperation(entry, + NULL, + CompletionCallback(), + NULL, + 0, + 0, + TYPE_CLOSE, + false, + 0, + false, + false, + false); +} + +// Static. +SimpleEntryOperation SimpleEntryOperation::ReadOperation( + SimpleEntryImpl* entry, + int index, + int offset, + int length, + net::IOBuffer* buf, + const CompletionCallback& callback, + bool alone_in_queue) { + return SimpleEntryOperation(entry, + buf, + callback, + NULL, + offset, + length, + TYPE_READ, + false, + index, + false, + false, + alone_in_queue); +} + +// Static. +SimpleEntryOperation SimpleEntryOperation::WriteOperation( + SimpleEntryImpl* entry, + int index, + int offset, + int length, + net::IOBuffer* buf, + bool truncate, + bool optimistic, + const CompletionCallback& callback) { + return SimpleEntryOperation(entry, + buf, + callback, + NULL, + offset, + length, + TYPE_WRITE, + false, + index, + truncate, + optimistic, + false); +} + +bool SimpleEntryOperation::ConflictsWith( + const SimpleEntryOperation& other_op) const { + if (type_ != TYPE_READ && type_ != TYPE_WRITE) + return true; + if (other_op.type() != TYPE_READ && other_op.type() != TYPE_WRITE) + return true; + if (type() == TYPE_READ && other_op.type() == TYPE_READ) + return false; + if (index_ != other_op.index_) + return false; + int end = (type_ == TYPE_WRITE && truncate_) ? INT_MAX : offset_ + length_; + int other_op_end = (other_op.type() == TYPE_WRITE && other_op.truncate()) + ? INT_MAX + : other_op.offset() + other_op.length(); + return (offset_ < other_op_end && other_op.offset() < end); +} + +void SimpleEntryOperation::ReleaseReferences() { + callback_ = CompletionCallback(); + buf_ = NULL; + entry_ = NULL; +} + +SimpleEntryOperation::SimpleEntryOperation(SimpleEntryImpl* entry, + net::IOBuffer* buf, + const CompletionCallback& callback, + Entry** out_entry, + int offset, + int length, + EntryOperationType type, + bool have_index, + int index, + bool truncate, + bool optimistic, + bool alone_in_queue) + : entry_(entry), + buf_(buf), + callback_(callback), + out_entry_(out_entry), + offset_(offset), + length_(length), + type_(type), + have_index_(have_index), + index_(index), + truncate_(truncate), + optimistic_(optimistic), + alone_in_queue_(alone_in_queue) { +} + +} // namespace disk_cache diff --git a/net/disk_cache/simple/simple_entry_operation.h b/net/disk_cache/simple/simple_entry_operation.h new file mode 100644 index 0000000000..acdd60a320 --- /dev/null +++ b/net/disk_cache/simple/simple_entry_operation.h @@ -0,0 +1,125 @@ +// Copyright 2013 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. + +#ifndef NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_OPERATION_H_ +#define NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_OPERATION_H_ + +#include "base/memory/ref_counted.h" +#include "net/base/completion_callback.h" +#include "net/base/net_log.h" + +namespace net { +class IOBuffer; +} + +namespace disk_cache { + +class Entry; +class SimpleEntryImpl; + +// SimpleEntryOperation stores the information regarding operations in +// SimpleEntryImpl, between the moment they are issued by users of the backend, +// and the moment when they are executed. +class SimpleEntryOperation { + public: + typedef net::CompletionCallback CompletionCallback; + + enum EntryOperationType { + TYPE_OPEN = 0, + TYPE_CREATE = 1, + TYPE_CLOSE = 2, + TYPE_READ = 3, + TYPE_WRITE = 4, + }; + + SimpleEntryOperation(const SimpleEntryOperation& other); + ~SimpleEntryOperation(); + + static SimpleEntryOperation OpenOperation(SimpleEntryImpl* entry, + bool have_index, + const CompletionCallback& callback, + Entry** out_entry); + static SimpleEntryOperation CreateOperation( + SimpleEntryImpl* entry, + bool have_index, + const CompletionCallback& callback, + Entry** out_entry); + static SimpleEntryOperation CloseOperation(SimpleEntryImpl* entry); + static SimpleEntryOperation ReadOperation(SimpleEntryImpl* entry, + int index, + int offset, + int length, + net::IOBuffer* buf, + const CompletionCallback& callback, + bool alone_in_queue); + static SimpleEntryOperation WriteOperation( + SimpleEntryImpl* entry, + int index, + int offset, + int length, + net::IOBuffer* buf, + bool truncate, + bool optimistic, + const CompletionCallback& callback); + + bool ConflictsWith(const SimpleEntryOperation& other_op) const; + // Releases all references. After calling this operation, SimpleEntryOperation + // will only hold POD members. + void ReleaseReferences(); + + EntryOperationType type() const { + return static_cast<EntryOperationType>(type_); + } + const CompletionCallback& callback() const { return callback_; } + Entry** out_entry() { return out_entry_; } + bool have_index() const { return have_index_; } + int index() const { return index_; } + int offset() const { return offset_; } + int length() const { return length_; } + net::IOBuffer* buf() { return buf_.get(); } + bool truncate() const { return truncate_; } + bool optimistic() const { return optimistic_; } + bool alone_in_queue() const { return alone_in_queue_; } + + private: + SimpleEntryOperation(SimpleEntryImpl* entry, + net::IOBuffer* buf, + const CompletionCallback& callback, + Entry** out_entry, + int offset, + int length, + EntryOperationType type, + bool have_index, + int index, + bool truncate, + bool optimistic, + bool alone_in_queue); + + // This ensures entry will not be deleted until the operation has ran. + scoped_refptr<SimpleEntryImpl> entry_; + scoped_refptr<net::IOBuffer> buf_; + CompletionCallback callback_; + + // Used in open and create operations. + Entry** out_entry_; + + // Used in write and read operations. + const int offset_; + const int length_; + + const unsigned int type_ : 3; /* 3 */ + // Used in open and create operations. + const unsigned int have_index_ : 1; /* 4 */ + // Used in write and read operations. + const unsigned int index_ : 2; /* 6 */ + // Used only in write operations. + const unsigned int truncate_ : 1; /* 7 */ + const unsigned int optimistic_ : 1; /* 8 */ + // Used only in SimpleCache.ReadIsParallelizable histogram. + const unsigned int alone_in_queue_ : 1; /* 9 */ +}; + +} // namespace disk_cache + +#endif // NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_OPERATION_H_ diff --git a/net/dns/mdns_client_impl.cc b/net/dns/mdns_client_impl.cc index 089a51a8a7..8f79edf4cd 100644 --- a/net/dns/mdns_client_impl.cc +++ b/net/dns/mdns_client_impl.cc @@ -622,8 +622,7 @@ void MDnsTransactionImpl::ServeRecordsFromCache() { client_->core()->QueryCache(rrtype_, name_, &records); for (std::vector<const RecordParsed*>::iterator i = records.begin(); i != records.end() && weak_this; ++i) { - weak_this->TriggerCallback(MDnsTransaction::RESULT_RECORD, - records.front()); + weak_this->TriggerCallback(MDnsTransaction::RESULT_RECORD, *i); } #if defined(ENABLE_NSEC) diff --git a/net/net.gyp b/net/net.gyp index 8942367294..0165031978 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -271,6 +271,9 @@ 'cert/crl_set.h', 'cert/ev_root_ca_metadata.cc', 'cert/ev_root_ca_metadata.h', + 'cert/jwk_serializer_nss.cc', + 'cert/jwk_serializer_openssl.cc', + 'cert/jwk_serializer.h', 'cert/multi_threaded_cert_verifier.cc', 'cert/multi_threaded_cert_verifier.h', 'cert/nss_cert_database.cc', @@ -390,6 +393,8 @@ 'disk_cache/simple/simple_entry_format.h', 'disk_cache/simple/simple_entry_impl.cc', 'disk_cache/simple/simple_entry_impl.h', + 'disk_cache/simple/simple_entry_operation.cc', + 'disk_cache/simple/simple_entry_operation.h', 'disk_cache/simple/simple_index.cc', 'disk_cache/simple/simple_index.h', 'disk_cache/simple/simple_index_file.cc', @@ -1199,6 +1204,7 @@ 'cert/cert_database_nss.cc', 'cert/cert_verify_proc_nss.cc', 'cert/cert_verify_proc_nss.h', + 'cert/jwk_serializer_nss.cc', 'cert/nss_cert_database.cc', 'cert/nss_cert_database.h', 'cert/test_root_certs_nss.cc', @@ -1236,6 +1242,7 @@ 'cert/cert_database_openssl.cc', 'cert/cert_verify_proc_openssl.cc', 'cert/cert_verify_proc_openssl.h', + 'cert/jwk_serializer_openssl.cc', 'cert/test_root_certs_openssl.cc', 'cert/x509_certificate_openssl.cc', 'cert/x509_util_openssl.cc', @@ -1524,6 +1531,7 @@ 'cert/cert_verify_proc_unittest.cc', 'cert/crl_set_unittest.cc', 'cert/ev_root_ca_metadata_unittest.cc', + 'cert/jwk_serializer_unittest.cc', 'cert/multi_threaded_cert_verifier_unittest.cc', 'cert/nss_cert_database_unittest.cc', 'cert/pem_tokenizer_unittest.cc', @@ -1869,11 +1877,14 @@ 'tools/quic/quic_in_memory_cache_test.cc', 'tools/quic/quic_reliable_client_stream_test.cc', 'tools/quic/quic_reliable_server_stream_test.cc', + 'tools/quic/quic_server_test.cc', 'tools/quic/quic_spdy_server_stream_test.cc', 'tools/quic/test_tools/http_message_test_utils.cc', 'tools/quic/test_tools/http_message_test_utils.h', 'tools/quic/test_tools/mock_epoll_server.cc', 'tools/quic/test_tools/mock_epoll_server.h', + 'tools/quic/test_tools/mock_quic_dispatcher.cc', + 'tools/quic/test_tools/mock_quic_dispatcher.h', 'tools/quic/test_tools/quic_client_peer.cc', 'tools/quic/test_tools/quic_client_peer.h', 'tools/quic/test_tools/quic_epoll_connection_helper_peer.cc', diff --git a/net/net.target.darwin-arm.mk b/net/net.target.darwin-arm.mk index 32a09e6590..88d78fc546 100644 --- a/net/net.target.darwin-arm.mk +++ b/net/net.target.darwin-arm.mk @@ -103,6 +103,7 @@ LOCAL_SRC_FILES := \ net/cert/cert_verify_result.cc \ net/cert/crl_set.cc \ net/cert/ev_root_ca_metadata.cc \ + net/cert/jwk_serializer_openssl.cc \ net/cert/multi_threaded_cert_verifier.cc \ net/cert/pem_tokenizer.cc \ net/cert/single_request_cert_verifier.cc \ @@ -149,6 +150,7 @@ LOCAL_SRC_FILES := \ net/disk_cache/simple/simple_backend_impl.cc \ net/disk_cache/simple/simple_entry_format.cc \ net/disk_cache/simple/simple_entry_impl.cc \ + net/disk_cache/simple/simple_entry_operation.cc \ net/disk_cache/simple/simple_index.cc \ net/disk_cache/simple/simple_index_file.cc \ net/disk_cache/simple/simple_net_log_parameters.cc \ diff --git a/net/net.target.darwin-mips.mk b/net/net.target.darwin-mips.mk index 47c7546b98..6fedabc2e6 100644 --- a/net/net.target.darwin-mips.mk +++ b/net/net.target.darwin-mips.mk @@ -103,6 +103,7 @@ LOCAL_SRC_FILES := \ net/cert/cert_verify_result.cc \ net/cert/crl_set.cc \ net/cert/ev_root_ca_metadata.cc \ + net/cert/jwk_serializer_openssl.cc \ net/cert/multi_threaded_cert_verifier.cc \ net/cert/pem_tokenizer.cc \ net/cert/single_request_cert_verifier.cc \ @@ -149,6 +150,7 @@ LOCAL_SRC_FILES := \ net/disk_cache/simple/simple_backend_impl.cc \ net/disk_cache/simple/simple_entry_format.cc \ net/disk_cache/simple/simple_entry_impl.cc \ + net/disk_cache/simple/simple_entry_operation.cc \ net/disk_cache/simple/simple_index.cc \ net/disk_cache/simple/simple_index_file.cc \ net/disk_cache/simple/simple_net_log_parameters.cc \ diff --git a/net/net.target.darwin-x86.mk b/net/net.target.darwin-x86.mk index 24f1ffd8d0..4479a95214 100644 --- a/net/net.target.darwin-x86.mk +++ b/net/net.target.darwin-x86.mk @@ -103,6 +103,7 @@ LOCAL_SRC_FILES := \ net/cert/cert_verify_result.cc \ net/cert/crl_set.cc \ net/cert/ev_root_ca_metadata.cc \ + net/cert/jwk_serializer_openssl.cc \ net/cert/multi_threaded_cert_verifier.cc \ net/cert/pem_tokenizer.cc \ net/cert/single_request_cert_verifier.cc \ @@ -149,6 +150,7 @@ LOCAL_SRC_FILES := \ net/disk_cache/simple/simple_backend_impl.cc \ net/disk_cache/simple/simple_entry_format.cc \ net/disk_cache/simple/simple_entry_impl.cc \ + net/disk_cache/simple/simple_entry_operation.cc \ net/disk_cache/simple/simple_index.cc \ net/disk_cache/simple/simple_index_file.cc \ net/disk_cache/simple/simple_net_log_parameters.cc \ diff --git a/net/net.target.linux-arm.mk b/net/net.target.linux-arm.mk index 32a09e6590..88d78fc546 100644 --- a/net/net.target.linux-arm.mk +++ b/net/net.target.linux-arm.mk @@ -103,6 +103,7 @@ LOCAL_SRC_FILES := \ net/cert/cert_verify_result.cc \ net/cert/crl_set.cc \ net/cert/ev_root_ca_metadata.cc \ + net/cert/jwk_serializer_openssl.cc \ net/cert/multi_threaded_cert_verifier.cc \ net/cert/pem_tokenizer.cc \ net/cert/single_request_cert_verifier.cc \ @@ -149,6 +150,7 @@ LOCAL_SRC_FILES := \ net/disk_cache/simple/simple_backend_impl.cc \ net/disk_cache/simple/simple_entry_format.cc \ net/disk_cache/simple/simple_entry_impl.cc \ + net/disk_cache/simple/simple_entry_operation.cc \ net/disk_cache/simple/simple_index.cc \ net/disk_cache/simple/simple_index_file.cc \ net/disk_cache/simple/simple_net_log_parameters.cc \ diff --git a/net/net.target.linux-mips.mk b/net/net.target.linux-mips.mk index 47c7546b98..6fedabc2e6 100644 --- a/net/net.target.linux-mips.mk +++ b/net/net.target.linux-mips.mk @@ -103,6 +103,7 @@ LOCAL_SRC_FILES := \ net/cert/cert_verify_result.cc \ net/cert/crl_set.cc \ net/cert/ev_root_ca_metadata.cc \ + net/cert/jwk_serializer_openssl.cc \ net/cert/multi_threaded_cert_verifier.cc \ net/cert/pem_tokenizer.cc \ net/cert/single_request_cert_verifier.cc \ @@ -149,6 +150,7 @@ LOCAL_SRC_FILES := \ net/disk_cache/simple/simple_backend_impl.cc \ net/disk_cache/simple/simple_entry_format.cc \ net/disk_cache/simple/simple_entry_impl.cc \ + net/disk_cache/simple/simple_entry_operation.cc \ net/disk_cache/simple/simple_index.cc \ net/disk_cache/simple/simple_index_file.cc \ net/disk_cache/simple/simple_net_log_parameters.cc \ diff --git a/net/net.target.linux-x86.mk b/net/net.target.linux-x86.mk index 24f1ffd8d0..4479a95214 100644 --- a/net/net.target.linux-x86.mk +++ b/net/net.target.linux-x86.mk @@ -103,6 +103,7 @@ LOCAL_SRC_FILES := \ net/cert/cert_verify_result.cc \ net/cert/crl_set.cc \ net/cert/ev_root_ca_metadata.cc \ + net/cert/jwk_serializer_openssl.cc \ net/cert/multi_threaded_cert_verifier.cc \ net/cert/pem_tokenizer.cc \ net/cert/single_request_cert_verifier.cc \ @@ -149,6 +150,7 @@ LOCAL_SRC_FILES := \ net/disk_cache/simple/simple_backend_impl.cc \ net/disk_cache/simple/simple_entry_format.cc \ net/disk_cache/simple/simple_entry_impl.cc \ + net/disk_cache/simple/simple_entry_operation.cc \ net/disk_cache/simple/simple_index.cc \ net/disk_cache/simple/simple_index_file.cc \ net/disk_cache/simple/simple_net_log_parameters.cc \ diff --git a/net/quic/crypto/crypto_server_config.h b/net/quic/crypto/crypto_server_config.h index 651e928c29..1a991362bd 100644 --- a/net/quic/crypto/crypto_server_config.h +++ b/net/quic/crypto/crypto_server_config.h @@ -198,8 +198,10 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig { public: Config(); - // serialized contains the bytes of this server config, suitable for sending - // on the wire. + // TODO(rtenneti): since this is a class, we should probably do + // getters/setters here. + // |serialized| contains the bytes of this server config, suitable for + // sending on the wire. std::string serialized; // id contains the SCID of this server config. std::string id; diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc index ea738af4d6..30f822ca88 100644 --- a/net/quic/quic_connection.cc +++ b/net/quic/quic_connection.cc @@ -877,8 +877,6 @@ void QuicConnection::RetransmitPacket( RetransmissionInfo retransmission_info(serialized_packet.sequence_number); retransmission_info.number_retransmissions = retransmission_it->second.number_retransmissions + 1; - retransmission_map_.insert(make_pair(serialized_packet.sequence_number, - retransmission_info)); // Remove info with old sequence number. unacked_packets_.erase(unacked_it); retransmission_map_.erase(retransmission_it); @@ -888,6 +886,8 @@ void QuicConnection::RetransmitPacket( unacked_packets_.rbegin()->first < serialized_packet.sequence_number); unacked_packets_.insert(make_pair(serialized_packet.sequence_number, unacked)); + retransmission_map_.insert(make_pair(serialized_packet.sequence_number, + retransmission_info)); SendOrQueuePacket(unacked->encryption_level(), serialized_packet.sequence_number, serialized_packet.packet, diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc index 19e58c3163..6d69676861 100644 --- a/net/quic/quic_packet_creator.cc +++ b/net/quic/quic_packet_creator.cc @@ -111,16 +111,23 @@ size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id, size_t bytes_consumed = 0; if (data.size() != 0) { - size_t min_last_stream_frame_size = - QuicFramer::GetMinStreamFrameSize(framer_->version(), id, offset, true); - // Comparing against the last stream frame size including the frame length - // guarantees that all the bytes will fit. Otherwise there is a - // discontinuity where the packet goes one byte over due to the length data. - if (data.size() + min_last_stream_frame_size + kQuicStreamPayloadLengthSize - >= free_bytes) { - // Its the last frame, put as much data as possible in. + // When a STREAM frame is the last frame in a packet, it consumes two fewer + // bytes of framing overhead. + // Anytime more data is available than fits in with the extra two bytes, + // the frame will be the last, and up to two extra bytes are consumed. + // TODO(ianswett): If QUIC pads, the 1 byte PADDING frame does not fit when + // 1 byte is available, because then the STREAM frame isn't the last. + + // The minimum frame size(0 bytes of data) if it's not the last frame. + size_t min_frame_size = QuicFramer::GetMinStreamFrameSize( + framer_->version(), id, offset, false); + // Check if it's the last frame in the packet. + if (data.size() + min_frame_size > free_bytes) { + // The minimum frame size(0 bytes of data) if it is the last frame. + size_t min_last_frame_size = QuicFramer::GetMinStreamFrameSize( + framer_->version(), id, offset, true); bytes_consumed = - min<size_t>(free_bytes - min_last_stream_frame_size, data.size()); + min<size_t>(free_bytes - min_last_frame_size, data.size()); } else { DCHECK_LT(data.size(), BytesFree()); bytes_consumed = data.size(); diff --git a/net/quic/quic_received_packet_manager.cc b/net/quic/quic_received_packet_manager.cc index f6f94ccf89..3ade8fba9a 100644 --- a/net/quic/quic_received_packet_manager.cc +++ b/net/quic/quic_received_packet_manager.cc @@ -99,6 +99,8 @@ QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash( packets_entropy_.upper_bound(sequence_number); // When this map is empty we should only query entropy for // |largest_received_sequence_number_|. + // TODO(rtenneti): add support for LOG_IF_EVERY_N_SEC to chromium. + // LOG_IF_EVERY_N_SEC(WARNING, it != packets_entropy_.end(), 10) LOG_IF(WARNING, it != packets_entropy_.end()) << "largest_received: " << received_info_.largest_observed << " sequence_number: " << sequence_number; diff --git a/net/quic/quic_utils.h b/net/quic/quic_utils.h index fca3904757..6650dbf453 100644 --- a/net/quic/quic_utils.h +++ b/net/quic/quic_utils.h @@ -70,6 +70,10 @@ class NET_EXPORT_PRIVATE QuicUtils { // "0x0010: 001c fb98 4000 4001 7e18 d8ef 2301 455d ....@.@.~...#.E]\n" // "0x0020: 7fe2 0800 6bcb 0bc6 806e ....k....n\n" static std::string StringToHexASCIIDump(base::StringPiece in_buffer); + + static char* AsChars(unsigned char* data) { + return reinterpret_cast<char*>(data); + } }; } // namespace net diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index a5645b997a..d1f28323c6 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -771,8 +771,7 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> { //////////////////////////////////////////////////////////////////////////// int DoBufferRecv(IOBuffer* buffer, int len); int DoBufferSend(IOBuffer* buffer, int len); - int DoGetDomainBoundCert(const std::string& host, - const std::vector<uint8>& requested_cert_types); + int DoGetDomainBoundCert(const std::string& host); void OnGetDomainBoundCertComplete(int result); void OnHandshakeStateUpdated(const HandshakeState& state); @@ -903,7 +902,6 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> { // prior to invoking OnHandshakeIOComplete. // Read on the NSS task runner when once OnHandshakeIOComplete is invoked // on the NSS task runner. - SSLClientCertType domain_bound_cert_type_; std::string domain_bound_private_key_; std::string domain_bound_cert_; @@ -944,8 +942,7 @@ SSLClientSocketNSS::Core::Core( user_write_buf_len_(0), network_task_runner_(network_task_runner), nss_task_runner_(nss_task_runner), - weak_net_log_(weak_net_log_factory_.GetWeakPtr()), - domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) { + weak_net_log_(weak_net_log_factory_.GetWeakPtr()) { } SSLClientSocketNSS::Core::~Core() { @@ -1274,7 +1271,6 @@ SECStatus SSLClientSocketNSS::Core::OwnAuthCertHandler( PRFileDesc* socket, PRBool checksig, PRBool is_server) { -#ifdef SSL_ENABLE_FALSE_START Core* core = reinterpret_cast<Core*>(arg); if (!core->handshake_callback_called_) { // Only need to turn off False Start in the initial handshake. Also, it is @@ -1296,7 +1292,6 @@ SECStatus SSLClientSocketNSS::Core::OwnAuthCertHandler( SSL_OptionSet(socket, SSL_ENABLE_FALSE_START, PR_FALSE); } } -#endif // Tell NSS to not verify the certificate. return SECSuccess; @@ -2318,17 +2313,15 @@ SECStatus SSLClientSocketNSS::Core::ClientChannelIDHandler( // We have negotiated the TLS channel ID extension. core->channel_id_xtn_negotiated_ = true; std::string host = core->host_and_port_.host(); - std::vector<uint8> requested_cert_types; - requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN); int error = ERR_UNEXPECTED; if (core->OnNetworkTaskRunner()) { - error = core->DoGetDomainBoundCert(host, requested_cert_types); + error = core->DoGetDomainBoundCert(host); } else { bool posted = core->network_task_runner_->PostTask( FROM_HERE, base::Bind( IgnoreResult(&Core::DoGetDomainBoundCert), - core, host, requested_cert_types)); + core, host)); error = posted ? ERR_IO_PENDING : ERR_ABORTED; } @@ -2372,9 +2365,7 @@ int SSLClientSocketNSS::Core::ImportChannelIDKeys(SECKEYPublicKey** public_key, return MapNSSError(PORT_GetError()); // Set the private key. - switch (domain_bound_cert_type_) { - case CLIENT_CERT_ECDSA_SIGN: { - if (!crypto::ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( + if (!crypto::ECPrivateKey::ImportFromEncryptedPrivateKeyInfo( ServerBoundCertService::kEPKIPassword, reinterpret_cast<const unsigned char*>( domain_bound_private_key_.data()), @@ -2384,15 +2375,8 @@ int SSLClientSocketNSS::Core::ImportChannelIDKeys(SECKEYPublicKey** public_key, false, key, public_key)) { - int error = MapNSSError(PORT_GetError()); - return error; - } - break; - } - - default: - NOTREACHED(); - return ERR_INVALID_ARGUMENT; + int error = MapNSSError(PORT_GetError()); + return error; } return OK; @@ -2433,8 +2417,8 @@ void SSLClientSocketNSS::Core::UpdateConnectionStatus() { SSL_CONNECTION_COMPRESSION_MASK) << SSL_CONNECTION_COMPRESSION_SHIFT; - // NSS 3.12.x doesn't have version macros for TLS 1.1 and 1.2 (because NSS - // doesn't support them yet), so we use 0x0302 and 0x0303 directly. + // NSS 3.14.x doesn't have a version macro for TLS 1.2 (because NSS didn't + // support it yet), so use 0x0303 directly. int version = SSL_CONNECTION_VERSION_UNKNOWN; if (channel_info.protocolVersion < SSL_LIBRARY_VERSION_3_0) { // All versions less than SSL_LIBRARY_VERSION_3_0 are treated as SSL @@ -2444,7 +2428,7 @@ void SSLClientSocketNSS::Core::UpdateConnectionStatus() { version = SSL_CONNECTION_VERSION_SSL3; } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_3_1_TLS) { version = SSL_CONNECTION_VERSION_TLS1; - } else if (channel_info.protocolVersion == 0x0302) { + } else if (channel_info.protocolVersion == SSL_LIBRARY_VERSION_TLS_1_1) { version = SSL_CONNECTION_VERSION_TLS1_1; } else if (channel_info.protocolVersion == 0x0303) { version = SSL_CONNECTION_VERSION_TLS1_2; @@ -2454,10 +2438,6 @@ void SSLClientSocketNSS::Core::UpdateConnectionStatus() { SSL_CONNECTION_VERSION_SHIFT; } - // SSL_HandshakeNegotiatedExtension was added in NSS 3.12.6. - // Since SSL_MAX_EXTENSIONS was added at the same time, we can test - // SSL_MAX_EXTENSIONS for the presence of SSL_HandshakeNegotiatedExtension. -#if defined(SSL_MAX_EXTENSIONS) PRBool peer_supports_renego_ext; ok = SSL_HandshakeNegotiatedExtension(nss_fd_, ssl_renegotiation_info_xtn, &peer_supports_renego_ext); @@ -2491,7 +2471,6 @@ void SSLClientSocketNSS::Core::UpdateConnectionStatus() { peer_supports_renego_ext == PR_TRUE); } } -#endif if (ssl_config_.version_fallback) { nss_handshake_state_.ssl_connection_status |= @@ -2620,9 +2599,7 @@ int SSLClientSocketNSS::Core::DoBufferSend(IOBuffer* send_buffer, int len) { return rv; } -int SSLClientSocketNSS::Core::DoGetDomainBoundCert( - const std::string& host, - const std::vector<uint8>& requested_cert_types) { +int SSLClientSocketNSS::Core::DoGetDomainBoundCert(const std::string& host) { DCHECK(OnNetworkTaskRunner()); if (detached_) @@ -2632,8 +2609,6 @@ int SSLClientSocketNSS::Core::DoGetDomainBoundCert( int rv = server_bound_cert_service_->GetDomainBoundCert( host, - requested_cert_types, - &domain_bound_cert_type_, &domain_bound_private_key_, &domain_bound_cert_, base::Bind(&Core::OnGetDomainBoundCertComplete, base::Unretained(this)), @@ -3168,25 +3143,18 @@ int SSLClientSocketNSS::InitializeSSLOptions() { SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE); } -#ifdef SSL_ENABLE_SESSION_TICKETS // Support RFC 5077 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); if (rv != SECSuccess) { LogFailedNSSFunction( net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS"); } -#else - #error "You need to install NSS-3.12 or later to build chromium" -#endif -#ifdef SSL_ENABLE_FALSE_START rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALSE_START, ssl_config_.false_start_enabled); if (rv != SECSuccess) LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_FALSE_START"); -#endif -#ifdef SSL_ENABLE_RENEGOTIATION // We allow servers to request renegotiation. Since we're a client, // prohibiting this is rather a waste of time. Only servers are in a // position to prevent renegotiation attacks. @@ -3198,14 +3166,12 @@ int SSLClientSocketNSS::InitializeSSLOptions() { LogFailedNSSFunction( net_log_, "SSL_OptionSet", "SSL_ENABLE_RENEGOTIATION"); } -#endif // SSL_ENABLE_RENEGOTIATION -#ifdef SSL_CBC_RANDOM_IV rv = SSL_OptionSet(nss_fd_, SSL_CBC_RANDOM_IV, PR_TRUE); if (rv != SECSuccess) LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_CBC_RANDOM_IV"); -#endif +// Added in NSS 3.15 #ifdef SSL_ENABLE_OCSP_STAPLING if (IsOCSPStaplingSupported()) { rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE); @@ -3216,6 +3182,7 @@ int SSLClientSocketNSS::InitializeSSLOptions() { } #endif +// Chromium patch to libssl #ifdef SSL_ENABLE_CACHED_INFO rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_CACHED_INFO, ssl_config_.cached_info_enabled); diff --git a/net/spdy/spdy_credential_builder.cc b/net/spdy/spdy_credential_builder.cc index 1742aff985..79567b668a 100644 --- a/net/spdy/spdy_credential_builder.cc +++ b/net/spdy/spdy_credential_builder.cc @@ -26,14 +26,10 @@ std::vector<uint8> ToVector(base::StringPiece piece) { // static int SpdyCredentialBuilder::Build(const std::string& tls_unique, - SSLClientCertType type, const std::string& key, const std::string& cert, size_t slot, SpdyCredential* credential) { - if (type != CLIENT_CERT_ECDSA_SIGN) - return ERR_BAD_SSL_CLIENT_AUTH_CERT; - std::string secret = SpdyCredentialBuilder::GetCredentialSecret(tls_unique); // Extract the SubjectPublicKeyInfo from the certificate. diff --git a/net/spdy/spdy_credential_builder.h b/net/spdy/spdy_credential_builder.h index d74b600dd7..3bdc0a1171 100644 --- a/net/spdy/spdy_credential_builder.h +++ b/net/spdy/spdy_credential_builder.h @@ -8,7 +8,6 @@ #include <string> #include "net/base/net_export.h" -#include "net/ssl/ssl_client_cert_type.h" namespace net { @@ -20,7 +19,6 @@ struct SpdyCredential; class NET_EXPORT_PRIVATE SpdyCredentialBuilder { public: static int Build(const std::string& tls_unique, - SSLClientCertType type, const std::string& key, const std::string& cert, size_t slot, diff --git a/net/spdy/spdy_credential_builder_unittest.cc b/net/spdy/spdy_credential_builder_unittest.cc index 89332d5a7f..bc67cc593a 100644 --- a/net/spdy/spdy_credential_builder_unittest.cc +++ b/net/spdy/spdy_credential_builder_unittest.cc @@ -30,16 +30,12 @@ void CreateCertAndKey(std::string* cert, std::string* key) { sequenced_worker_pool)); TestCompletionCallback callback; - std::vector<uint8> requested_cert_types; - requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN); - SSLClientCertType cert_type; ServerBoundCertService::RequestHandle request_handle; int rv = server_bound_cert_service->GetDomainBoundCert( - "www.google.com", requested_cert_types, &cert_type, key, cert, + "www.google.com", key, cert, callback.callback(), &request_handle); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(OK, callback.WaitForResult()); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, cert_type); sequenced_worker_pool->Shutdown(); } @@ -53,13 +49,9 @@ class SpdyCredentialBuilderTest : public testing::Test { } protected: - int BuildWithType(SSLClientCertType type) { - return SpdyCredentialBuilder::Build( - MockClientSocket::kTlsUnique, type, key_, cert_, kSlot, &credential_); - } - int Build() { - return BuildWithType(CLIENT_CERT_ECDSA_SIGN); + return SpdyCredentialBuilder::Build( + MockClientSocket::kTlsUnique, key_, cert_, kSlot, &credential_); } std::string GetCredentialSecret() { @@ -89,35 +81,13 @@ TEST_F(SpdyCredentialBuilderTest, MAYBE_GetCredentialSecret) { } #if defined(USE_OPENSSL) -#define MAYBE_SucceedsWithECDSACert DISABLED_SucceedsWithECDSACert -#else -#define MAYBE_SucceedsWithECDSACert SucceedsWithECDSACert -#endif - -TEST_F(SpdyCredentialBuilderTest, MAYBE_SucceedsWithECDSACert) { - EXPECT_EQ(OK, BuildWithType(CLIENT_CERT_ECDSA_SIGN)); -} - -#if defined(USE_OPENSSL) -#define MAYBE_FailsWithRSACert DISABLED_FailsWithRSACert -#else -#define MAYBE_FailsWithRSACert FailsWithRSACert -#endif - -TEST_F(SpdyCredentialBuilderTest, MAYBE_FailsWithRSACert) { - EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT, - BuildWithType(CLIENT_CERT_RSA_SIGN)); -} - -#if defined(USE_OPENSSL) -#define MAYBE_FailsWithDSACert DISABLED_FailsWithDSACert +#define MAYBE_Succeeds DISABLED_Succeeds #else -#define MAYBE_FailsWithDSACert FailsWithDSACert +#define MAYBE_Succeeds Succeeds #endif -TEST_F(SpdyCredentialBuilderTest, MAYBE_FailsWithDSACert) { - EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT, - BuildWithType(CLIENT_CERT_DSS_SIGN)); +TEST_F(SpdyCredentialBuilderTest, MAYBE_Succeeds) { + EXPECT_EQ(OK, Build()); } #if defined(USE_OPENSSL) diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc index 04a8ecade0..55387cf410 100644 --- a/net/spdy/spdy_http_stream_unittest.cc +++ b/net/spdy/spdy_http_stream_unittest.cc @@ -540,23 +540,18 @@ void GetECServerBoundCertAndProof( std::string* cert, std::string* proof) { TestCompletionCallback callback; - std::vector<uint8> requested_cert_types; - requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN); - SSLClientCertType cert_type; std::string key; ServerBoundCertService::RequestHandle request_handle; int rv = server_bound_cert_service->GetDomainBoundCert( - host, requested_cert_types, &cert_type, &key, cert, callback.callback(), + host, &key, cert, callback.callback(), &request_handle); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(OK, callback.WaitForResult()); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, cert_type); SpdyCredential credential; EXPECT_EQ(OK, SpdyCredentialBuilder::Build( - MockClientSocket::kTlsUnique, cert_type, key, - *cert, 2, &credential)); + MockClientSocket::kTlsUnique, key, *cert, 2, &credential)); ASSERT_FALSE(credential.certs.empty()); cert->assign(credential.certs[0]); diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 8a730cec34..db47549374 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc @@ -793,7 +793,6 @@ scoped_ptr<SpdyFrame> SpdySession::CreateSynStream( int SpdySession::CreateCredentialFrame( const std::string& origin, - SSLClientCertType type, const std::string& key, const std::string& cert, RequestPriority priority, @@ -807,7 +806,7 @@ int SpdySession::CreateCredentialFrame( std::string tls_unique; ssl_socket->GetTLSUniqueChannelBinding(&tls_unique); size_t slot = credential_state_.SetHasCredential(GURL(origin)); - int rv = SpdyCredentialBuilder::Build(tls_unique, type, key, cert, slot, + int rv = SpdyCredentialBuilder::Build(tls_unique, key, cert, slot, &credential); DCHECK_NE(rv, ERR_IO_PENDING); if (rv != OK) diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index c6a22e67dd..819db111b2 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h @@ -35,7 +35,6 @@ #include "net/spdy/spdy_session_pool.h" #include "net/spdy/spdy_stream.h" #include "net/spdy/spdy_write_queue.h" -#include "net/ssl/ssl_client_cert_type.h" #include "net/ssl/ssl_config_service.h" #include "url/gurl.h" @@ -299,7 +298,6 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface, // |credential_frame| and returns OK. Returns the error (guaranteed // to not be ERR_IO_PENDING) otherwise. int CreateCredentialFrame(const std::string& origin, - SSLClientCertType type, const std::string& key, const std::string& cert, RequestPriority priority, diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc index db085cfd82..18d20e8d3a 100644 --- a/net/spdy/spdy_stream.cc +++ b/net/spdy/spdy_stream.cc @@ -108,7 +108,6 @@ SpdyStream::SpdyStream(SpdyStreamType type, net_log_(net_log), send_bytes_(0), recv_bytes_(0), - domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE), just_completed_frame_type_(DATA), just_completed_frame_size_(0) { CHECK(type_ == SPDY_BIDIRECTIONAL_STREAM || @@ -741,11 +740,10 @@ int SpdyStream::DoGetDomainBoundCert() { io_state_ = STATE_GET_DOMAIN_BOUND_CERT_COMPLETE; ServerBoundCertService* sbc_service = session_->GetServerBoundCertService(); DCHECK(sbc_service != NULL); - std::vector<uint8> requested_cert_types; - requested_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN); int rv = sbc_service->GetDomainBoundCert( - url.GetOrigin().host(), requested_cert_types, - &domain_bound_cert_type_, &domain_bound_private_key_, &domain_bound_cert_, + url.GetOrigin().host(), + &domain_bound_private_key_, + &domain_bound_cert_, base::Bind(&SpdyStream::OnGetDomainBoundCertComplete, GetWeakPtr()), &domain_bound_cert_request_handle_); return rv; @@ -771,8 +769,11 @@ int SpdyStream::DoSendDomainBoundCert() { origin.erase(origin.length() - 1); // Trim trailing slash. scoped_ptr<SpdyFrame> frame; int rv = session_->CreateCredentialFrame( - origin, domain_bound_cert_type_, domain_bound_private_key_, - domain_bound_cert_, priority_, &frame); + origin, + domain_bound_private_key_, + domain_bound_cert_, + priority_, + &frame); if (rv != OK) { DCHECK_NE(rv, ERR_IO_PENDING); return rv; diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h index 06209a1779..4d18e3eff3 100644 --- a/net/spdy/spdy_stream.h +++ b/net/spdy/spdy_stream.h @@ -541,7 +541,6 @@ class NET_EXPORT_PRIVATE SpdyStream { // Data received before delegate is attached. ScopedVector<SpdyBuffer> pending_buffers_; - SSLClientCertType domain_bound_cert_type_; std::string domain_bound_private_key_; std::string domain_bound_cert_; ServerBoundCertService::RequestHandle domain_bound_cert_request_handle_; diff --git a/net/ssl/default_server_bound_cert_store.cc b/net/ssl/default_server_bound_cert_store.cc index b189661899..6fb9180e87 100644 --- a/net/ssl/default_server_bound_cert_store.cc +++ b/net/ssl/default_server_bound_cert_store.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" +#include "net/base/net_errors.h" namespace net { @@ -60,16 +61,15 @@ DefaultServerBoundCertStore::GetServerBoundCertTask::~GetServerBoundCertTask() { void DefaultServerBoundCertStore::GetServerBoundCertTask::Run( DefaultServerBoundCertStore* store) { - SSLClientCertType type = CLIENT_CERT_INVALID_TYPE; base::Time expiration_time; std::string private_key_result; std::string cert_result; - bool was_sync = store->GetServerBoundCert( - server_identifier_, &type, &expiration_time, &private_key_result, + int err = store->GetServerBoundCert( + server_identifier_, &expiration_time, &private_key_result, &cert_result, GetCertCallback()); - DCHECK(was_sync); + DCHECK(err != ERR_IO_PENDING); - InvokeCallback(base::Bind(callback_, server_identifier_, type, + InvokeCallback(base::Bind(callback_, err, server_identifier_, expiration_time, private_key_result, cert_result)); } @@ -79,7 +79,6 @@ class DefaultServerBoundCertStore::SetServerBoundCertTask : public DefaultServerBoundCertStore::Task { public: SetServerBoundCertTask(const std::string& server_identifier, - SSLClientCertType type, base::Time creation_time, base::Time expiration_time, const std::string& private_key, @@ -89,7 +88,6 @@ class DefaultServerBoundCertStore::SetServerBoundCertTask private: std::string server_identifier_; - SSLClientCertType type_; base::Time creation_time_; base::Time expiration_time_; std::string private_key_; @@ -98,13 +96,11 @@ class DefaultServerBoundCertStore::SetServerBoundCertTask DefaultServerBoundCertStore::SetServerBoundCertTask::SetServerBoundCertTask( const std::string& server_identifier, - SSLClientCertType type, base::Time creation_time, base::Time expiration_time, const std::string& private_key, const std::string& cert) : server_identifier_(server_identifier), - type_(type), creation_time_(creation_time), expiration_time_(expiration_time), private_key_(private_key), @@ -116,7 +112,7 @@ DefaultServerBoundCertStore::SetServerBoundCertTask::~SetServerBoundCertTask() { void DefaultServerBoundCertStore::SetServerBoundCertTask::Run( DefaultServerBoundCertStore* store) { - store->SyncSetServerBoundCert(server_identifier_, type_, creation_time_, + store->SyncSetServerBoundCert(server_identifier_, creation_time_, expiration_time_, private_key_, cert_); } @@ -236,9 +232,8 @@ DefaultServerBoundCertStore::DefaultServerBoundCertStore( store_(store), weak_ptr_factory_(this) {} -bool DefaultServerBoundCertStore::GetServerBoundCert( +int DefaultServerBoundCertStore::GetServerBoundCert( const std::string& server_identifier, - SSLClientCertType* type, base::Time* expiration_time, std::string* private_key_result, std::string* cert_result, @@ -249,34 +244,30 @@ bool DefaultServerBoundCertStore::GetServerBoundCert( if (!loaded_) { EnqueueTask(scoped_ptr<Task>( new GetServerBoundCertTask(server_identifier, callback))); - return false; + return ERR_IO_PENDING; } ServerBoundCertMap::iterator it = server_bound_certs_.find(server_identifier); - if (it == server_bound_certs_.end()) { - *type = CLIENT_CERT_INVALID_TYPE; - return true; - } + if (it == server_bound_certs_.end()) + return ERR_FILE_NOT_FOUND; ServerBoundCert* cert = it->second; - *type = cert->type(); *expiration_time = cert->expiration_time(); *private_key_result = cert->private_key(); *cert_result = cert->cert(); - return true; + return OK; } void DefaultServerBoundCertStore::SetServerBoundCert( const std::string& server_identifier, - SSLClientCertType type, base::Time creation_time, base::Time expiration_time, const std::string& private_key, const std::string& cert) { RunOrEnqueueTask(scoped_ptr<Task>(new SetServerBoundCertTask( - server_identifier, type, creation_time, expiration_time, private_key, + server_identifier, creation_time, expiration_time, private_key, cert))); } @@ -377,7 +368,6 @@ void DefaultServerBoundCertStore::OnLoaded( void DefaultServerBoundCertStore::SyncSetServerBoundCert( const std::string& server_identifier, - SSLClientCertType type, base::Time creation_time, base::Time expiration_time, const std::string& private_key, @@ -389,7 +379,7 @@ void DefaultServerBoundCertStore::SyncSetServerBoundCert( InternalInsertServerBoundCert( server_identifier, new ServerBoundCert( - server_identifier, type, creation_time, expiration_time, private_key, + server_identifier, creation_time, expiration_time, private_key, cert)); } diff --git a/net/ssl/default_server_bound_cert_store.h b/net/ssl/default_server_bound_cert_store.h index 8ec680562c..61282182f8 100644 --- a/net/ssl/default_server_bound_cert_store.h +++ b/net/ssl/default_server_bound_cert_store.h @@ -43,16 +43,14 @@ class NET_EXPORT DefaultServerBoundCertStore : public ServerBoundCertStore { virtual ~DefaultServerBoundCertStore(); // ServerBoundCertStore implementation. - virtual bool GetServerBoundCert( + virtual int GetServerBoundCert( const std::string& server_identifier, - SSLClientCertType* type, base::Time* expiration_time, std::string* private_key_result, std::string* cert_result, const GetCertCallback& callback) OVERRIDE; virtual void SetServerBoundCert( const std::string& server_identifier, - SSLClientCertType type, base::Time creation_time, base::Time expiration_time, const std::string& private_key, @@ -110,7 +108,6 @@ class NET_EXPORT DefaultServerBoundCertStore : public ServerBoundCertStore { // initialization is complete. void SyncSetServerBoundCert( const std::string& server_identifier, - SSLClientCertType type, base::Time creation_time, base::Time expiration_time, const std::string& private_key, diff --git a/net/ssl/default_server_bound_cert_store_unittest.cc b/net/ssl/default_server_bound_cert_store_unittest.cc index 8673916435..c3f8452fa9 100644 --- a/net/ssl/default_server_bound_cert_store_unittest.cc +++ b/net/ssl/default_server_bound_cert_store_unittest.cc @@ -13,6 +13,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" +#include "net/base/net_errors.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -27,8 +28,8 @@ void NotCalled() { ADD_FAILURE() << "Unexpected callback execution."; } -void GetCertCallbackNotCalled(const std::string& server_identifier, - SSLClientCertType type, +void GetCertCallbackNotCalled(int err, + const std::string& server_identifier, base::Time expiration_time, const std::string& private_key_result, const std::string& cert_result) { @@ -39,21 +40,21 @@ class AsyncGetCertHelper { public: AsyncGetCertHelper() : called_(false) {} - void Callback(const std::string& server_identifier, - SSLClientCertType type, + void Callback(int err, + const std::string& server_identifier, base::Time expiration_time, const std::string& private_key_result, const std::string& cert_result) { + err_ = err; server_identifier_ = server_identifier; - type_ = type; expiration_time_ = expiration_time; private_key_ = private_key_result; cert_ = cert_result; called_ = true; } + int err_; std::string server_identifier_; - SSLClientCertType type_; base::Time expiration_time_; std::string private_key_; std::string cert_; @@ -127,14 +128,12 @@ TEST(DefaultServerBoundCertStoreTest, TestLoading) { persistent_store->AddServerBoundCert( DefaultServerBoundCertStore::ServerBoundCert( "google.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "a", "b")); persistent_store->AddServerBoundCert( DefaultServerBoundCertStore::ServerBoundCert( "verisign.com", - CLIENT_CERT_ECDSA_SIGN, base::Time(), base::Time(), "c", "d")); @@ -145,7 +144,6 @@ TEST(DefaultServerBoundCertStoreTest, TestLoading) { EXPECT_EQ(0, store.GetCertCount()); store.SetServerBoundCert( "verisign.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "e", "f"); @@ -154,7 +152,6 @@ TEST(DefaultServerBoundCertStoreTest, TestLoading) { EXPECT_EQ(2, store.GetCertCount()); store.SetServerBoundCert( "twitter.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "g", "h"); @@ -166,32 +163,28 @@ TEST(DefaultServerBoundCertStoreTest, TestLoading) { TEST(DefaultServerBoundCertStoreTest, TestSettingAndGetting) { // No persistent store, all calls will be synchronous. DefaultServerBoundCertStore store(NULL); - SSLClientCertType type; base::Time expiration_time; std::string private_key, cert; EXPECT_EQ(0, store.GetCertCount()); - EXPECT_TRUE(store.GetServerBoundCert("verisign.com", - &type, - &expiration_time, - &private_key, - &cert, - base::Bind(&GetCertCallbackNotCalled))); - EXPECT_EQ(CLIENT_CERT_INVALID_TYPE, type); + EXPECT_EQ(ERR_FILE_NOT_FOUND, + store.GetServerBoundCert("verisign.com", + &expiration_time, + &private_key, + &cert, + base::Bind(&GetCertCallbackNotCalled))); EXPECT_TRUE(private_key.empty()); EXPECT_TRUE(cert.empty()); store.SetServerBoundCert( "verisign.com", - CLIENT_CERT_RSA_SIGN, base::Time::FromInternalValue(123), base::Time::FromInternalValue(456), "i", "j"); - EXPECT_TRUE(store.GetServerBoundCert("verisign.com", - &type, - &expiration_time, - &private_key, - &cert, - base::Bind(&GetCertCallbackNotCalled))); - EXPECT_EQ(CLIENT_CERT_RSA_SIGN, type); + EXPECT_EQ(OK, + store.GetServerBoundCert("verisign.com", + &expiration_time, + &private_key, + &cert, + base::Bind(&GetCertCallbackNotCalled))); EXPECT_EQ(456, expiration_time.ToInternalValue()); EXPECT_EQ("i", private_key); EXPECT_EQ("j", cert); @@ -201,19 +194,16 @@ TEST(DefaultServerBoundCertStoreTest, TestDuplicateCerts) { scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); DefaultServerBoundCertStore store(persistent_store.get()); - SSLClientCertType type; base::Time expiration_time; std::string private_key, cert; EXPECT_EQ(0, store.GetCertCount()); store.SetServerBoundCert( "verisign.com", - CLIENT_CERT_RSA_SIGN, base::Time::FromInternalValue(123), base::Time::FromInternalValue(1234), "a", "b"); store.SetServerBoundCert( "verisign.com", - CLIENT_CERT_ECDSA_SIGN, base::Time::FromInternalValue(456), base::Time::FromInternalValue(4567), "c", "d"); @@ -221,13 +211,12 @@ TEST(DefaultServerBoundCertStoreTest, TestDuplicateCerts) { // Wait for load & queued set tasks. base::MessageLoop::current()->RunUntilIdle(); EXPECT_EQ(1, store.GetCertCount()); - EXPECT_TRUE(store.GetServerBoundCert("verisign.com", - &type, - &expiration_time, - &private_key, - &cert, - base::Bind(&GetCertCallbackNotCalled))); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type); + EXPECT_EQ(OK, + store.GetServerBoundCert("verisign.com", + &expiration_time, + &private_key, + &cert, + base::Bind(&GetCertCallbackNotCalled))); EXPECT_EQ(4567, expiration_time.ToInternalValue()); EXPECT_EQ("c", private_key); EXPECT_EQ("d", cert); @@ -237,29 +226,31 @@ TEST(DefaultServerBoundCertStoreTest, TestAsyncGet) { scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( "verisign.com", - CLIENT_CERT_RSA_SIGN, base::Time::FromInternalValue(123), base::Time::FromInternalValue(1234), "a", "b")); DefaultServerBoundCertStore store(persistent_store.get()); AsyncGetCertHelper helper; - SSLClientCertType type; base::Time expiration_time; std::string private_key; std::string cert = "not set"; EXPECT_EQ(0, store.GetCertCount()); - EXPECT_FALSE(store.GetServerBoundCert( - "verisign.com", &type, &expiration_time, &private_key, &cert, - base::Bind(&AsyncGetCertHelper::Callback, base::Unretained(&helper)))); + EXPECT_EQ(ERR_IO_PENDING, + store.GetServerBoundCert("verisign.com", + &expiration_time, + &private_key, + &cert, + base::Bind(&AsyncGetCertHelper::Callback, + base::Unretained(&helper)))); // Wait for load & queued get tasks. base::MessageLoop::current()->RunUntilIdle(); EXPECT_EQ(1, store.GetCertCount()); EXPECT_EQ("not set", cert); EXPECT_TRUE(helper.called_); + EXPECT_EQ(OK, helper.err_); EXPECT_EQ("verisign.com", helper.server_identifier_); - EXPECT_EQ(CLIENT_CERT_RSA_SIGN, helper.type_); EXPECT_EQ(1234, helper.expiration_time_.ToInternalValue()); EXPECT_EQ("a", helper.private_key_); EXPECT_EQ("b", helper.cert_); @@ -271,19 +262,16 @@ TEST(DefaultServerBoundCertStoreTest, TestDeleteAll) { store.SetServerBoundCert( "verisign.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "a", "b"); store.SetServerBoundCert( "google.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "c", "d"); store.SetServerBoundCert( "harvard.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "e", "f"); @@ -301,13 +289,11 @@ TEST(DefaultServerBoundCertStoreTest, TestAsyncGetAndDeleteAll) { scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( "verisign.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "a", "b")); persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( "google.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "c", "d")); @@ -333,13 +319,11 @@ TEST(DefaultServerBoundCertStoreTest, TestDelete) { scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); DefaultServerBoundCertStore store(persistent_store.get()); - SSLClientCertType type; base::Time expiration_time; std::string private_key, cert; EXPECT_EQ(0, store.GetCertCount()); store.SetServerBoundCert( "verisign.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "a", "b"); @@ -348,7 +332,6 @@ TEST(DefaultServerBoundCertStoreTest, TestDelete) { store.SetServerBoundCert( "google.com", - CLIENT_CERT_ECDSA_SIGN, base::Time(), base::Time(), "c", "d"); @@ -359,45 +342,40 @@ TEST(DefaultServerBoundCertStoreTest, TestDelete) { base::Bind(&CallCounter, &delete_finished)); ASSERT_EQ(1, delete_finished); EXPECT_EQ(1, store.GetCertCount()); - EXPECT_TRUE(store.GetServerBoundCert("verisign.com", - &type, - &expiration_time, - &private_key, - &cert, - base::Bind(&GetCertCallbackNotCalled))); - EXPECT_EQ(CLIENT_CERT_INVALID_TYPE, type); - EXPECT_TRUE(store.GetServerBoundCert("google.com", - &type, - &expiration_time, - &private_key, - &cert, - base::Bind(&GetCertCallbackNotCalled))); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type); + EXPECT_EQ(ERR_FILE_NOT_FOUND, + store.GetServerBoundCert("verisign.com", + &expiration_time, + &private_key, + &cert, + base::Bind(&GetCertCallbackNotCalled))); + EXPECT_EQ(OK, + store.GetServerBoundCert("google.com", + &expiration_time, + &private_key, + &cert, + base::Bind(&GetCertCallbackNotCalled))); int delete2_finished = 0; store.DeleteServerBoundCert("google.com", base::Bind(&CallCounter, &delete2_finished)); ASSERT_EQ(1, delete2_finished); EXPECT_EQ(0, store.GetCertCount()); - EXPECT_TRUE(store.GetServerBoundCert("google.com", - &type, - &expiration_time, - &private_key, - &cert, - base::Bind(&GetCertCallbackNotCalled))); - EXPECT_EQ(CLIENT_CERT_INVALID_TYPE, type); + EXPECT_EQ(ERR_FILE_NOT_FOUND, + store.GetServerBoundCert("google.com", + &expiration_time, + &private_key, + &cert, + base::Bind(&GetCertCallbackNotCalled))); } TEST(DefaultServerBoundCertStoreTest, TestAsyncDelete) { scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( "a.com", - CLIENT_CERT_RSA_SIGN, base::Time::FromInternalValue(1), base::Time::FromInternalValue(2), "a", "b")); persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( "b.com", - CLIENT_CERT_RSA_SIGN, base::Time::FromInternalValue(3), base::Time::FromInternalValue(4), "c", "d")); @@ -408,17 +386,20 @@ TEST(DefaultServerBoundCertStoreTest, TestAsyncDelete) { AsyncGetCertHelper a_helper; AsyncGetCertHelper b_helper; - SSLClientCertType type; base::Time expiration_time; std::string private_key; std::string cert = "not set"; EXPECT_EQ(0, store.GetCertCount()); - EXPECT_FALSE(store.GetServerBoundCert( - "a.com", &type, &expiration_time, &private_key, &cert, - base::Bind(&AsyncGetCertHelper::Callback, base::Unretained(&a_helper)))); - EXPECT_FALSE(store.GetServerBoundCert( - "b.com", &type, &expiration_time, &private_key, &cert, - base::Bind(&AsyncGetCertHelper::Callback, base::Unretained(&b_helper)))); + EXPECT_EQ(ERR_IO_PENDING, + store.GetServerBoundCert( + "a.com", &expiration_time, &private_key, &cert, + base::Bind(&AsyncGetCertHelper::Callback, + base::Unretained(&a_helper)))); + EXPECT_EQ(ERR_IO_PENDING, + store.GetServerBoundCert( + "b.com", &expiration_time, &private_key, &cert, + base::Bind(&AsyncGetCertHelper::Callback, + base::Unretained(&b_helper)))); EXPECT_EQ(0, delete_finished); EXPECT_FALSE(a_helper.called_); @@ -429,14 +410,14 @@ TEST(DefaultServerBoundCertStoreTest, TestAsyncDelete) { EXPECT_EQ(1, store.GetCertCount()); EXPECT_EQ("not set", cert); EXPECT_TRUE(a_helper.called_); + EXPECT_EQ(ERR_FILE_NOT_FOUND, a_helper.err_); EXPECT_EQ("a.com", a_helper.server_identifier_); - EXPECT_EQ(CLIENT_CERT_INVALID_TYPE, a_helper.type_); EXPECT_EQ(0, a_helper.expiration_time_.ToInternalValue()); EXPECT_EQ("", a_helper.private_key_); EXPECT_EQ("", a_helper.cert_); EXPECT_TRUE(b_helper.called_); + EXPECT_EQ(OK, b_helper.err_); EXPECT_EQ("b.com", b_helper.server_identifier_); - EXPECT_EQ(CLIENT_CERT_RSA_SIGN, b_helper.type_); EXPECT_EQ(4, b_helper.expiration_time_.ToInternalValue()); EXPECT_EQ("c", b_helper.private_key_); EXPECT_EQ("d", b_helper.cert_); @@ -449,25 +430,21 @@ TEST(DefaultServerBoundCertStoreTest, TestGetAll) { EXPECT_EQ(0, store.GetCertCount()); store.SetServerBoundCert( "verisign.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "a", "b"); store.SetServerBoundCert( "google.com", - CLIENT_CERT_ECDSA_SIGN, base::Time(), base::Time(), "c", "d"); store.SetServerBoundCert( "harvard.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "e", "f"); store.SetServerBoundCert( "mit.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "g", "h"); @@ -486,13 +463,11 @@ TEST(DefaultServerBoundCertStoreTest, TestInitializeFrom) { store.SetServerBoundCert( "preexisting.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "a", "b"); store.SetServerBoundCert( "both.com", - CLIENT_CERT_ECDSA_SIGN, base::Time(), base::Time(), "c", "d"); @@ -503,14 +478,12 @@ TEST(DefaultServerBoundCertStoreTest, TestInitializeFrom) { ServerBoundCertStore::ServerBoundCertList source_certs; source_certs.push_back(ServerBoundCertStore::ServerBoundCert( "both.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), // Key differs from above to test that existing entries are overwritten. "e", "f")); source_certs.push_back(ServerBoundCertStore::ServerBoundCert( "copied.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "g", "h")); @@ -538,13 +511,11 @@ TEST(DefaultServerBoundCertStoreTest, TestAsyncInitializeFrom) { scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore); persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( "preexisting.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "a", "b")); persistent_store->AddServerBoundCert(ServerBoundCertStore::ServerBoundCert( "both.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "c", "d")); @@ -553,14 +524,12 @@ TEST(DefaultServerBoundCertStoreTest, TestAsyncInitializeFrom) { ServerBoundCertStore::ServerBoundCertList source_certs; source_certs.push_back(ServerBoundCertStore::ServerBoundCert( "both.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), // Key differs from above to test that existing entries are overwritten. "e", "f")); source_certs.push_back(ServerBoundCertStore::ServerBoundCert( "copied.com", - CLIENT_CERT_RSA_SIGN, base::Time(), base::Time(), "g", "h")); diff --git a/net/ssl/server_bound_cert_service.cc b/net/ssl/server_bound_cert_service.cc index 37404699f2..4bc82ed5d9 100644 --- a/net/ssl/server_bound_cert_service.cc +++ b/net/ssl/server_bound_cert_service.cc @@ -42,15 +42,6 @@ const int kValidityPeriodInDays = 365; // while. const int kSystemTimeValidityBufferInDays = 90; -bool IsSupportedCertType(uint8 type) { - switch(type) { - case CLIENT_CERT_ECDSA_SIGN: - return true; - default: - return false; - } -} - // Used by the GetDomainBoundCertResult histogram to record the final // outcome of each GetDomainBoundCert call. Do not re-use values. enum GetCertResult { @@ -96,7 +87,6 @@ void RecordGetCertTime(base::TimeDelta request_time) { // unjoined thread, due to relying on a non-leaked LazyInstance scoped_ptr<ServerBoundCertStore::ServerBoundCert> GenerateCert( const std::string& server_identifier, - SSLClientCertType type, uint32 serial_number, int* error) { scoped_ptr<ServerBoundCertStore::ServerBoundCert> result; @@ -107,34 +97,25 @@ scoped_ptr<ServerBoundCertStore::ServerBoundCert> GenerateCert( not_valid_before + base::TimeDelta::FromDays(kValidityPeriodInDays); std::string der_cert; std::vector<uint8> private_key_info; - switch (type) { - case CLIENT_CERT_ECDSA_SIGN: { - scoped_ptr<crypto::ECPrivateKey> key(crypto::ECPrivateKey::Create()); - if (!key.get()) { - DLOG(ERROR) << "Unable to create key pair for client"; - *error = ERR_KEY_GENERATION_FAILED; - return result.Pass(); - } - if (!x509_util::CreateDomainBoundCertEC(key.get(), server_identifier, - serial_number, not_valid_before, - not_valid_after, &der_cert)) { - DLOG(ERROR) << "Unable to create x509 cert for client"; - *error = ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED; - return result.Pass(); - } + scoped_ptr<crypto::ECPrivateKey> key(crypto::ECPrivateKey::Create()); + if (!key.get()) { + DLOG(ERROR) << "Unable to create key pair for client"; + *error = ERR_KEY_GENERATION_FAILED; + return result.Pass(); + } + if (!x509_util::CreateDomainBoundCertEC(key.get(), server_identifier, + serial_number, not_valid_before, + not_valid_after, &der_cert)) { + DLOG(ERROR) << "Unable to create x509 cert for client"; + *error = ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED; + return result.Pass(); + } - if (!key->ExportEncryptedPrivateKey(ServerBoundCertService::kEPKIPassword, - 1, &private_key_info)) { - DLOG(ERROR) << "Unable to export private key"; - *error = ERR_PRIVATE_KEY_EXPORT_FAILED; - return result.Pass(); - } - break; - } - default: - NOTREACHED(); - *error = ERR_INVALID_ARGUMENT; - return result.Pass(); + if (!key->ExportEncryptedPrivateKey(ServerBoundCertService::kEPKIPassword, + 1, &private_key_info)) { + DLOG(ERROR) << "Unable to export private key"; + *error = ERR_PRIVATE_KEY_EXPORT_FAILED; + return result.Pass(); } // TODO(rkn): Perhaps ExportPrivateKey should be changed to output a @@ -142,7 +123,10 @@ scoped_ptr<ServerBoundCertStore::ServerBoundCert> GenerateCert( std::string key_out(private_key_info.begin(), private_key_info.end()); result.reset(new ServerBoundCertStore::ServerBoundCert( - server_identifier, type, not_valid_before, not_valid_after, key_out, + server_identifier, + not_valid_before, + not_valid_after, + key_out, der_cert)); UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.GenerateCertTime", base::TimeTicks::Now() - start, @@ -160,12 +144,10 @@ class ServerBoundCertServiceRequest { public: ServerBoundCertServiceRequest(base::TimeTicks request_start, const CompletionCallback& callback, - SSLClientCertType* type, std::string* private_key, std::string* cert) : request_start_(request_start), callback_(callback), - type_(type), private_key_(private_key), cert_(cert) { } @@ -174,7 +156,6 @@ class ServerBoundCertServiceRequest { void Cancel() { RecordGetDomainBoundCertResult(ASYNC_CANCELLED); callback_.Reset(); - type_ = NULL; private_key_ = NULL; cert_ = NULL; } @@ -182,7 +163,6 @@ class ServerBoundCertServiceRequest { // Copies the contents of |private_key| and |cert| to the caller's output // arguments and calls the callback. void Post(int error, - SSLClientCertType type, const std::string& private_key, const std::string& cert) { switch (error) { @@ -214,7 +194,6 @@ class ServerBoundCertServiceRequest { break; } if (!callback_.is_null()) { - *type_ = type; *private_key_ = private_key; *cert_ = cert; callback_.Run(error); @@ -227,7 +206,6 @@ class ServerBoundCertServiceRequest { private: base::TimeTicks request_start_; CompletionCallback callback_; - SSLClientCertType* type_; std::string* private_key_; std::string* cert_; }; @@ -244,10 +222,8 @@ class ServerBoundCertServiceWorker { ServerBoundCertServiceWorker( const std::string& server_identifier, - SSLClientCertType type, const WorkerDoneCallback& callback) : server_identifier_(server_identifier), - type_(type), serial_number_(base::RandInt(0, std::numeric_limits<int>::max())), origin_loop_(base::MessageLoopProxy::current()), callback_(callback) { @@ -269,9 +245,8 @@ class ServerBoundCertServiceWorker { // Runs on a worker thread. int error = ERR_FAILED; scoped_ptr<ServerBoundCertStore::ServerBoundCert> cert = - GenerateCert(server_identifier_, type_, serial_number_, &error); - DVLOG(1) << "GenerateCert " << server_identifier_ << " " << type_ - << " returned " << error; + GenerateCert(server_identifier_, serial_number_, &error); + DVLOG(1) << "GenerateCert " << server_identifier_ << " returned " << error; #if defined(USE_NSS) // Detach the thread from NSPR. // Calling NSS functions attaches the thread to NSPR, which stores @@ -288,7 +263,6 @@ class ServerBoundCertServiceWorker { } const std::string server_identifier_; - const SSLClientCertType type_; // Note that serial_number_ must be initialized on a non-worker thread // (see documentation for GenerateCert). uint32 serial_number_; @@ -303,31 +277,25 @@ class ServerBoundCertServiceWorker { // origin message loop. class ServerBoundCertServiceJob { public: - ServerBoundCertServiceJob(SSLClientCertType type) - : type_(type) { - } + ServerBoundCertServiceJob() { } ~ServerBoundCertServiceJob() { if (!requests_.empty()) DeleteAllCanceled(); } - SSLClientCertType type() const { return type_; } - void AddRequest(ServerBoundCertServiceRequest* request) { requests_.push_back(request); } void HandleResult(int error, - SSLClientCertType type, const std::string& private_key, const std::string& cert) { - PostAll(error, type, private_key, cert); + PostAll(error, private_key, cert); } private: void PostAll(int error, - SSLClientCertType type, const std::string& private_key, const std::string& cert) { std::vector<ServerBoundCertServiceRequest*> requests; @@ -335,7 +303,7 @@ class ServerBoundCertServiceJob { for (std::vector<ServerBoundCertServiceRequest*>::iterator i = requests.begin(); i != requests.end(); i++) { - (*i)->Post(error, type, private_key, cert); + (*i)->Post(error, private_key, cert); // Post() causes the ServerBoundCertServiceRequest to delete itself. } } @@ -352,7 +320,6 @@ class ServerBoundCertServiceJob { } std::vector<ServerBoundCertServiceRequest*> requests_; - SSLClientCertType type_; }; // static @@ -399,7 +366,8 @@ ServerBoundCertService::ServerBoundCertService( weak_ptr_factory_(this), requests_(0), cert_store_hits_(0), - inflight_joins_(0) { + inflight_joins_(0), + workers_created_(0) { base::Time start = base::Time::Now(); base::Time end = start + base::TimeDelta::FromDays( kValidityPeriodInDays + kSystemTimeValidityBufferInDays); @@ -422,20 +390,15 @@ std::string ServerBoundCertService::GetDomainForHost(const std::string& host) { int ServerBoundCertService::GetDomainBoundCert( const std::string& host, - const std::vector<uint8>& requested_types, - SSLClientCertType* type, std::string* private_key, std::string* cert, const CompletionCallback& callback, RequestHandle* out_req) { - DVLOG(1) << __FUNCTION__ << " " << host << " " - << (requested_types.empty() ? -1 : requested_types[0]) - << (requested_types.size() > 1 ? "..." : ""); + DVLOG(1) << __FUNCTION__ << " " << host; DCHECK(CalledOnValidThread()); base::TimeTicks request_start = base::TimeTicks::Now(); - if (callback.is_null() || !private_key || !cert || host.empty() || - requested_types.empty()) { + if (callback.is_null() || !private_key || !cert || host.empty()) { RecordGetDomainBoundCertResult(INVALID_ARGUMENT); return ERR_INVALID_ARGUMENT; } @@ -446,19 +409,6 @@ int ServerBoundCertService::GetDomainBoundCert( return ERR_INVALID_ARGUMENT; } - SSLClientCertType preferred_type = CLIENT_CERT_INVALID_TYPE; - for (size_t i = 0; i < requested_types.size(); ++i) { - if (IsSupportedCertType(requested_types[i])) { - preferred_type = static_cast<SSLClientCertType>(requested_types[i]); - break; - } - } - if (preferred_type == CLIENT_CERT_INVALID_TYPE) { - RecordGetDomainBoundCertResult(UNSUPPORTED_TYPE); - // None of the requested types are supported. - return ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED; - } - requests_++; // See if an identical request is currently in flight. @@ -469,26 +419,13 @@ int ServerBoundCertService::GetDomainBoundCert( // An identical request is in flight already. We'll just attach our // callback. job = j->second; - // Check that the job is for an acceptable type of cert. - if (std::find(requested_types.begin(), requested_types.end(), job->type()) - == requested_types.end()) { - DVLOG(1) << "Found inflight job of wrong type " << job->type() - << " for " << domain; - // If we get here, the server is asking for different types of certs in - // short succession. This probably means the server is broken or - // misconfigured. Since we only store one type of cert per domain, we - // are unable to handle this well. Just return an error and let the first - // job finish. - RecordGetDomainBoundCertResult(TYPE_MISMATCH); - return ERR_ORIGIN_BOUND_CERT_GENERATION_TYPE_MISMATCH; - } inflight_joins_++; ServerBoundCertServiceRequest* request = new ServerBoundCertServiceRequest( request_start, base::Bind(&RequestHandle::OnRequestComplete, base::Unretained(out_req)), - type, private_key, cert); + private_key, cert); job->AddRequest(request); out_req->RequestStarted(this, request, callback); return ERR_IO_PENDING; @@ -498,30 +435,30 @@ int ServerBoundCertService::GetDomainBoundCert( // domain. Note that |expiration_time| is ignored, and expired certs are // considered valid. base::Time expiration_time; - if (server_bound_cert_store_->GetServerBoundCert( - domain, - type, - &expiration_time /* ignored */, - private_key, - cert, - base::Bind(&ServerBoundCertService::GotServerBoundCert, - weak_ptr_factory_.GetWeakPtr()))) { - if (IsSupportedCertType(*type)) { - // Sync lookup found a valid cert. - DVLOG(1) << "Cert store had valid cert for " << domain - << " of type " << *type; - cert_store_hits_++; - RecordGetDomainBoundCertResult(SYNC_SUCCESS); - base::TimeDelta request_time = base::TimeTicks::Now() - request_start; - UMA_HISTOGRAM_TIMES("DomainBoundCerts.GetCertTimeSync", request_time); - RecordGetCertTime(request_time); - return OK; - } + int err = server_bound_cert_store_->GetServerBoundCert( + domain, + &expiration_time /* ignored */, + private_key, + cert, + base::Bind(&ServerBoundCertService::GotServerBoundCert, + weak_ptr_factory_.GetWeakPtr())); + if (err == OK) { + // Sync lookup found a valid cert. + DVLOG(1) << "Cert store had valid cert for " << domain; + cert_store_hits_++; + RecordGetDomainBoundCertResult(SYNC_SUCCESS); + base::TimeDelta request_time = base::TimeTicks::Now() - request_start; + UMA_HISTOGRAM_TIMES("DomainBoundCerts.GetCertTimeSync", request_time); + RecordGetCertTime(request_time); + return OK; + } + + if (err == ERR_FILE_NOT_FOUND) { // Sync lookup did not find a valid cert. Start generating a new one. + workers_created_++; ServerBoundCertServiceWorker* worker = new ServerBoundCertServiceWorker( domain, - preferred_type, base::Bind(&ServerBoundCertService::GeneratedServerBoundCert, weak_ptr_factory_.GetWeakPtr())); if (!worker->Start(task_runner_)) { @@ -532,23 +469,28 @@ int ServerBoundCertService::GetDomainBoundCert( } } - // We are either waiting for async DB lookup, or waiting for cert generation. - // Create a job & request to track it. - job = new ServerBoundCertServiceJob(preferred_type); - inflight_[domain] = job; - - ServerBoundCertServiceRequest* request = new ServerBoundCertServiceRequest( - request_start, - base::Bind(&RequestHandle::OnRequestComplete, base::Unretained(out_req)), - type, private_key, cert); - job->AddRequest(request); - out_req->RequestStarted(this, request, callback); - return ERR_IO_PENDING; + if (err == ERR_IO_PENDING || err == ERR_FILE_NOT_FOUND) { + // We are either waiting for async DB lookup, or waiting for cert + // generation. Create a job & request to track it. + job = new ServerBoundCertServiceJob(); + inflight_[domain] = job; + + ServerBoundCertServiceRequest* request = new ServerBoundCertServiceRequest( + request_start, + base::Bind(&RequestHandle::OnRequestComplete, + base::Unretained(out_req)), + private_key, cert); + job->AddRequest(request); + out_req->RequestStarted(this, request, callback); + return ERR_IO_PENDING; + } + + return err; } void ServerBoundCertService::GotServerBoundCert( + int err, const std::string& server_identifier, - SSLClientCertType type, base::Time expiration_time, const std::string& key, const std::string& cert) { @@ -560,22 +502,19 @@ void ServerBoundCertService::GotServerBoundCert( NOTREACHED(); return; } - ServerBoundCertServiceJob* job = j->second; - if (IsSupportedCertType(type)) { + if (err == OK) { // Async DB lookup found a valid cert. - DVLOG(1) << "Cert store had valid cert for " << server_identifier - << " of type " << type; + DVLOG(1) << "Cert store had valid cert for " << server_identifier; cert_store_hits_++; // ServerBoundCertServiceRequest::Post will do the histograms and stuff. - HandleResult(OK, server_identifier, type, key, cert); + HandleResult(OK, server_identifier, key, cert); return; } - // Async lookup did not find a valid cert. Start generating a new one. + workers_created_++; ServerBoundCertServiceWorker* worker = new ServerBoundCertServiceWorker( server_identifier, - job->type(), base::Bind(&ServerBoundCertService::GeneratedServerBoundCert, weak_ptr_factory_.GetWeakPtr())); if (!worker->Start(task_runner_)) { @@ -583,7 +522,6 @@ void ServerBoundCertService::GotServerBoundCert( LOG(ERROR) << "ServerBoundCertServiceWorker couldn't be started."; HandleResult(ERR_INSUFFICIENT_RESOURCES, server_identifier, - CLIENT_CERT_INVALID_TYPE, std::string(), std::string()); return; @@ -609,24 +547,21 @@ void ServerBoundCertService::GeneratedServerBoundCert( // TODO(mattm): we should just Pass() the cert object to // SetServerBoundCert(). server_bound_cert_store_->SetServerBoundCert( - cert->server_identifier(), cert->type(), cert->creation_time(), - cert->expiration_time(), cert->private_key(), cert->cert()); + cert->server_identifier(), + cert->creation_time(), + cert->expiration_time(), + cert->private_key(), + cert->cert()); - HandleResult(error, server_identifier, cert->type(), cert->private_key(), - cert->cert()); + HandleResult(error, server_identifier, cert->private_key(), cert->cert()); } else { - HandleResult(error, - server_identifier, - CLIENT_CERT_INVALID_TYPE, - std::string(), - std::string()); + HandleResult(error, server_identifier, std::string(), std::string()); } } void ServerBoundCertService::HandleResult( int error, const std::string& server_identifier, - SSLClientCertType type, const std::string& private_key, const std::string& cert) { DCHECK(CalledOnValidThread()); @@ -640,7 +575,7 @@ void ServerBoundCertService::HandleResult( ServerBoundCertServiceJob* job = j->second; inflight_.erase(j); - job->HandleResult(error, type, private_key, cert); + job->HandleResult(error, private_key, cert); delete job; } diff --git a/net/ssl/server_bound_cert_service.h b/net/ssl/server_bound_cert_service.h index dd5059071a..d931ec8708 100644 --- a/net/ssl/server_bound_cert_service.h +++ b/net/ssl/server_bound_cert_service.h @@ -17,7 +17,6 @@ #include "net/base/completion_callback.h" #include "net/base/net_export.h" #include "net/ssl/server_bound_cert_store.h" -#include "net/ssl/ssl_client_cert_type.h" namespace base { class TaskRunner; @@ -92,17 +91,13 @@ class NET_EXPORT ServerBoundCertService // longer hold. bool IsSystemTimeValid() const { return is_system_time_valid_; } - // Fetches the domain bound cert for the specified host of the specified - // type if one exists and creates one otherwise. Returns OK if successful or - // an error code upon failure. - // - // |requested_types| is a list of the TLS ClientCertificateTypes the site will - // accept, ordered from most preferred to least preferred. Types we don't - // support will be ignored. See ssl_client_cert_type.h. + // Fetches the domain bound cert for the specified host if one exists and + // creates one otherwise. Returns OK if successful or an error code upon + // failure. // // On successful completion, |private_key| stores a DER-encoded - // PrivateKeyInfo struct, and |cert| stores a DER-encoded certificate, and - // |type| specifies the type of certificate that was returned. + // PrivateKeyInfo struct, and |cert| stores a DER-encoded certificate. + // The PrivateKeyInfo is always an ECDSA private key. // // |callback| must not be null. ERR_IO_PENDING is returned if the operation // could not be completed immediately, in which case the result code will @@ -113,8 +108,6 @@ class NET_EXPORT ServerBoundCertService // ServerBoundCertService is destroyed. int GetDomainBoundCert( const std::string& host, - const std::vector<uint8>& requested_types, - SSLClientCertType* type, std::string* private_key, std::string* cert, const CompletionCallback& callback, @@ -128,6 +121,7 @@ class NET_EXPORT ServerBoundCertService uint64 requests() const { return requests_; } uint64 cert_store_hits() const { return cert_store_hits_; } uint64 inflight_joins() const { return inflight_joins_; } + uint64 workers_created() const { return workers_created_; } private: // Cancels the specified request. |req| is the handle stored by @@ -135,8 +129,8 @@ class NET_EXPORT ServerBoundCertService // callback will not be called. void CancelRequest(ServerBoundCertServiceRequest* req); - void GotServerBoundCert(const std::string& server_identifier, - SSLClientCertType type, + void GotServerBoundCert(int err, + const std::string& server_identifier, base::Time expiration_time, const std::string& key, const std::string& cert); @@ -146,7 +140,6 @@ class NET_EXPORT ServerBoundCertService scoped_ptr<ServerBoundCertStore::ServerBoundCert> cert); void HandleResult(int error, const std::string& server_identifier, - SSLClientCertType type, const std::string& private_key, const std::string& cert); @@ -161,6 +154,7 @@ class NET_EXPORT ServerBoundCertService uint64 requests_; uint64 cert_store_hits_; uint64 inflight_joins_; + uint64 workers_created_; bool is_system_time_valid_; diff --git a/net/ssl/server_bound_cert_service_unittest.cc b/net/ssl/server_bound_cert_service_unittest.cc index 37a86a483a..0063f49603 100644 --- a/net/ssl/server_bound_cert_service_unittest.cc +++ b/net/ssl/server_bound_cert_service_unittest.cc @@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" +#include "base/task_runner.h" #include "base/threading/sequenced_worker_pool.h" #include "crypto/ec_private_key.h" #include "net/base/net_errors.h" @@ -47,6 +48,66 @@ class ServerBoundCertServiceTest : public testing::Test { scoped_ptr<ServerBoundCertService> service_; }; +class MockServerBoundCertStoreWithAsyncGet + : public DefaultServerBoundCertStore { + public: + MockServerBoundCertStoreWithAsyncGet() + : DefaultServerBoundCertStore(NULL), cert_count_(0) {} + + virtual int GetServerBoundCert(const std::string& server_identifier, + base::Time* expiration_time, + std::string* private_key_result, + std::string* cert_result, + const GetCertCallback& callback) OVERRIDE; + + virtual void SetServerBoundCert(const std::string& server_identifier, + base::Time creation_time, + base::Time expiration_time, + const std::string& private_key, + const std::string& cert) OVERRIDE { + cert_count_ = 1; + } + + virtual int GetCertCount() OVERRIDE { return cert_count_; } + + void CallGetServerBoundCertCallbackWithResult(int err, + base::Time expiration_time, + const std::string& private_key, + const std::string& cert); + + private: + GetCertCallback callback_; + std::string server_identifier_; + int cert_count_; +}; + +int MockServerBoundCertStoreWithAsyncGet::GetServerBoundCert( + const std::string& server_identifier, + base::Time* expiration_time, + std::string* private_key_result, + std::string* cert_result, + const GetCertCallback& callback) { + server_identifier_ = server_identifier; + callback_ = callback; + // Reset the cert count, it'll get incremented in either SetServerBoundCert or + // CallGetServerBoundCertCallbackWithResult. + cert_count_ = 0; + // Do nothing else: the results to be provided will be specified through + // CallGetServerBoundCertCallbackWithResult. + return ERR_IO_PENDING; +} + +void +MockServerBoundCertStoreWithAsyncGet::CallGetServerBoundCertCallbackWithResult( + int err, + base::Time expiration_time, + const std::string& private_key, + const std::string& cert) { + if (err == OK) + cert_count_ = 1; + callback_.Run(err, server_identifier_, expiration_time, private_key, cert); +} + TEST_F(ServerBoundCertServiceTest, GetDomainForHost) { EXPECT_EQ("google.com", ServerBoundCertService::GetDomainForHost("google.com")); @@ -73,38 +134,32 @@ TEST_F(ServerBoundCertServiceTest, CacheHit) { std::string host("encrypted.google.com"); int error; - std::vector<uint8> types; - types.push_back(CLIENT_CERT_ECDSA_SIGN); TestCompletionCallback callback; ServerBoundCertService::RequestHandle request_handle; // Asynchronous completion. - SSLClientCertType type1; std::string private_key_info1, der_cert1; EXPECT_EQ(0, service_->cert_count()); error = service_->GetDomainBoundCert( - host, types, &type1, &private_key_info1, &der_cert1, + host, &private_key_info1, &der_cert1, callback.callback(), &request_handle); EXPECT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle.is_active()); error = callback.WaitForResult(); EXPECT_EQ(OK, error); EXPECT_EQ(1, service_->cert_count()); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1); EXPECT_FALSE(private_key_info1.empty()); EXPECT_FALSE(der_cert1.empty()); EXPECT_FALSE(request_handle.is_active()); // Synchronous completion. - SSLClientCertType type2; std::string private_key_info2, der_cert2; error = service_->GetDomainBoundCert( - host, types, &type2, &private_key_info2, &der_cert2, + host, &private_key_info2, &der_cert2, callback.callback(), &request_handle); EXPECT_FALSE(request_handle.is_active()); EXPECT_EQ(OK, error); EXPECT_EQ(1, service_->cert_count()); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2); EXPECT_EQ(private_key_info1, private_key_info2); EXPECT_EQ(der_cert1, der_cert2); @@ -113,97 +168,16 @@ TEST_F(ServerBoundCertServiceTest, CacheHit) { EXPECT_EQ(0u, service_->inflight_joins()); } -TEST_F(ServerBoundCertServiceTest, UnsupportedTypes) { - std::string host("encrypted.google.com"); - - int error; - std::vector<uint8> types; - TestCompletionCallback callback; - ServerBoundCertService::RequestHandle request_handle; - - // Empty requested_types. - SSLClientCertType type1; - std::string private_key_info1, der_cert1; - error = service_->GetDomainBoundCert( - host, types, &type1, &private_key_info1, &der_cert1, - callback.callback(), &request_handle); - EXPECT_EQ(ERR_INVALID_ARGUMENT, error); - EXPECT_FALSE(request_handle.is_active()); - - // No supported types in requested_types. - types.push_back(CLIENT_CERT_RSA_SIGN); - types.push_back(2); - types.push_back(3); - error = service_->GetDomainBoundCert( - host, types, &type1, &private_key_info1, &der_cert1, - callback.callback(), &request_handle); - EXPECT_EQ(ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED, error); - EXPECT_FALSE(request_handle.is_active()); - - // Supported types after unsupported ones in requested_types. - types.push_back(CLIENT_CERT_ECDSA_SIGN); - // Asynchronous completion. - EXPECT_EQ(0, service_->cert_count()); - error = service_->GetDomainBoundCert( - host, types, &type1, &private_key_info1, &der_cert1, - callback.callback(), &request_handle); - EXPECT_EQ(ERR_IO_PENDING, error); - EXPECT_TRUE(request_handle.is_active()); - error = callback.WaitForResult(); - EXPECT_EQ(OK, error); - EXPECT_EQ(1, service_->cert_count()); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1); - EXPECT_FALSE(private_key_info1.empty()); - EXPECT_FALSE(der_cert1.empty()); - - // Now that the cert is created, doing requests for unsupported types - // shouldn't affect the created cert. - // Empty requested_types. - types.clear(); - SSLClientCertType type2; - std::string private_key_info2, der_cert2; - error = service_->GetDomainBoundCert( - host, types, &type2, &private_key_info2, &der_cert2, - callback.callback(), &request_handle); - EXPECT_EQ(ERR_INVALID_ARGUMENT, error); - EXPECT_FALSE(request_handle.is_active()); - - // No supported types in requested_types. - types.push_back(CLIENT_CERT_RSA_SIGN); - types.push_back(2); - types.push_back(3); - error = service_->GetDomainBoundCert( - host, types, &type2, &private_key_info2, &der_cert2, - callback.callback(), &request_handle); - EXPECT_EQ(ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED, error); - EXPECT_FALSE(request_handle.is_active()); - - // If we request EC, the cert we created before should still be there. - types.push_back(CLIENT_CERT_ECDSA_SIGN); - error = service_->GetDomainBoundCert( - host, types, &type2, &private_key_info2, &der_cert2, - callback.callback(), &request_handle); - EXPECT_FALSE(request_handle.is_active()); - EXPECT_EQ(OK, error); - EXPECT_EQ(1, service_->cert_count()); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2); - EXPECT_EQ(private_key_info1, private_key_info2); - EXPECT_EQ(der_cert1, der_cert2); -} - TEST_F(ServerBoundCertServiceTest, StoreCerts) { int error; - std::vector<uint8> types; - types.push_back(CLIENT_CERT_ECDSA_SIGN); TestCompletionCallback callback; ServerBoundCertService::RequestHandle request_handle; std::string host1("encrypted.google.com"); - SSLClientCertType type1; std::string private_key_info1, der_cert1; EXPECT_EQ(0, service_->cert_count()); error = service_->GetDomainBoundCert( - host1, types, &type1, &private_key_info1, &der_cert1, + host1, &private_key_info1, &der_cert1, callback.callback(), &request_handle); EXPECT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle.is_active()); @@ -212,10 +186,9 @@ TEST_F(ServerBoundCertServiceTest, StoreCerts) { EXPECT_EQ(1, service_->cert_count()); std::string host2("www.verisign.com"); - SSLClientCertType type2; std::string private_key_info2, der_cert2; error = service_->GetDomainBoundCert( - host2, types, &type2, &private_key_info2, &der_cert2, + host2, &private_key_info2, &der_cert2, callback.callback(), &request_handle); EXPECT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle.is_active()); @@ -224,10 +197,9 @@ TEST_F(ServerBoundCertServiceTest, StoreCerts) { EXPECT_EQ(2, service_->cert_count()); std::string host3("www.twitter.com"); - SSLClientCertType type3; std::string private_key_info3, der_cert3; error = service_->GetDomainBoundCert( - host3, types, &type3, &private_key_info3, &der_cert3, + host3, &private_key_info3, &der_cert3, callback.callback(), &request_handle); EXPECT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle.is_active()); @@ -241,38 +213,29 @@ TEST_F(ServerBoundCertServiceTest, StoreCerts) { EXPECT_NE(der_cert1, der_cert3); EXPECT_NE(private_key_info2, private_key_info3); EXPECT_NE(der_cert2, der_cert3); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type3); } // Tests an inflight join. TEST_F(ServerBoundCertServiceTest, InflightJoin) { std::string host("encrypted.google.com"); int error; - std::vector<uint8> types; - types.push_back(CLIENT_CERT_ECDSA_SIGN); - SSLClientCertType type1; std::string private_key_info1, der_cert1; TestCompletionCallback callback1; ServerBoundCertService::RequestHandle request_handle1; - SSLClientCertType type2; std::string private_key_info2, der_cert2; TestCompletionCallback callback2; ServerBoundCertService::RequestHandle request_handle2; error = service_->GetDomainBoundCert( - host, types, &type1, &private_key_info1, &der_cert1, + host, &private_key_info1, &der_cert1, callback1.callback(), &request_handle1); EXPECT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle1.is_active()); - // If we request RSA and EC in the 2nd request, should still join with the - // original request. - types.insert(types.begin(), CLIENT_CERT_RSA_SIGN); + // Should join with the original request. error = service_->GetDomainBoundCert( - host, types, &type2, &private_key_info2, &der_cert2, + host, &private_key_info2, &der_cert2, callback2.callback(), &request_handle2); EXPECT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle2.is_active()); @@ -282,8 +245,6 @@ TEST_F(ServerBoundCertServiceTest, InflightJoin) { error = callback2.WaitForResult(); EXPECT_EQ(OK, error); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2); EXPECT_EQ(2u, service_->requests()); EXPECT_EQ(0u, service_->cert_store_hits()); EXPECT_EQ(1u, service_->inflight_joins()); @@ -291,16 +252,13 @@ TEST_F(ServerBoundCertServiceTest, InflightJoin) { TEST_F(ServerBoundCertServiceTest, ExtractValuesFromBytesEC) { std::string host("encrypted.google.com"); - SSLClientCertType type; std::string private_key_info, der_cert; int error; - std::vector<uint8> types; - types.push_back(CLIENT_CERT_ECDSA_SIGN); TestCompletionCallback callback; ServerBoundCertService::RequestHandle request_handle; error = service_->GetDomainBoundCert( - host, types, &type, &private_key_info, &der_cert, callback.callback(), + host, &private_key_info, &der_cert, callback.callback(), &request_handle); EXPECT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle.is_active()); @@ -329,16 +287,11 @@ TEST_F(ServerBoundCertServiceTest, ExtractValuesFromBytesEC) { // Tests that the callback of a canceled request is never made. TEST_F(ServerBoundCertServiceTest, CancelRequest) { std::string host("encrypted.google.com"); - SSLClientCertType type; std::string private_key_info, der_cert; int error; - std::vector<uint8> types; - types.push_back(CLIENT_CERT_ECDSA_SIGN); ServerBoundCertService::RequestHandle request_handle; error = service_->GetDomainBoundCert(host, - types, - &type, &private_key_info, &der_cert, base::Bind(&FailTest), @@ -362,17 +315,12 @@ TEST_F(ServerBoundCertServiceTest, CancelRequest) { // Tests that destructing the RequestHandle cancels the request. TEST_F(ServerBoundCertServiceTest, CancelRequestByHandleDestruction) { std::string host("encrypted.google.com"); - SSLClientCertType type; std::string private_key_info, der_cert; int error; - std::vector<uint8> types; - types.push_back(CLIENT_CERT_ECDSA_SIGN); { ServerBoundCertService::RequestHandle request_handle; error = service_->GetDomainBoundCert(host, - types, - &type, &private_key_info, &der_cert, base::Bind(&FailTest), @@ -394,16 +342,11 @@ TEST_F(ServerBoundCertServiceTest, CancelRequestByHandleDestruction) { TEST_F(ServerBoundCertServiceTest, DestructionWithPendingRequest) { std::string host("encrypted.google.com"); - SSLClientCertType type; std::string private_key_info, der_cert; int error; - std::vector<uint8> types; - types.push_back(CLIENT_CERT_ECDSA_SIGN); ServerBoundCertService::RequestHandle request_handle; error = service_->GetDomainBoundCert(host, - types, - &type, &private_key_info, &der_cert, base::Bind(&FailTest), @@ -438,16 +381,11 @@ TEST_F(ServerBoundCertServiceTest, RequestAfterPoolShutdown) { // Make a request that will force synchronous completion. std::string host("encrypted.google.com"); - SSLClientCertType type; std::string private_key_info, der_cert; int error; - std::vector<uint8> types; - types.push_back(CLIENT_CERT_ECDSA_SIGN); ServerBoundCertService::RequestHandle request_handle; error = service_->GetDomainBoundCert(host, - types, - &type, &private_key_info, &der_cert, base::Bind(&FailTest), @@ -460,30 +398,23 @@ TEST_F(ServerBoundCertServiceTest, RequestAfterPoolShutdown) { // Tests that simultaneous creation of different certs works. TEST_F(ServerBoundCertServiceTest, SimultaneousCreation) { int error; - std::vector<uint8> types; - types.push_back(CLIENT_CERT_ECDSA_SIGN); std::string host1("encrypted.google.com"); - SSLClientCertType type1; std::string private_key_info1, der_cert1; TestCompletionCallback callback1; ServerBoundCertService::RequestHandle request_handle1; std::string host2("foo.com"); - SSLClientCertType type2; std::string private_key_info2, der_cert2; TestCompletionCallback callback2; ServerBoundCertService::RequestHandle request_handle2; std::string host3("bar.com"); - SSLClientCertType type3; std::string private_key_info3, der_cert3; TestCompletionCallback callback3; ServerBoundCertService::RequestHandle request_handle3; error = service_->GetDomainBoundCert(host1, - types, - &type1, &private_key_info1, &der_cert1, callback1.callback(), @@ -492,8 +423,6 @@ TEST_F(ServerBoundCertServiceTest, SimultaneousCreation) { EXPECT_TRUE(request_handle1.is_active()); error = service_->GetDomainBoundCert(host2, - types, - &type2, &private_key_info2, &der_cert2, callback2.callback(), @@ -502,8 +431,6 @@ TEST_F(ServerBoundCertServiceTest, SimultaneousCreation) { EXPECT_TRUE(request_handle2.is_active()); error = service_->GetDomainBoundCert(host3, - types, - &type3, &private_key_info3, &der_cert3, callback3.callback(), @@ -513,19 +440,16 @@ TEST_F(ServerBoundCertServiceTest, SimultaneousCreation) { error = callback1.WaitForResult(); EXPECT_EQ(OK, error); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1); EXPECT_FALSE(private_key_info1.empty()); EXPECT_FALSE(der_cert1.empty()); error = callback2.WaitForResult(); EXPECT_EQ(OK, error); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2); EXPECT_FALSE(private_key_info2.empty()); EXPECT_FALSE(der_cert2.empty()); error = callback3.WaitForResult(); EXPECT_EQ(OK, error); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type3); EXPECT_FALSE(private_key_info3.empty()); EXPECT_FALSE(der_cert3.empty()); @@ -545,13 +469,11 @@ TEST_F(ServerBoundCertServiceTest, Expiration) { ServerBoundCertStore* store = service_->GetCertStore(); base::Time now = base::Time::Now(); store->SetServerBoundCert("good", - CLIENT_CERT_ECDSA_SIGN, now, now + base::TimeDelta::FromDays(1), "a", "b"); store->SetServerBoundCert("expired", - CLIENT_CERT_ECDSA_SIGN, now - base::TimeDelta::FromDays(2), now - base::TimeDelta::FromDays(1), "c", @@ -559,38 +481,99 @@ TEST_F(ServerBoundCertServiceTest, Expiration) { EXPECT_EQ(2, service_->cert_count()); int error; - std::vector<uint8> types; - types.push_back(CLIENT_CERT_ECDSA_SIGN); TestCompletionCallback callback; ServerBoundCertService::RequestHandle request_handle; // Cert is valid - synchronous completion. - SSLClientCertType type1; std::string private_key_info1, der_cert1; error = service_->GetDomainBoundCert( - "good", types, &type1, &private_key_info1, &der_cert1, + "good", &private_key_info1, &der_cert1, callback.callback(), &request_handle); EXPECT_EQ(OK, error); EXPECT_FALSE(request_handle.is_active()); EXPECT_EQ(2, service_->cert_count()); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type1); EXPECT_STREQ("a", private_key_info1.c_str()); EXPECT_STREQ("b", der_cert1.c_str()); // Expired cert is valid as well - synchronous completion. - SSLClientCertType type2; std::string private_key_info2, der_cert2; error = service_->GetDomainBoundCert( - "expired", types, &type2, &private_key_info2, &der_cert2, + "expired", &private_key_info2, &der_cert2, callback.callback(), &request_handle); EXPECT_EQ(OK, error); EXPECT_FALSE(request_handle.is_active()); EXPECT_EQ(2, service_->cert_count()); - EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, type2); EXPECT_STREQ("c", private_key_info2.c_str()); EXPECT_STREQ("d", der_cert2.c_str()); } +TEST_F(ServerBoundCertServiceTest, AsyncStoreGetNoCertsInStore) { + MockServerBoundCertStoreWithAsyncGet* mock_store = + new MockServerBoundCertStoreWithAsyncGet(); + service_ = scoped_ptr<ServerBoundCertService>( + new ServerBoundCertService(mock_store, sequenced_worker_pool_)); + + std::string host("encrypted.google.com"); + + int error; + TestCompletionCallback callback; + ServerBoundCertService::RequestHandle request_handle; + + // Asynchronous completion with no certs in the store. + std::string private_key_info, der_cert; + EXPECT_EQ(0, service_->cert_count()); + error = service_->GetDomainBoundCert( + host, &private_key_info, &der_cert, callback.callback(), &request_handle); + EXPECT_EQ(ERR_IO_PENDING, error); + EXPECT_TRUE(request_handle.is_active()); + + mock_store->CallGetServerBoundCertCallbackWithResult( + ERR_FILE_NOT_FOUND, base::Time(), std::string(), std::string()); + + error = callback.WaitForResult(); + EXPECT_EQ(OK, error); + EXPECT_EQ(1, service_->cert_count()); + EXPECT_FALSE(private_key_info.empty()); + EXPECT_FALSE(der_cert.empty()); + EXPECT_FALSE(request_handle.is_active()); +} + +TEST_F(ServerBoundCertServiceTest, AsyncStoreGetOneCertInStore) { + MockServerBoundCertStoreWithAsyncGet* mock_store = + new MockServerBoundCertStoreWithAsyncGet(); + service_ = scoped_ptr<ServerBoundCertService>( + new ServerBoundCertService(mock_store, sequenced_worker_pool_)); + + std::string host("encrypted.google.com"); + + int error; + TestCompletionCallback callback; + ServerBoundCertService::RequestHandle request_handle; + + // Asynchronous completion with a cert in the store. + std::string private_key_info, der_cert; + EXPECT_EQ(0, service_->cert_count()); + error = service_->GetDomainBoundCert( + host, &private_key_info, &der_cert, callback.callback(), &request_handle); + EXPECT_EQ(ERR_IO_PENDING, error); + EXPECT_TRUE(request_handle.is_active()); + + mock_store->CallGetServerBoundCertCallbackWithResult( + OK, base::Time(), "ab", "cd"); + + error = callback.WaitForResult(); + EXPECT_EQ(OK, error); + EXPECT_EQ(1, service_->cert_count()); + EXPECT_EQ(1u, service_->requests()); + EXPECT_EQ(1u, service_->cert_store_hits()); + // Because the cert was found in the store, no new workers should have been + // created. + EXPECT_EQ(0u, service_->workers_created()); + EXPECT_STREQ("ab", private_key_info.c_str()); + EXPECT_STREQ("cd", der_cert.c_str()); + EXPECT_FALSE(request_handle.is_active()); +} + #endif // !defined(USE_OPENSSL) } // namespace diff --git a/net/ssl/server_bound_cert_store.cc b/net/ssl/server_bound_cert_store.cc index d0d520dcb9..e778362c0b 100644 --- a/net/ssl/server_bound_cert_store.cc +++ b/net/ssl/server_bound_cert_store.cc @@ -6,19 +6,16 @@ namespace net { -ServerBoundCertStore::ServerBoundCert::ServerBoundCert() - : type_(CLIENT_CERT_INVALID_TYPE) { +ServerBoundCertStore::ServerBoundCert::ServerBoundCert() { } ServerBoundCertStore::ServerBoundCert::ServerBoundCert( const std::string& server_identifier, - SSLClientCertType type, base::Time creation_time, base::Time expiration_time, const std::string& private_key, const std::string& cert) : server_identifier_(server_identifier), - type_(type), creation_time_(creation_time), expiration_time_(expiration_time), private_key_(private_key), @@ -29,7 +26,7 @@ ServerBoundCertStore::ServerBoundCert::~ServerBoundCert() {} void ServerBoundCertStore::InitializeFrom(const ServerBoundCertList& list) { for (ServerBoundCertList::const_iterator i = list.begin(); i != list.end(); ++i) { - SetServerBoundCert(i->server_identifier(), i->type(), i->creation_time(), + SetServerBoundCert(i->server_identifier(), i->creation_time(), i->expiration_time(), i->private_key(), i->cert()); } } diff --git a/net/ssl/server_bound_cert_store.h b/net/ssl/server_bound_cert_store.h index ad0ecb0d8b..0de0f3eebd 100644 --- a/net/ssl/server_bound_cert_store.h +++ b/net/ssl/server_bound_cert_store.h @@ -12,7 +12,6 @@ #include "base/threading/non_thread_safe.h" #include "base/time/time.h" #include "net/base/net_export.h" -#include "net/ssl/ssl_client_cert_type.h" namespace net { @@ -27,12 +26,11 @@ class NET_EXPORT ServerBoundCertStore : NON_EXPORTED_BASE(public base::NonThreadSafe) { public: // The ServerBoundCert class contains a private key in addition to the server - // cert, and cert type. + // cert. class NET_EXPORT ServerBoundCert { public: ServerBoundCert(); ServerBoundCert(const std::string& server_identifier, - SSLClientCertType type, base::Time creation_time, base::Time expiration_time, const std::string& private_key, @@ -41,8 +39,6 @@ class NET_EXPORT ServerBoundCertStore // Server identifier. For domain bound certs, for instance "verisign.com". const std::string& server_identifier() const { return server_identifier_; } - // TLS ClientCertificateType. - SSLClientCertType type() const { return type_; } // The time the certificate was created, also the start of the certificate // validity period. base::Time creation_time() const { return creation_time_; } @@ -57,7 +53,6 @@ class NET_EXPORT ServerBoundCertStore private: std::string server_identifier_; - SSLClientCertType type_; base::Time creation_time_; base::Time expiration_time_; std::string private_key_; @@ -67,8 +62,8 @@ class NET_EXPORT ServerBoundCertStore typedef std::list<ServerBoundCert> ServerBoundCertList; typedef base::Callback<void( + int, const std::string&, - SSLClientCertType, base::Time, const std::string&, const std::string&)> GetCertCallback; @@ -77,14 +72,13 @@ class NET_EXPORT ServerBoundCertStore virtual ~ServerBoundCertStore() {} // GetServerBoundCert may return the result synchronously through the - // output parameters, in which case it will return true. Otherwise it will - // return false and the callback will be called with the result + // output parameters, in which case it will return either OK if a cert is + // found in the store, or ERR_FILE_NOT_FOUND if none is found. If the + // result cannot be returned synchronously, GetServerBoundCert will + // return ERR_IO_PENDING and the callback will be called with the result // asynchronously. - // In either case, the type will be CLIENT_CERT_INVALID_TYPE if no cert - // existed for the given |server_identifier|. - virtual bool GetServerBoundCert( + virtual int GetServerBoundCert( const std::string& server_identifier, - SSLClientCertType* type, base::Time* expiration_time, std::string* private_key_result, std::string* cert_result, @@ -93,7 +87,6 @@ class NET_EXPORT ServerBoundCertStore // Adds a server bound cert and the corresponding private key to the store. virtual void SetServerBoundCert( const std::string& server_identifier, - SSLClientCertType type, base::Time creation_time, base::Time expiration_time, const std::string& private_key, diff --git a/net/third_party/nss/README.chromium b/net/third_party/nss/README.chromium index d183ca8451..ae77651f6f 100644 --- a/net/third_party/nss/README.chromium +++ b/net/third_party/nss/README.chromium @@ -75,10 +75,6 @@ Patches: patches/cbc.patch https://code.google.com/p/chromium/issues/detail?id=172658#c12 - * Define AES_256_KEY_LENGTH if the system blapit.h header doesn't define it. - Remove this patch when all system NSS packages are NSS 3.12.10 or later. - patches/aes256keylength.patch - * Change ssl3_SuiteBOnly to always return PR_TRUE. The softoken in NSS versions older than 3.15 report an EC key size range of 112 bits to 571 bits, even when it is compiled to support only the NIST P-256, P-384, and diff --git a/net/third_party/nss/patches/aes256keylength.patch b/net/third_party/nss/patches/aes256keylength.patch deleted file mode 100644 index 2fc2506297..0000000000 --- a/net/third_party/nss/patches/aes256keylength.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff -pu a/nss/lib/ssl/sslsnce.c b/nss/lib/ssl/sslsnce.c ---- a/nss/lib/ssl/sslsnce.c 2013-07-31 12:07:10.974699609 -0700 -+++ b/nss/lib/ssl/sslsnce.c 2013-07-31 14:12:33.185058439 -0700 -@@ -86,6 +86,11 @@ - #include "nspr.h" - #include "sslmutex.h" - -+/* AES_256_KEY_LENGTH was added to blapit.h in NSS 3.12.10. */ -+#ifndef AES_256_KEY_LENGTH -+#define AES_256_KEY_LENGTH 32 /* bytes */ -+#endif -+ - /* - ** Format of a cache entry in the shared memory. - */ diff --git a/net/third_party/nss/patches/applypatches.sh b/net/third_party/nss/patches/applypatches.sh index 86444a22c2..81192a4d3b 100755 --- a/net/third_party/nss/patches/applypatches.sh +++ b/net/third_party/nss/patches/applypatches.sh @@ -38,8 +38,6 @@ patch -p4 < $patches_dir/secretexporterlocks.patch patch -p4 < $patches_dir/cbc.patch -patch -p4 < $patches_dir/aes256keylength.patch - patch -p4 < $patches_dir/suitebonly.patch patch -p4 < $patches_dir/secitemarray.patch diff --git a/net/third_party/nss/ssl.gyp b/net/third_party/nss/ssl.gyp index 49cfbd8732..fc526733c0 100644 --- a/net/third_party/nss/ssl.gyp +++ b/net/third_party/nss/ssl.gyp @@ -68,7 +68,6 @@ 'ssl/win32err.c', 'ssl/win32err.h', 'ssl/bodge/secitem_array.c', - 'ssl/bodge/secure_memcmp.c', ], 'sources!': [ 'ssl/os2_err.c', diff --git a/net/third_party/nss/ssl/bodge/secure_memcmp.c b/net/third_party/nss/ssl/bodge/secure_memcmp.c deleted file mode 100644 index b18579c6ea..0000000000 --- a/net/third_party/nss/ssl/bodge/secure_memcmp.c +++ /dev/null @@ -1,59 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -// This file exists to provide the secure memcmp function. This was added in -// NSS 3.12.5. - -#include <stdlib.h> - -/* - * Perform a constant-time compare of two memory regions. The return value is - * 0 if the memory regions are equal and non-zero otherwise. - */ -int -NSS_SecureMemcmp(const void *ia, const void *ib, size_t n) -{ - const unsigned char *a = (const unsigned char*) ia; - const unsigned char *b = (const unsigned char*) ib; - size_t i; - unsigned char r = 0; - - for (i = 0; i < n; ++i) { - r |= *a++ ^ *b++; - } - - return r; -} diff --git a/net/third_party/nss/ssl/sslsnce.c b/net/third_party/nss/ssl/sslsnce.c index 4b8825a717..b0446adc17 100644 --- a/net/third_party/nss/ssl/sslsnce.c +++ b/net/third_party/nss/ssl/sslsnce.c @@ -86,11 +86,6 @@ #include "nspr.h" #include "sslmutex.h" -/* AES_256_KEY_LENGTH was added to blapit.h in NSS 3.12.10. */ -#ifndef AES_256_KEY_LENGTH -#define AES_256_KEY_LENGTH 32 /* bytes */ -#endif - /* ** Format of a cache entry in the shared memory. */ diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc index 36a9d4b9d0..d18525f634 100644 --- a/net/tools/quic/quic_server.cc +++ b/net/tools/quic/quic_server.cc @@ -179,6 +179,19 @@ void QuicServer::OnEvent(int fd, EpollEvent* event) { } } +/* static */ +void QuicServer::MaybeDispatchPacket(QuicDispatcher* dispatcher, + const QuicEncryptedPacket& packet, + const IPEndPoint& server_address, + const IPEndPoint& client_address) { + QuicGuid guid; + if (!QuicFramer::ReadGuidFromPacket(packet, &guid)) { + return; + } + + dispatcher->ProcessPacket(server_address, client_address, guid, packet); +} + bool QuicServer::ReadAndDispatchSinglePacket(int fd, int port, QuicDispatcher* dispatcher, @@ -199,19 +212,9 @@ bool QuicServer::ReadAndDispatchSinglePacket(int fd, } QuicEncryptedPacket packet(buf, bytes_read, false); - QuicGuid guid; - QuicDataReader reader(packet.data(), packet.length()); - uint8 public_flags; - if (!reader.ReadBytes(&public_flags, 1)) { - LOG(DFATAL) << "Unable to read public flags."; - return false; - } - if (!reader.ReadUInt64(&guid)) { - return true; // We read, we just didn't like the results. - } IPEndPoint server_address(server_ip, port); - dispatcher->ProcessPacket(server_address, client_address, guid, packet); + MaybeDispatchPacket(dispatcher, packet, server_address, client_address); return true; } diff --git a/net/tools/quic/quic_server.h b/net/tools/quic/quic_server.h index 63995665cc..142d1d1572 100644 --- a/net/tools/quic/quic_server.h +++ b/net/tools/quic/quic_server.h @@ -59,6 +59,14 @@ class QuicServer : public EpollCallbackInterface { virtual void OnShutdown(EpollServer* eps, int fd) OVERRIDE {} + // Dispatches the given packet only if it looks like a valid QUIC packet. + // TODO(rjshade): Return a status describing why a packet was dropped, and log + // somehow. Maybe expose as a varz. + static void MaybeDispatchPacket(QuicDispatcher* dispatcher, + const QuicEncryptedPacket& packet, + const IPEndPoint& server_address, + const IPEndPoint& client_address); + bool overflow_supported() { return overflow_supported_; } int packets_dropped() { return packets_dropped_; } diff --git a/net/tools/quic/quic_server_test.cc b/net/tools/quic/quic_server_test.cc new file mode 100644 index 0000000000..7d1d66939c --- /dev/null +++ b/net/tools/quic/quic_server_test.cc @@ -0,0 +1,74 @@ +// Copyright 2013 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. + +#include "net/tools/quic/quic_server.h" + +#include "net/quic/crypto/quic_random.h" +#include "net/quic/quic_utils.h" +#include "net/tools/quic/test_tools/mock_quic_dispatcher.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; + +namespace net { +namespace tools { +namespace test { + +namespace { + +class QuicServerDispatchPacketTest : public ::testing::Test { + public: + QuicServerDispatchPacketTest() + : crypto_config_("blah", QuicRandom::GetInstance()), + dispatcher_(config_, crypto_config_, 1234, &eps_) {} + + + void MaybeDispatchPacket(const QuicEncryptedPacket& packet) { + IPEndPoint client_addr, server_addr; + QuicServer::MaybeDispatchPacket(&dispatcher_, packet, + client_addr, server_addr); + } + + protected: + QuicConfig config_; + QuicCryptoServerConfig crypto_config_; + EpollServer eps_; + MockQuicDispatcher dispatcher_; +}; + +TEST_F(QuicServerDispatchPacketTest, DoNotDispatchPacketWithoutGUID) { + // Packet too short to be considered valid. + unsigned char invalid_packet[] = { 0x00 }; + QuicEncryptedPacket encrypted_invalid_packet( + QuicUtils::AsChars(invalid_packet), arraysize(invalid_packet), false); + + // We expect the invalid packet to be dropped, and ProcessPacket should never + // be called. + EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _, _)).Times(0); + MaybeDispatchPacket(encrypted_invalid_packet); +} + +TEST_F(QuicServerDispatchPacketTest, DispatchValidPacket) { + unsigned char valid_packet[] = { + // public flags (8 byte guid) + 0x3C, + // guid + 0x10, 0x32, 0x54, 0x76, + 0x98, 0xBA, 0xDC, 0xFE, + // packet sequence number + 0xBC, 0x9A, 0x78, 0x56, + 0x34, 0x12, + // private flags + 0x00 }; + QuicEncryptedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet), + arraysize(valid_packet), false); + + EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _, _)).Times(1); + MaybeDispatchPacket(encrypted_valid_packet); +} + +} // namespace +} // namespace test +} // namespace tools +} // namespace net diff --git a/net/tools/quic/test_tools/mock_quic_dispatcher.cc b/net/tools/quic/test_tools/mock_quic_dispatcher.cc new file mode 100644 index 0000000000..3a2b1d9825 --- /dev/null +++ b/net/tools/quic/test_tools/mock_quic_dispatcher.cc @@ -0,0 +1,21 @@ +// Copyright 2013 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. + +#include "net/tools/quic/test_tools/mock_quic_dispatcher.h" + +namespace net { +namespace tools { +namespace test { + +MockQuicDispatcher::MockQuicDispatcher( + const QuicConfig& config, + const QuicCryptoServerConfig& crypto_config, + QuicGuid guid, + EpollServer* eps) + : QuicDispatcher(config, crypto_config, guid, eps) { } +MockQuicDispatcher::~MockQuicDispatcher() {} + +} // namespace test +} // namespace tools +} // namespace net diff --git a/net/tools/quic/test_tools/mock_quic_dispatcher.h b/net/tools/quic/test_tools/mock_quic_dispatcher.h new file mode 100644 index 0000000000..563ab0de5f --- /dev/null +++ b/net/tools/quic/test_tools/mock_quic_dispatcher.h @@ -0,0 +1,38 @@ +// Copyright 2013 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. + +#ifndef NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_DISPATCHER_H_ +#define NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_DISPATCHER_H_ + +#include "net/base/ip_endpoint.h" +#include "net/quic/crypto/crypto_server_config.h" +#include "net/quic/quic_config.h" +#include "net/quic/quic_protocol.h" +#include "net/tools/flip_server/epoll_server.h" +#include "net/tools/quic/quic_dispatcher.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace net { +namespace tools { +namespace test { + +class MockQuicDispatcher : public QuicDispatcher { + public: + MockQuicDispatcher(const QuicConfig& config, + const QuicCryptoServerConfig& crypto_config, + QuicGuid guid, + EpollServer* eps); + virtual ~MockQuicDispatcher(); + + MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address, + const IPEndPoint& client_address, + QuicGuid guid, + const QuicEncryptedPacket& packet)); +}; + +} // namespace test +} // namespace tools +} // namespace net + +#endif // NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_DISPATCHER_H_ |