summaryrefslogtreecommitdiffstats
path: root/net/socket/ssl_client_socket_nss.cc
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-28 15:16:09 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-28 15:16:09 +0000
commit1757070507965c07af1f19790311e5732d9a9d42 (patch)
treed647c9b985f90983c9aed537f711eb059949962a /net/socket/ssl_client_socket_nss.cc
parent587b8066b4d994a10986fbeef624aba4c69b4cfe (diff)
downloadchromium_src-1757070507965c07af1f19790311e5732d9a9d42.zip
chromium_src-1757070507965c07af1f19790311e5732d9a9d42.tar.gz
chromium_src-1757070507965c07af1f19790311e5732d9a9d42.tar.bz2
net: use SSL_PeerCertificateChain for SSLHostInfo
Previously we would extract the chain built by NSS which may not have matched the actual chain sent by the server. Since we use the SSLHostInfo recorded chain for Snap Start prediction, this would trigger mispredicts. TEST=none BUG=none http://codereview.chromium.org/4103005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64245 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket/ssl_client_socket_nss.cc')
-rw-r--r--net/socket/ssl_client_socket_nss.cc61
1 files changed, 42 insertions, 19 deletions
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index f62c7b1..325f7c2 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -359,6 +359,43 @@ BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context,
#endif
+// PeerCertificateChain is a helper object which extracts the certificate
+// chain, as given by the server, from an NSS socket and performs the needed
+// resource management. The first element of the chain is the leaf certificate
+// and the other elements are in the order given by the server.
+class PeerCertificateChain {
+ public:
+ PeerCertificateChain(PRFileDesc* nss_fd)
+ : num_certs_(0),
+ certs_(NULL) {
+ SECStatus rv = SSL_PeerCertificateChain(nss_fd, NULL, &num_certs_);
+ DCHECK_EQ(rv, SECSuccess);
+
+ certs_ = new CERTCertificate*[num_certs_];
+ const unsigned expected_num_certs = num_certs_;
+ rv = SSL_PeerCertificateChain(nss_fd, certs_, &num_certs_);
+ DCHECK_EQ(rv, SECSuccess);
+ DCHECK_EQ(num_certs_, expected_num_certs);
+ }
+
+ ~PeerCertificateChain() {
+ for (unsigned i = 0; i < num_certs_; i++)
+ CERT_DestroyCertificate(certs_[i]);
+ delete[] certs_;
+ }
+
+ unsigned size() const { return num_certs_; }
+
+ CERTCertificate* operator[](unsigned i) {
+ DCHECK_LT(i, num_certs_);
+ return certs_[i];
+ }
+
+ private:
+ unsigned num_certs_;
+ CERTCertificate** certs_;
+};
+
} // namespace
SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
@@ -468,33 +505,19 @@ void SSLClientSocketNSS::SaveSnapStartInfo() {
state->npn_valid = false;
}
- // TODO(wtc): CERT_GetCertChainFromCert might not return the same cert chain
- // that the Certificate message actually contained. http://crbug.com/48854
- CERTCertList* cert_list = CERT_GetCertChainFromCert(
- server_cert_nss_, PR_Now(), certUsageSSLCA);
- if (!cert_list)
- return;
-
state->certs.clear();
- for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
- !CERT_LIST_END(node, cert_list);
- node = CERT_LIST_NEXT(node)) {
- if (node->cert->derCert.len > std::numeric_limits<uint16>::max()) {
- CERT_DestroyCertList(cert_list);
+ PeerCertificateChain certs(nss_fd_);
+ for (unsigned i = 0; i < certs.size(); i++) {
+ if (certs[i]->derCert.len > std::numeric_limits<uint16>::max())
return;
- }
- if (node->cert->isRoot == PR_TRUE)
- continue;
state->certs.push_back(std::string(
- reinterpret_cast<char*>(node->cert->derCert.data),
- node->cert->derCert.len));
+ reinterpret_cast<char*>(certs[i]->derCert.data),
+ certs[i]->derCert.len));
}
LOG(ERROR) << "Setting Snap Start info " << hostname_;
ssl_host_info_->Persist();
-
- CERT_DestroyCertList(cert_list);
}
static void DestroyCertificates(CERTCertificate** certs, unsigned len) {