diff options
author | rsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-04 02:22:04 +0000 |
---|---|---|
committer | rsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-04 02:22:04 +0000 |
commit | 5946838ef91d54c07e4cf2c345b61ae7eb6db064 (patch) | |
tree | c4984bd5a4281fe4096643c402b247967a75adb7 /net | |
parent | 9b15b2fc4de826bc676da810a0f27371d269d95e (diff) | |
download | chromium_src-5946838ef91d54c07e4cf2c345b61ae7eb6db064.zip chromium_src-5946838ef91d54c07e4cf2c345b61ae7eb6db064.tar.gz chromium_src-5946838ef91d54c07e4cf2c345b61ae7eb6db064.tar.bz2 |
Log the (server, to-be-verified) certificate chains to the NetLog when logging bytes.
BUG=91464
Review URL: http://codereview.chromium.org/8413072
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108615 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/cert_verifier.cc | 10 | ||||
-rw-r--r-- | net/base/net_log_event_type_list.h | 16 | ||||
-rw-r--r-- | net/base/x509_certificate.cc | 41 | ||||
-rw-r--r-- | net/base/x509_certificate.h | 12 | ||||
-rw-r--r-- | net/base/x509_certificate_net_log_param.cc | 28 | ||||
-rw-r--r-- | net/base/x509_certificate_net_log_param.h | 35 | ||||
-rw-r--r-- | net/net.gyp | 2 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_mac.cc | 6 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 6 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_openssl.cc | 6 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_win.cc | 13 |
11 files changed, 171 insertions, 4 deletions
diff --git a/net/base/cert_verifier.cc b/net/base/cert_verifier.cc index 1a80b40..2c703eb 100644 --- a/net/base/cert_verifier.cc +++ b/net/base/cert_verifier.cc @@ -17,6 +17,7 @@ #include "net/base/net_errors.h" #include "net/base/net_log.h" #include "net/base/x509_certificate.h" +#include "net/base/x509_certificate_net_log_param.h" #if defined(USE_NSS) #include <private/pprthred.h> // PR_DetachThread @@ -155,6 +156,10 @@ class CertVerifierWorker { error_(ERR_FAILED) { } + // Returns the certificate being verified. May only be called /before/ + // Start() is called. + X509Certificate* certificate() const { return cert_; } + bool Start() { DCHECK_EQ(MessageLoop::current(), origin_loop_); @@ -261,7 +266,10 @@ class CertVerifierJob { : start_time_(base::TimeTicks::Now()), worker_(worker), net_log_(net_log) { - net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_JOB, NULL); + scoped_refptr<NetLog::EventParameters> params; + if (net_log_.IsLoggingBytes()) + params = new X509CertificateNetLogParam(worker_->certificate()); + net_log_.BeginEvent(NetLog::TYPE_CERT_VERIFIER_JOB, params); } ~CertVerifierJob() { diff --git a/net/base/net_log_event_type_list.h b/net/base/net_log_event_type_list.h index 8ebca16..aa9d890 100644 --- a/net/base/net_log_event_type_list.h +++ b/net/base/net_log_event_type_list.h @@ -486,6 +486,15 @@ EVENT_TYPE(SSL_SOCKET_BYTES_SENT) EVENT_TYPE(SOCKET_BYTES_RECEIVED) EVENT_TYPE(SSL_SOCKET_BYTES_RECEIVED) +// Certificates were received from the SSL server (during a handshake or +// renegotiation). This event is only present when logging at LOG_ALL. +// The following parameters are attached to the event: +// { +// "certificates": <A list of PEM encoded certificates in the order that +// they were sent by the server>, +// } +EVENT_TYPE(SSL_CERTIFICATES_RECEIVED) + // ------------------------------------------------------------------------ // DatagramSocket // ------------------------------------------------------------------------ @@ -1320,6 +1329,13 @@ EVENT_TYPE(CHROME_POLICY_ABORTED_REQUEST) EVENT_TYPE(CERT_VERIFIER_REQUEST) // This event is created when we start a CertVerifier job. +// The END phase event parameters are: +// { +// "certificates": <A list of PEM encoded certificates, the first one +// being the certificate to verify and the remaining +// being intermediate certificates to assist path +// building. Only present when byte logging is enabled.> +// } EVENT_TYPE(CERT_VERIFIER_JOB) // This event is created when a CertVerifier request attaches to a job. diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate.cc index 7bc2ab9..ccbc554 100644 --- a/net/base/x509_certificate.cc +++ b/net/base/x509_certificate.cc @@ -11,6 +11,7 @@ #include <string> #include <vector> +#include "base/base64.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/singleton.h" @@ -601,6 +602,46 @@ bool X509Certificate::VerifyNameMatch(const std::string& hostname) const { } #endif +// static +bool X509Certificate::GetPEMEncoded(OSCertHandle cert_handle, + std::string* pem_encoded) { + std::string der_encoded; + if (!GetDEREncoded(cert_handle, &der_encoded) || der_encoded.empty()) + return false; + std::string b64_encoded; + if (!base::Base64Encode(der_encoded, &b64_encoded) || b64_encoded.empty()) + return false; + *pem_encoded = "-----BEGIN CERTIFICATE-----\n"; + + // Divide the Base-64 encoded data into 64-character chunks, as per + // 4.3.2.4 of RFC 1421. + static const size_t kChunkSize = 64; + size_t chunks = (b64_encoded.size() + (kChunkSize - 1)) / kChunkSize; + for (size_t i = 0, chunk_offset = 0; i < chunks; + ++i, chunk_offset += kChunkSize) { + pem_encoded->append(b64_encoded, chunk_offset, kChunkSize); + pem_encoded->append("\n"); + } + pem_encoded->append("-----END CERTIFICATE-----\n"); + return true; +} + +bool X509Certificate::GetPEMEncodedChain( + std::vector<std::string>* pem_encoded) const { + std::vector<std::string> encoded_chain; + std::string pem_data; + if (!GetPEMEncoded(os_cert_handle(), &pem_data)) + return false; + encoded_chain.push_back(pem_data); + for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { + if (!GetPEMEncoded(intermediate_ca_certs_[i], &pem_data)) + return false; + encoded_chain.push_back(pem_data); + } + pem_encoded->swap(encoded_chain); + return true; +} + X509Certificate::X509Certificate(OSCertHandle cert_handle, const OSCertHandles& intermediates) : cert_handle_(DupOSCertHandle(cert_handle)) { diff --git a/net/base/x509_certificate.h b/net/base/x509_certificate.h index 8337c7b..e24d88e 100644 --- a/net/base/x509_certificate.h +++ b/net/base/x509_certificate.h @@ -392,6 +392,18 @@ class NET_EXPORT X509Certificate static bool GetDEREncoded(OSCertHandle cert_handle, std::string* der_encoded); + // Returns the PEM encoded data from an OSCertHandle. If the return value is + // true, then the PEM encoded certificate is written to |pem_encoded|. + static bool GetPEMEncoded(OSCertHandle cert_handle, + std::string* pem_encoded); + + // Encodes the entire certificate chain (this certificate and any + // intermediate certificates stored in |intermediate_ca_certs_|) as a series + // of PEM encoded strings. Returns true if all certificates were encoded, + // storig the result in |*pem_encoded|, with this certificate stored as + // the first element. + bool GetPEMEncodedChain(std::vector<std::string>* pem_encoded) const; + // Returns the OSCertHandle of this object. Because of caching, this may // differ from the OSCertHandle originally supplied during initialization. // Note: On Windows, CryptoAPI may return unexpected results if this handle diff --git a/net/base/x509_certificate_net_log_param.cc b/net/base/x509_certificate_net_log_param.cc new file mode 100644 index 0000000..03e8a3cb --- /dev/null +++ b/net/base/x509_certificate_net_log_param.cc @@ -0,0 +1,28 @@ +// Copyright (c) 2011 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/x509_certificate_net_log_param.h" + +#include "base/values.h" +#include "net/base/x509_certificate.h" + +namespace net { + +X509CertificateNetLogParam::X509CertificateNetLogParam( + X509Certificate* certificate) { + certificate->GetPEMEncodedChain(&encoded_chain_); +} + +X509CertificateNetLogParam::~X509CertificateNetLogParam() {} + +base::Value* X509CertificateNetLogParam::ToValue() const { + DictionaryValue* dict = new DictionaryValue(); + ListValue* certs = new ListValue(); + for (size_t i = 0; i < encoded_chain_.size(); ++i) + certs->Append(base::Value::CreateStringValue(encoded_chain_[i])); + dict->Set("certificates", certs); + return dict; +} + +} // namespace net diff --git a/net/base/x509_certificate_net_log_param.h b/net/base/x509_certificate_net_log_param.h new file mode 100644 index 0000000..97b8515f --- /dev/null +++ b/net/base/x509_certificate_net_log_param.h @@ -0,0 +1,35 @@ +// Copyright (c) 2011 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_BASE_X509_CERT_NET_LOG_PARAM_H_ +#define NET_BASE_X509_CERT_NET_LOG_PARAM_H_ +#pragma once + +#include <string> +#include <vector> + +#include "base/compiler_specific.h" +#include "net/base/net_log.h" + +namespace net { + +class X509Certificate; + +// NetLog parameter to describe an X509Certificate. +// Note: These parameters are memory intensive, due to PEM-encoding each +// certificate, thus should only be used when logging at NetLog::LOG_ALL. +class X509CertificateNetLogParam : public NetLog::EventParameters { + public: + explicit X509CertificateNetLogParam(X509Certificate* certificate); + virtual ~X509CertificateNetLogParam(); + + virtual base::Value* ToValue() const OVERRIDE; + + private: + std::vector<std::string> encoded_chain_; +}; + +} // namespace net + +#endif // NET_BASE_X509_CERT_NET_LOG_PARAM_H_ diff --git a/net/net.gyp b/net/net.gyp index c9c292d..09b9f97 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -243,6 +243,8 @@ 'base/x509_certificate.cc', 'base/x509_certificate.h', 'base/x509_certificate_mac.cc', + 'base/x509_certificate_net_log_param.cc', + 'base/x509_certificate_net_log_param.h', 'base/x509_certificate_nss.cc', 'base/x509_certificate_openssl.cc', 'base/x509_certificate_win.cc', diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc index 77ba0cf..527cad5 100644 --- a/net/socket/ssl_client_socket_mac.cc +++ b/net/socket/ssl_client_socket_mac.cc @@ -23,6 +23,7 @@ #include "net/base/ssl_cert_request_info.h" #include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" +#include "net/base/x509_certificate_net_log_param.h" #include "net/socket/client_socket_handle.h" #include "net/socket/ssl_error_params.h" @@ -1284,6 +1285,11 @@ int SSLClientSocketMac::DidCompleteHandshake() { GetServerCert(ssl_context_)); if (!new_server_cert) return ERR_UNEXPECTED; + if (net_log_.IsLoggingBytes()) { + net_log_.AddEvent( + NetLog::TYPE_SSL_CERTIFICATES_RECEIVED, + make_scoped_refptr(new X509CertificateNetLogParam(new_server_cert))); + } if (renegotiating_ && X509Certificate::IsSameOSCert(server_cert_->os_cert_handle(), diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index bee836e..7426c10 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -92,6 +92,7 @@ #include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" #include "net/base/sys_addrinfo.h" +#include "net/base/x509_certificate_net_log_param.h" #include "net/ocsp/nss_ocsp.h" #include "net/socket/client_socket_handle.h" #include "net/socket/dns_cert_provenance_checker.h" @@ -1055,6 +1056,11 @@ void SSLClientSocketNSS::UpdateServerCert() { // case CreateFromDERCertChain() returns NULL. server_cert_ = X509Certificate::CreateFromDERCertChain( certs.AsStringPieceVector()); + if (server_cert_ && net_log_.IsLoggingBytes()) { + net_log_.AddEvent( + NetLog::TYPE_SSL_CERTIFICATES_RECEIVED, + make_scoped_refptr(new X509CertificateNetLogParam(server_cert_))); + } } } } diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc index fa7f2a1..a2e3a19 100644 --- a/net/socket/ssl_client_socket_openssl.cc +++ b/net/socket/ssl_client_socket_openssl.cc @@ -21,6 +21,7 @@ #include "net/base/ssl_cert_request_info.h" #include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" +#include "net/base/x509_certificate_net_log_param.h" #include "net/socket/ssl_error_params.h" namespace net { @@ -760,6 +761,11 @@ int SSLClientSocketOpenSSL::DoHandshake() { // SSL handshake is completed. Let's verify the certificate. const bool got_cert = !!UpdateServerCert(); DCHECK(got_cert); + if (net_log_.IsLoggingBytes()) { + net_log_.AddEvent( + NetLog::TYPE_SSL_CERTIFICATES_RECEIVED, + make_scoped_refptr(new X509CertificateNetLogParam(server_cert_))); + } GotoState(STATE_VERIFY_CERT); } else { int ssl_error = SSL_get_error(ssl_, rv); diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc index 13fd101..98dde95 100644 --- a/net/socket/ssl_client_socket_win.cc +++ b/net/socket/ssl_client_socket_win.cc @@ -23,6 +23,7 @@ #include "net/base/ssl_cert_request_info.h" #include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" +#include "net/base/x509_certificate_net_log_param.h" #include "net/socket/client_socket_handle.h" #pragma comment(lib, "secur32.lib") @@ -1519,6 +1520,14 @@ int SSLClientSocketWin::DidCompleteHandshake() { LOG(ERROR) << "QueryContextAttributes (remote cert) failed: " << status; return MapSecurityError(status); } + scoped_refptr<X509Certificate> new_server_cert( + X509Certificate::CreateFromHandle(server_cert_handle, + X509Certificate::OSCertHandles())); + if (net_log_.IsLoggingBytes()) { + net_log_.AddEvent( + NetLog::TYPE_SSL_CERTIFICATES_RECEIVED, + make_scoped_refptr(new X509CertificateNetLogParam(new_server_cert))); + } if (renegotiating_ && X509Certificate::IsSameOSCert(server_cert_->os_cert_handle(), server_cert_handle)) { @@ -1526,9 +1535,7 @@ int SSLClientSocketWin::DidCompleteHandshake() { // user has accepted the certificate error. DidCompleteRenegotiation(); } else { - server_cert_ = X509Certificate::CreateFromHandle( - server_cert_handle, X509Certificate::OSCertHandles()); - + server_cert_ = new_server_cert; next_state_ = STATE_VERIFY_CERT; } CertFreeCertificateContext(server_cert_handle); |