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 e46458ad99e166657007407f056cecac79ff4a5f..dab47284180a3ea0f2bf2618edc2cf197da3853c 100644 |
--- a/net/ssl/client_cert_store_nss.cc |
+++ b/net/ssl/client_cert_store_nss.cc |
@@ -10,6 +10,7 @@ |
#include <algorithm> |
#include <memory> |
#include <utility> |
+#include <vector> |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
@@ -18,8 +19,10 @@ |
#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" |
+#include "net/third_party/nss/ssl/cmpcert.h" |
namespace net { |
@@ -63,26 +66,6 @@ void ClientCertStoreNSS::FilterCertsOnWorkerThread( |
filtered_certs->clear(); |
- // Create a "fake" CERTDistNames structure. No public API exists to create |
- // one from a list of issuers. |
- CERTDistNames ca_names; |
- ca_names.arena = NULL; |
- ca_names.nnames = 0; |
- ca_names.names = NULL; |
- ca_names.head = NULL; |
- |
- std::vector<SECItem> ca_names_items(request.cert_authorities.size()); |
- for (size_t i = 0; i < request.cert_authorities.size(); ++i) { |
- const std::string& authority = request.cert_authorities[i]; |
- ca_names_items[i].type = siBuffer; |
- ca_names_items[i].data = |
- reinterpret_cast<unsigned char*>(const_cast<char*>(authority.data())); |
- ca_names_items[i].len = static_cast<unsigned int>(authority.size()); |
- } |
- ca_names.nnames = static_cast<int>(ca_names_items.size()); |
- if (!ca_names_items.empty()) |
- ca_names.names = &ca_names_items[0]; |
- |
size_t num_raw = 0; |
for (const auto& cert : certs) { |
++num_raw; |
@@ -96,16 +79,26 @@ void ClientCertStoreNSS::FilterCertsOnWorkerThread( |
continue; |
} |
- // Check if the certificate issuer is allowed by the server. |
- if (!request.cert_authorities.empty() && |
- NSS_CmpCertChainWCANames(handle, &ca_names) != SECSuccess) { |
+ std::vector<ScopedCERTCertificate> intermediates; |
+ if (!MatchClientCertificateIssuers(handle, request.cert_authorities, |
+ &intermediates)) { |
DVLOG(2) << "skipped non-matching cert: " |
<< base::StringPiece(handle->nickname); |
continue; |
} |
DVLOG(2) << "matched cert: " << base::StringPiece(handle->nickname); |
- filtered_certs->push_back(cert); |
+ |
+ X509Certificate::OSCertHandles intermediates_raw; |
+ for (const auto& intermediate : intermediates) { |
+ intermediates_raw.push_back(intermediate.get()); |
+ } |
+ |
+ // Retain a copy of the intermediates. Some deployments expect the client to |
+ // supply intermediates out of the local store. See |
+ // https://crbug.com/548631. |
+ filtered_certs->push_back( |
+ X509Certificate::CreateFromHandle(handle, intermediates_raw)); |
} |
DVLOG(2) << "num_raw:" << num_raw |
<< " num_filtered:" << filtered_certs->size(); |