Chromium Code Reviews| 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 |