Index: net/ssl/client_cert_store_nss.cc |
diff --git a/net/ssl/client_cert_store_nss.cc b/net/ssl/client_cert_store_nss.cc |
index ef29b55926a9bc5b64ce92a2022f8f788aaac291..7f543d73bb98df2e8017c19036e1a87f13501e8d 100644 |
--- a/net/ssl/client_cert_store_nss.cc |
+++ b/net/ssl/client_cert_store_nss.cc |
@@ -18,6 +18,7 @@ |
#include "base/strings/string_piece.h" |
#include "base/threading/worker_pool.h" |
#include "crypto/nss_crypto_module_delegate.h" |
+#include "net/cert/scoped_nss_types.h" |
#include "net/cert/x509_util.h" |
#include "net/ssl/ssl_cert_request_info.h" |
@@ -57,7 +58,6 @@ void ClientCertStoreNSS::GetClientCerts(const SSLCertRequestInfo& request, |
void ClientCertStoreNSS::FilterCertsOnWorkerThread( |
const CertificateList& certs, |
const SSLCertRequestInfo& request, |
- bool query_nssdb, |
CertificateList* filtered_certs) { |
DCHECK(filtered_certs); |
@@ -97,16 +97,39 @@ void ClientCertStoreNSS::FilterCertsOnWorkerThread( |
} |
// Check if the certificate issuer is allowed by the server. |
- if (request.cert_authorities.empty() || |
- (!query_nssdb && cert->IsIssuedByEncoded(request.cert_authorities)) || |
- (query_nssdb && |
- NSS_CmpCertChainWCANames(handle, &ca_names) == SECSuccess)) { |
- DVLOG(2) << "matched cert: " << base::StringPiece(handle->nickname); |
- filtered_certs->push_back(cert); |
- } else { |
+ if (!request.cert_authorities.empty() && |
+ NSS_CmpCertChainWCANames(handle, &ca_names) != SECSuccess) { |
DVLOG(2) << "skipped non-matching cert: " |
<< base::StringPiece(handle->nickname); |
+ continue; |
+ } |
+ |
+ DVLOG(2) << "matched cert: " << base::StringPiece(handle->nickname); |
+ |
+ // Build a certificate chain from |handle| to include any |
+ // intermediates. Some deployments expect the client to supply intermediates |
+ // out of the local store. https://crbug.com/548631 |
Ryan Sleevi
2016/02/05 23:51:24
Blah, I remember what the 'bug' was now.
So NSS_C
|
+ ScopedCERTCertificateList chain(CERT_CertChainFromCert( |
+ handle, certUsageSSLClient, PR_FALSE /* includeRoot */)); |
+ if (!chain) { |
+ DVLOG(2) << "could not build chain: " |
+ << base::StringPiece(handle->nickname); |
+ continue; |
+ } |
+ std::vector<base::StringPiece> der_chain; |
+ for (int i = 0; i < chain->len; i++) { |
+ der_chain.push_back( |
+ base::StringPiece(reinterpret_cast<const char*>(chain->certs[i].data), |
+ chain->certs[i].len)); |
+ } |
+ scoped_refptr<X509Certificate> full_cert = |
+ X509Certificate::CreateFromDERCertChain(der_chain); |
Ryan Sleevi
2016/02/05 23:51:24
This actually forces NSS through a full reparse an
|
+ if (!full_cert.get()) { |
+ DVLOG(2) << "could not decode chain: " |
+ << base::StringPiece(handle->nickname); |
+ continue; |
} |
+ filtered_certs->push_back(full_cert); |
} |
DVLOG(2) << "num_raw:" << num_raw |
<< " num_filtered:" << filtered_certs->size(); |
@@ -121,7 +144,7 @@ void ClientCertStoreNSS::GetAndFilterCertsOnWorkerThread( |
CertificateList* selected_certs) { |
CertificateList platform_certs; |
GetPlatformCertsOnWorkerThread(std::move(password_delegate), &platform_certs); |
- FilterCertsOnWorkerThread(platform_certs, *request, true, selected_certs); |
+ FilterCertsOnWorkerThread(platform_certs, *request, selected_certs); |
} |
// static |