| 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();
|
|
|