summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-20 16:30:19 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-20 16:30:19 +0000
commitd0672be51d1a4c25f3dd7d91f9d9c1293b33adc6 (patch)
tree93a2a7f1b8d3426a4e65692b56e12e4011b60241
parenta5e842bf6fda331cdacf3a8d56da19a3ea8d3d0b (diff)
downloadchromium_src-d0672be51d1a4c25f3dd7d91f9d9c1293b33adc6.zip
chromium_src-d0672be51d1a4c25f3dd7d91f9d9c1293b33adc6.tar.gz
chromium_src-d0672be51d1a4c25f3dd7d91f9d9c1293b33adc6.tar.bz2
net: move SSL host info serialisation into SSLHostInfo
This is a prelude to SSLHostInfo being able to kick off certificate validation based on predicted certificates. In order for that to happen, SSLHostInfo has to be able to parse the contents of the saved data, therefore the serialisation/deserialisation is moved into SSLHostInfo and we use a protocol buffer to clean things up. TEST=net_unittests BUG=none Review URL: http://codereview.chromium.org/3915001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63221 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/base/ssl_config_service.h1
-rw-r--r--net/base/ssl_host_info.cc13
-rw-r--r--net/http/disk_cache_based_ssl_host_info.cc12
-rw-r--r--net/http/disk_cache_based_ssl_host_info.h5
-rw-r--r--net/http/http_cache.cc2
-rw-r--r--net/http/http_network_transaction.cc1
-rw-r--r--net/net.gyp42
-rw-r--r--net/socket/client_socket_factory.cc2
-rw-r--r--net/socket/client_socket_pool_base_unittest.cc1
-rw-r--r--net/socket/socket_test_util.cc1
-rw-r--r--net/socket/ssl_client_socket_mac_factory.cc1
-rw-r--r--net/socket/ssl_client_socket_nss.cc193
-rw-r--r--net/socket/ssl_client_socket_nss.h2
-rw-r--r--net/socket/ssl_client_socket_nss_factory.cc1
-rw-r--r--net/socket/ssl_client_socket_pool.cc2
-rw-r--r--net/socket/ssl_host_info.cc100
-rw-r--r--net/socket/ssl_host_info.h (renamed from net/base/ssl_host_info.h)51
-rw-r--r--net/socket/ssl_host_info.proto34
-rw-r--r--net/socket/tcp_client_socket_pool_unittest.cc1
19 files changed, 268 insertions, 197 deletions
diff --git a/net/base/ssl_config_service.h b/net/base/ssl_config_service.h
index dc48a36..0ab88b2 100644
--- a/net/base/ssl_config_service.h
+++ b/net/base/ssl_config_service.h
@@ -10,7 +10,6 @@
#include "base/observer_list.h"
#include "base/ref_counted.h"
-#include "net/base/ssl_host_info.h"
#include "net/base/x509_certificate.h"
namespace net {
diff --git a/net/base/ssl_host_info.cc b/net/base/ssl_host_info.cc
deleted file mode 100644
index 4b6c0e2..0000000
--- a/net/base/ssl_host_info.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2010 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/base/ssl_host_info.h"
-
-namespace net {
-
-SSLHostInfo::~SSLHostInfo() {}
-
-SSLHostInfoFactory::~SSLHostInfoFactory() {}
-
-} // namespace net
diff --git a/net/http/disk_cache_based_ssl_host_info.cc b/net/http/disk_cache_based_ssl_host_info.cc
index f2de223..10b2e15 100644
--- a/net/http/disk_cache_based_ssl_host_info.cc
+++ b/net/http/disk_cache_based_ssl_host_info.cc
@@ -147,11 +147,12 @@ int DiskCacheBasedSSLHostInfo::WaitForDataReadyDone() {
ready_ = true;
callback = user_callback_;
user_callback_ = NULL;
- // We close the entry because, if we shutdown before ::Set is called, then we
- // might leak a cache reference, which causes a DCHECK on shutdown.
+ // We close the entry because, if we shutdown before ::Persist is called,
+ // then we might leak a cache reference, which causes a DCHECK on shutdown.
if (entry_)
entry_->Close();
entry_ = NULL;
+ Parse(data_);
if (callback)
callback->Run(OK);
@@ -172,17 +173,14 @@ int DiskCacheBasedSSLHostInfo::WaitForDataReady(CompletionCallback* callback) {
return ERR_IO_PENDING;
}
-void DiskCacheBasedSSLHostInfo::Set(const std::string& new_data) {
+void DiskCacheBasedSSLHostInfo::Persist() {
DCHECK(CalledOnValidThread());
DCHECK(state_ != GET_BACKEND);
- if (new_data.empty())
- return;
-
DCHECK(new_data_.empty());
CHECK(ready_);
DCHECK(user_callback_ == NULL);
- new_data_ = new_data;
+ new_data_ = Serialize();
if (!backend_)
return;
diff --git a/net/http/disk_cache_based_ssl_host_info.h b/net/http/disk_cache_based_ssl_host_info.h
index 5cab8ff..51a4a91 100644
--- a/net/http/disk_cache_based_ssl_host_info.h
+++ b/net/http/disk_cache_based_ssl_host_info.h
@@ -11,8 +11,8 @@
#include "base/non_thread_safe.h"
#include "base/scoped_ptr.h"
#include "net/base/completion_callback.h"
-#include "net/base/ssl_host_info.h"
#include "net/disk_cache/disk_cache.h"
+#include "net/socket/ssl_host_info.h"
namespace net {
@@ -30,8 +30,7 @@ class DiskCacheBasedSSLHostInfo : public SSLHostInfo,
// Implementation of SSLHostInfo
virtual void Start();
virtual int WaitForDataReady(CompletionCallback* callback);
- virtual const std::string& data() const { return data_; }
- virtual void Set(const std::string& new_data);
+ virtual void Persist();
private:
~DiskCacheBasedSSLHostInfo();
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index 153b5d5..eca95ef 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -24,7 +24,6 @@
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
-#include "net/base/ssl_host_info.h"
#include "net/disk_cache/disk_cache.h"
#include "net/http/disk_cache_based_ssl_host_info.h"
#include "net/http/http_cache_transaction.h"
@@ -34,6 +33,7 @@
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
+#include "net/socket/ssl_host_info.h"
#include "net/spdy/spdy_session_pool.h"
namespace net {
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 0d9f340..e0b9c39 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -26,7 +26,6 @@
#include "net/base/net_util.h"
#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_connection_status_flags.h"
-#include "net/base/ssl_host_info.h"
#include "net/base/upload_data_stream.h"
#include "net/http/http_auth.h"
#include "net/http/http_auth_handler.h"
diff --git a/net/net.gyp b/net/net.gyp
index e8a32c9..f0306b1 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -173,8 +173,6 @@
'base/ssl_config_service_win.cc',
'base/ssl_config_service_win.h',
'base/ssl_false_start_blacklist.cc',
- 'base/ssl_host_info.cc',
- 'base/ssl_host_info.h',
'base/ssl_info.cc',
'base/ssl_info.h',
'base/static_cookie_policy.cc',
@@ -324,6 +322,7 @@
'../third_party/zlib/zlib.gyp:zlib',
'net_base',
'net_resources',
+ 'ssl_host_info',
],
'sources': [
'disk_cache/addr.cc',
@@ -995,6 +994,45 @@
],
},
{
+ # This is a separate target in order to limit the scope of the protobuf
+ # includes.
+ 'target_name': 'ssl_host_info',
+ 'type': '<(library)',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../third_party/protobuf/protobuf.gyp:protobuf_lite',
+ ],
+ 'sources': [
+ 'socket/ssl_host_info.proto',
+ 'socket/ssl_host_info.cc',
+ 'socket/ssl_host_info.h',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'genproto',
+ 'extension': 'proto',
+ 'inputs': [
+ '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/protoc_out/net/socket/<(RULE_INPUT_ROOT).pb.h',
+ '<(SHARED_INTERMEDIATE_DIR)/protoc_out/net/socket/<(RULE_INPUT_ROOT).pb.cc',
+ ],
+ 'action': [
+ '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
+ 'socket/<(RULE_INPUT_ROOT)<(RULE_INPUT_EXT)',
+ '--cpp_out=<(SHARED_INTERMEDIATE_DIR)/protoc_out/net',
+ ],
+ 'message': 'Generating C++ code from <(RULE_INPUT_PATH)',
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)/protoc_out/net',
+ '<(SHARED_INTERMEDIATE_DIR)/protoc_out',
+ ],
+ },
+ {
'target_name': 'net_perftests',
'type': 'executable',
'dependencies': [
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index a31af007..90bcdc5 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -6,7 +6,6 @@
#include "base/singleton.h"
#include "build/build_config.h"
-#include "net/base/ssl_host_info.h"
#include "net/socket/client_socket_handle.h"
#if defined(OS_WIN)
#include "net/socket/ssl_client_socket_win.h"
@@ -18,6 +17,7 @@
#include "net/socket/ssl_client_socket_mac.h"
#include "net/socket/ssl_client_socket_nss.h"
#endif
+#include "net/socket/ssl_host_info.h"
#include "net/socket/tcp_client_socket.h"
namespace net {
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 1f99b3d..820b030 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -23,6 +23,7 @@
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_histograms.h"
#include "net/socket/socket_test_util.h"
+#include "net/socket/ssl_host_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 9854cc5..53bcf89 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -21,6 +21,7 @@
#include "net/http/http_response_headers.h"
#include "net/socket/client_socket_pool_histograms.h"
#include "net/socket/socket.h"
+#include "net/socket/ssl_host_info.h"
#include "testing/gtest/include/gtest/gtest.h"
#define NET_TRACE(level, s) DLOG(level) << s << __FUNCTION__ << "() "
diff --git a/net/socket/ssl_client_socket_mac_factory.cc b/net/socket/ssl_client_socket_mac_factory.cc
index bc26261..7f0c5ce 100644
--- a/net/socket/ssl_client_socket_mac_factory.cc
+++ b/net/socket/ssl_client_socket_mac_factory.cc
@@ -5,6 +5,7 @@
#include "net/socket/client_socket_factory.h"
#include "net/socket/ssl_client_socket_mac.h"
+#include "net/socket/ssl_host_info.h"
namespace net {
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 95458fa..136f138 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -83,11 +83,11 @@
#include "net/base/net_log.h"
#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_connection_status_flags.h"
-#include "net/base/ssl_host_info.h"
#include "net/base/ssl_info.h"
#include "net/base/sys_addrinfo.h"
#include "net/ocsp/nss_ocsp.h"
#include "net/socket/client_socket_handle.h"
+#include "net/socket/ssl_host_info.h"
static const int kRecvBufferSize = 4096;
@@ -461,15 +461,9 @@ int SSLClientSocketNSS::Init() {
return OK;
}
-// This is a version number of the Snap Start information saved by
-// |SaveSnapStartInfo| and loaded by |LoadSnapStartInfo|. Since the information
-// can be saved on disk we might have version skew in the future. Any data with
-// a different version is ignored by |LoadSnapStartInfo|.
-static const uint8 kSnapStartInfoVersion = 0;
-
-// SaveSnapStartInfo serialises the information needed to perform a Snap Start
-// with this server in the future (if any) and tells
-// |ssl_host_info_| to preserve it.
+// SaveSnapStartInfo extracts the information needed to perform a Snap Start
+// with this server in the future (if any) and tells |ssl_host_info_| to
+// preserve it.
void SSLClientSocketNSS::SaveSnapStartInfo() {
if (!ssl_host_info_.get())
return;
@@ -501,32 +495,12 @@ void SSLClientSocketNSS::SaveSnapStartInfo() {
return;
if (hello_data_len > std::numeric_limits<uint16>::max())
return;
+ SSLHostInfo::State* state = ssl_host_info_->mutable_state();
+ state->server_hello =
+ std::string(reinterpret_cast<const char *>(hello_data), hello_data_len);
- // The format of the saved info looks like:
- // struct Cert {
- // uint16 length
- // opaque certificate[length];
- // }
- //
- // uint8 version (kSnapStartInfoVersion)
- // uint8 npn_status
- // uint8 npn_proto_len
- // uint8 npn_proto[npn_proto_len]
- // uint16 hello_data_len
- // opaque hello_data[hello_data_len]
- // uint8 num_certs;
- // Cert[num_certs];
-
- std::string npn_proto;
- NextProtoStatus npn_status = GetNextProto(&npn_proto);
-
- unsigned num_certs = 0;
- unsigned len = 3;
- DCHECK_LT(npn_proto.size(), 256u);
- len += npn_proto.size();
- len += 2; // for hello_data_len
- len += hello_data_len;
- len++; // for |num_certs|
+ state->npn_valid = true;
+ state->npn_status = GetNextProto(&state->npn_protocol);
// TODO(wtc): CERT_GetCertChainFromCert might not return the same cert chain
// that the Certificate message actually contained. http://crbug.com/48854
@@ -535,67 +509,22 @@ void SSLClientSocketNSS::SaveSnapStartInfo() {
if (!cert_list)
return;
- unsigned last_cert_len = 0;
- bool last_cert_is_root = false;
for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
!CERT_LIST_END(node, cert_list);
node = CERT_LIST_NEXT(node)) {
- num_certs++;
if (node->cert->derCert.len > std::numeric_limits<uint16>::max()) {
CERT_DestroyCertList(cert_list);
return;
}
- last_cert_len = node->cert->derCert.len;
- len += 2 + last_cert_len;
- last_cert_is_root = node->cert->isRoot == PR_TRUE;
- }
-
- if (num_certs == 0 || num_certs > std::numeric_limits<uint8>::max()) {
- CERT_DestroyCertList(cert_list);
- return;
- }
-
- if (num_certs > 1 && last_cert_is_root) {
- // The cert list included the root certificate, which we don't want to
- // save. (Since we need to predict the server's certificates we don't want
- // to predict the root cert because the server won't send it to us. We
- // could implement this logic either here, or in the code which loads the
- // certificates. But, by doing it here, we save a little disk space).
- //
- // Note that, when the TODO above (http://crbug.com/48854) is handled, this
- // point will be moot.
- len -= 2 + last_cert_len;
- num_certs--;
- }
-
- std::vector<uint8> data(len);
- unsigned j = 0;
- data[j++] = kSnapStartInfoVersion;
- data[j++] = static_cast<uint8>(npn_status);
- data[j++] = static_cast<uint8>(npn_proto.size());
- memcpy(&data[j], npn_proto.data(), npn_proto.size());
- j += npn_proto.size();
- data[j++] = hello_data_len >> 8;
- data[j++] = hello_data_len;
- memcpy(&data[j], hello_data, hello_data_len);
- j += hello_data_len;
- data[j++] = num_certs;
-
- unsigned i = 0;
- for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
- i < num_certs;
- node = CERT_LIST_NEXT(node), i++) {
- data[j++] = node->cert->derCert.len >> 8;
- data[j++] = node->cert->derCert.len;
- memcpy(&data[j], node->cert->derCert.data, node->cert->derCert.len);
- j += node->cert->derCert.len;
+ if (node->cert->isRoot == PR_TRUE)
+ continue;
+ state->certs.push_back(std::string(
+ reinterpret_cast<char*>(node->cert->derCert.data),
+ node->cert->derCert.len));
}
- DCHECK_EQ(j, len);
-
- LOG(ERROR) << "Setting Snap Start info " << hostname_ << " " << len;
- ssl_host_info_->Set(std::string(
- reinterpret_cast<const char *>(&data[0]), len));
+ LOG(ERROR) << "Setting Snap Start info " << hostname_;
+ ssl_host_info_->Persist();
CERT_DestroyCertList(cert_list);
}
@@ -609,69 +538,29 @@ static void DestroyCertificates(CERTCertificate** certs, unsigned len) {
// by |SaveSnapStartInfo|, and sets the predicted certificates and ServerHello
// data on the NSS socket. Returns true on success. If this function returns
// false, the caller should try a normal TLS handshake.
-bool SSLClientSocketNSS::LoadSnapStartInfo(const std::string& info) {
- const unsigned char* data =
- reinterpret_cast<const unsigned char*>(info.data());
- SECStatus rv;
-
- // See the comment in |SaveSnapStartInfo| for the format of the data.
- if (info.size() < 3 ||
- data[0] != kSnapStartInfoVersion) {
- return false;
- }
+bool SSLClientSocketNSS::LoadSnapStartInfo() {
+ const SSLHostInfo::State& state(ssl_host_info_->state());
- unsigned j = 1;
- const uint8 npn_status = data[j++];
- const uint8 npn_proto_len = data[j++];
- if (static_cast<unsigned>(npn_proto_len) + j > info.size()) {
- NOTREACHED();
+ if (state.server_hello.empty() ||
+ state.certs.empty() ||
+ !state.npn_valid) {
return false;
}
- const std::string npn_proto(info.substr(j, npn_proto_len));
- j += npn_proto_len;
- if (j + 2 > info.size()) {
- NOTREACHED();
- return false;
- }
- uint16 hello_data_len = static_cast<uint16>(data[j]) << 8 |
- static_cast<uint16>(data[j+1]);
- j += 2;
- if (static_cast<unsigned>(hello_data_len) + j > info.size()) {
- NOTREACHED();
- return false;
- }
-
- rv = SSL_SetPredictedServerHelloData(nss_fd_, &data[j], hello_data_len);
+ SECStatus rv;
+ rv = SSL_SetPredictedServerHelloData(
+ nss_fd_,
+ reinterpret_cast<const uint8*>(state.server_hello.data()),
+ state.server_hello.size());
DCHECK_EQ(SECSuccess, rv);
- j += hello_data_len;
-
- if (j + 1 > info.size()) {
- NOTREACHED();
- return false;
- }
- unsigned num_certs = data[j++];
- scoped_array<CERTCertificate*> certs(new CERTCertificate*[num_certs]);
- for (unsigned i = 0; i < num_certs; i++) {
- if (j + 2 > info.size()) {
- DestroyCertificates(&certs[0], i);
- NOTREACHED();
- // It's harmless to call only SSL_SetPredictedServerHelloData.
- return false;
- }
- uint16 cert_len = static_cast<uint16>(data[j]) << 8 |
- static_cast<uint16>(data[j+1]);
- j += 2;
- if (static_cast<unsigned>(cert_len) + j > info.size()) {
- DestroyCertificates(&certs[0], i);
- NOTREACHED();
- return false;
- }
+ const std::vector<std::string>& certs_in = state.certs;
+ scoped_array<CERTCertificate*> certs(new CERTCertificate*[certs_in.size()]);
+ for (size_t i = 0; i < certs_in.size(); i++) {
SECItem derCert;
- derCert.data = const_cast<uint8*>(data + j);
- derCert.len = cert_len;
- j += cert_len;
+ derCert.data =
+ const_cast<uint8*>(reinterpret_cast<const uint8*>(certs_in[i].data()));
+ derCert.len = certs_in[i].size();
certs[i] = CERT_NewTempCertificate(
CERT_GetDefaultCertDB(), &derCert, NULL /* no nickname given */,
PR_FALSE /* not permanent */, PR_TRUE /* copy DER data */);
@@ -682,16 +571,14 @@ bool SSLClientSocketNSS::LoadSnapStartInfo(const std::string& info) {
}
}
- rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(), num_certs);
- DestroyCertificates(&certs[0], num_certs);
+ rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(), certs_in.size());
+ DestroyCertificates(&certs[0], certs_in.size());
DCHECK_EQ(SECSuccess, rv);
- predicted_npn_status_ = static_cast<NextProtoStatus>(npn_status);
- predicted_npn_proto_ = npn_proto;
-
- // We ignore any trailing data that might be in |info|.
- if (j != info.size())
- LOG(WARNING) << "Trailing data found in SSLHostInfo";
+ if (state.npn_valid) {
+ predicted_npn_status_ = state.npn_status;
+ predicted_npn_proto_ = state.npn_protocol;
+ }
return true;
}
@@ -1974,9 +1861,7 @@ int SSLClientSocketNSS::DoSnapStartLoadInfo() {
int rv = ssl_host_info_->WaitForDataReady(&handshake_io_callback_);
if (rv == OK) {
- LOG(ERROR) << "SSL host info size " << hostname_ << " "
- << ssl_host_info_->data().size();
- if (LoadSnapStartInfo(ssl_host_info_->data())) {
+ if (LoadSnapStartInfo()) {
pseudo_connected_ = true;
GotoState(STATE_SNAP_START_WAIT_FOR_WRITE);
if (user_connect_callback_)
diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h
index 8518084..56d16b2 100644
--- a/net/socket/ssl_client_socket_nss.h
+++ b/net/socket/ssl_client_socket_nss.h
@@ -103,7 +103,7 @@ class SSLClientSocketNSS : public SSLClientSocket {
int DoPayloadWrite();
int Init();
void SaveSnapStartInfo();
- bool LoadSnapStartInfo(const std::string& info);
+ bool LoadSnapStartInfo();
bool IsNPNProtocolMispredicted();
void UncorkAfterTimeout();
diff --git a/net/socket/ssl_client_socket_nss_factory.cc b/net/socket/ssl_client_socket_nss_factory.cc
index b5488d9..efa6e23 100644
--- a/net/socket/ssl_client_socket_nss_factory.cc
+++ b/net/socket/ssl_client_socket_nss_factory.cc
@@ -6,6 +6,7 @@
#include "build/build_config.h"
#include "net/socket/ssl_client_socket_nss.h"
+#include "net/socket/ssl_host_info.h"
#if defined(OS_WIN)
#include "net/socket/ssl_client_socket_win.h"
#endif
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index 048ff4b..98e3b09 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -8,13 +8,13 @@
#include "base/values.h"
#include "net/base/net_errors.h"
#include "net/base/ssl_cert_request_info.h"
-#include "net/base/ssl_host_info.h"
#include "net/http/http_proxy_client_socket.h"
#include "net/http/http_proxy_client_socket_pool.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/socks_client_socket_pool.h"
#include "net/socket/ssl_client_socket.h"
+#include "net/socket/ssl_host_info.h"
#include "net/socket/tcp_client_socket_pool.h"
namespace net {
diff --git a/net/socket/ssl_host_info.cc b/net/socket/ssl_host_info.cc
new file mode 100644
index 0000000..4b5bb02
--- /dev/null
+++ b/net/socket/ssl_host_info.cc
@@ -0,0 +1,100 @@
+// Copyright (c) 2010 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/socket/ssl_host_info.h"
+
+#include "net/socket/ssl_client_socket.h"
+#include "net/socket/ssl_host_info.pb.h"
+
+namespace net {
+
+SSLHostInfo::SSLHostInfo() {
+ state_.npn_valid = false;
+}
+
+SSLHostInfo::~SSLHostInfo() {}
+
+// This array and the next two functions serve to map between the internal NPN
+// status enum (which might change across versions) and the protocol buffer
+// based enum (which will not).
+static const struct {
+ SSLClientSocket::NextProtoStatus npn_status;
+ SSLHostInfoProto::NextProtoStatus proto_status;
+} kNPNStatusMapping[] = {
+ { SSLClientSocket::kNextProtoUnsupported, SSLHostInfoProto::UNSUPPORTED },
+ { SSLClientSocket::kNextProtoNegotiated, SSLHostInfoProto::NEGOTIATED },
+ { SSLClientSocket::kNextProtoNoOverlap, SSLHostInfoProto::NO_OVERLAP },
+};
+
+static SSLClientSocket::NextProtoStatus NPNStatusFromProtoStatus(
+ SSLHostInfoProto::NextProtoStatus proto_status) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNPNStatusMapping) - 1; i++) {
+ if (kNPNStatusMapping[i].proto_status == proto_status)
+ return kNPNStatusMapping[i].npn_status;
+ }
+ return kNPNStatusMapping[ARRAYSIZE_UNSAFE(kNPNStatusMapping) - 1].npn_status;
+}
+
+static SSLHostInfoProto::NextProtoStatus ProtoStatusFromNPNStatus(
+ SSLClientSocket::NextProtoStatus npn_status) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNPNStatusMapping) - 1; i++) {
+ if (kNPNStatusMapping[i].npn_status == npn_status)
+ return kNPNStatusMapping[i].proto_status;
+ }
+ return kNPNStatusMapping[ARRAYSIZE_UNSAFE(kNPNStatusMapping)-1].proto_status;
+}
+
+const SSLHostInfo::State& SSLHostInfo::state() const {
+ return state_;
+}
+
+SSLHostInfo::State* SSLHostInfo::mutable_state() {
+ return &state_;
+}
+
+bool SSLHostInfo::Parse(const std::string& data) {
+ SSLHostInfoProto proto;
+ State* state = mutable_state();
+
+ state->certs.clear();
+ state->server_hello.clear();
+ state->npn_valid = false;
+
+ if (!proto.ParseFromString(data))
+ return false;
+
+ for (int i = 0; i < proto.certificate_der_size(); i++)
+ state->certs.push_back(proto.certificate_der(i));
+ if (proto.has_server_hello())
+ state->server_hello = proto.server_hello();
+ if (proto.has_npn_status() && proto.has_npn_protocol()) {
+ state->npn_valid = true;
+ state->npn_status = NPNStatusFromProtoStatus(proto.npn_status());
+ state->npn_protocol = proto.npn_protocol();
+ }
+
+ return true;
+}
+
+std::string SSLHostInfo::Serialize() const {
+ SSLHostInfoProto proto;
+
+ for (std::vector<std::string>::const_iterator
+ i = state_.certs.begin(); i != state_.certs.end(); i++) {
+ proto.add_certificate_der(*i);
+ }
+ if (!state_.server_hello.empty())
+ proto.set_server_hello(state_.server_hello);
+
+ if (state_.npn_valid) {
+ proto.set_npn_status(ProtoStatusFromNPNStatus(state_.npn_status));
+ proto.set_npn_protocol(state_.npn_protocol);
+ }
+
+ return proto.SerializeAsString();
+}
+
+SSLHostInfoFactory::~SSLHostInfoFactory() {}
+
+} // namespace net
diff --git a/net/base/ssl_host_info.h b/net/socket/ssl_host_info.h
index ae9ac6a..8065b47 100644
--- a/net/base/ssl_host_info.h
+++ b/net/socket/ssl_host_info.h
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_BASE_SSL_HOST_INFO_H
-#define NET_BASE_SSL_HOST_INFO_H
+#ifndef NET_SOCKET_SSL_HOST_INFO_H
+#define NET_SOCKET_SSL_HOST_INFO_H
#include <string>
+#include <vector>
+
#include "base/ref_counted.h"
#include "net/base/completion_callback.h"
+#include "net/socket/ssl_client_socket.h"
namespace net {
@@ -17,6 +20,7 @@ namespace net {
// certificates.
class SSLHostInfo {
public:
+ SSLHostInfo();
virtual ~SSLHostInfo();
// Start will commence the lookup. This must be called before any other
@@ -36,16 +40,39 @@ class SSLHostInfo {
// but, obviously, a callback will never be made.
virtual int WaitForDataReady(CompletionCallback* callback) = 0;
- // data returns any host information once WaitForDataReady has indicated that
- // the fetch has completed. In the event of an error, |data| returns an empty
- // string.
- virtual const std::string& data() const = 0;
+ // Persist allows for the host information to be updated for future users.
+ // This is a fire and forget operation: the caller may drop its reference
+ // from this object and the store operation will still complete. This can
+ // only be called once WaitForDataReady has returned OK or called its
+ // callback.
+ virtual void Persist() = 0;
+
+ struct State {
+ // certs is a vector of DER encoded X.509 certificates, as the server
+ // returned them and in the same order.
+ std::vector<std::string> certs;
+ // server_hello contains the bytes of the ServerHello message (or may be
+ // empty if the server doesn't support Snap Start.)
+ std::string server_hello;
+ // npn_valid is true iff |npn_status| and |npn_protocol| is successful.
+ bool npn_valid;
+ // these members contain the NPN result of a connection to the server.
+ SSLClientSocket::NextProtoStatus npn_status;
+ std::string npn_protocol;
+ };
+
+ // Once the data is ready, it can be read using the following members. These
+ // members can then be updated before calling |Persist|.
+ const State& state() const;
+ State* mutable_state();
- // Set allows for the host information to be updated for future users. This
- // is a fire and forget operation: the caller may drop its reference from
- // this object and the store operation will still complete. This can only be
- // called once WaitForDataReady has returned OK or called its callback.
- virtual void Set(const std::string& new_data) = 0;
+ protected:
+ // Parse parses an opaque blob of data and fills out the public member fields
+ // of this object. It returns true iff the parse was successful. The public
+ // member fields will be set to something sane in any case.
+ bool Parse(const std::string& data);
+ std::string Serialize() const;
+ State state_;
};
class SSLHostInfoFactory {
@@ -59,4 +86,4 @@ class SSLHostInfoFactory {
} // namespace net
-#endif // NET_BASE_SSL_HOST_INFO_H
+#endif // NET_SOCKET_SSL_HOST_INFO_H
diff --git a/net/socket/ssl_host_info.proto b/net/socket/ssl_host_info.proto
new file mode 100644
index 0000000..d74a872
--- /dev/null
+++ b/net/socket/ssl_host_info.proto
@@ -0,0 +1,34 @@
+// Copyright (c) 2010 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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package net;
+
+// SSLHostInfoProto contains information which we store about a given HTTPS
+// server.
+message SSLHostInfoProto {
+ // The certificate chain, as returned by the server, as a series of DER
+ // encoded X.509 certificates.
+ repeated bytes certificate_der = 1;
+ // The contents of the server's ServerHello message. Needed in order to
+ // predict its response in the case of Snap Start.
+ optional bytes server_hello = 2;
+
+ // This is a mirror of SSLClientSocket::NextProtoStatus. We use this in order
+ // to be robust against changes to that enum, which isn't required to be
+ // stable across versions. See the comments there for details.
+ enum NextProtoStatus {
+ UNSUPPORTED = 0;
+ NEGOTIATED = 1;
+ NO_OVERLAP = 2;
+ }
+
+ // When doing Snap Start, we also need to know what protocol we expect the
+ // server to negotiate.
+ optional NextProtoStatus npn_status = 3;
+ optional bytes npn_protocol = 4;
+};
diff --git a/net/socket/tcp_client_socket_pool_unittest.cc b/net/socket/tcp_client_socket_pool_unittest.cc
index 32ac9f8..80de0aa 100644
--- a/net/socket/tcp_client_socket_pool_unittest.cc
+++ b/net/socket/tcp_client_socket_pool_unittest.cc
@@ -15,6 +15,7 @@
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_histograms.h"
#include "net/socket/socket_test_util.h"
+#include "net/socket/ssl_host_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {