summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-04 02:22:04 +0000
committerrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-04 02:22:04 +0000
commit5946838ef91d54c07e4cf2c345b61ae7eb6db064 (patch)
treec4984bd5a4281fe4096643c402b247967a75adb7 /net
parent9b15b2fc4de826bc676da810a0f27371d269d95e (diff)
downloadchromium_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.cc10
-rw-r--r--net/base/net_log_event_type_list.h16
-rw-r--r--net/base/x509_certificate.cc41
-rw-r--r--net/base/x509_certificate.h12
-rw-r--r--net/base/x509_certificate_net_log_param.cc28
-rw-r--r--net/base/x509_certificate_net_log_param.h35
-rw-r--r--net/net.gyp2
-rw-r--r--net/socket/ssl_client_socket_mac.cc6
-rw-r--r--net/socket/ssl_client_socket_nss.cc6
-rw-r--r--net/socket/ssl_client_socket_openssl.cc6
-rw-r--r--net/socket/ssl_client_socket_win.cc13
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);