| 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 7f22765b608c68878d963c46d21baac6b1ffba9f..4756a8bb2e7f81c5b8d9131eca5e97b20f5fe260 100644
|
| --- a/net/ssl/client_cert_store_nss.cc
|
| +++ b/net/ssl/client_cert_store_nss.cc
|
| @@ -16,6 +16,7 @@
|
| #include "base/bind_helpers.h"
|
| #include "base/location.h"
|
| #include "base/logging.h"
|
| +#include "base/memory/ptr_util.h"
|
| #include "base/strings/string_piece.h"
|
| #include "base/task_runner_util.h"
|
| #include "base/threading/worker_pool.h"
|
| @@ -23,10 +24,51 @@
|
| #include "net/cert/scoped_nss_types.h"
|
| #include "net/cert/x509_util.h"
|
| #include "net/ssl/ssl_cert_request_info.h"
|
| +#include "net/ssl/ssl_platform_key_nss.h"
|
| +#include "net/ssl/threaded_ssl_private_key.h"
|
| #include "net/third_party/nss/ssl/cmpcert.h"
|
|
|
| namespace net {
|
|
|
| +namespace {
|
| +
|
| +class ClientCertIdentityNSS : public ClientCertIdentity {
|
| + public:
|
| + ClientCertIdentityNSS(
|
| + scoped_refptr<net::X509Certificate> cert,
|
| + scoped_refptr<crypto::CryptoModuleBlockingPasswordDelegate>
|
| + password_delegate)
|
| + : ClientCertIdentity(std::move(cert)),
|
| + password_delegate_(std::move(password_delegate)) {}
|
| + ~ClientCertIdentityNSS() override = default;
|
| +
|
| + void AcquirePrivateKey(
|
| + const base::Callback<void(scoped_refptr<SSLPrivateKey>)>&
|
| + private_key_callback) override;
|
| +
|
| + private:
|
| + scoped_refptr<crypto::CryptoModuleBlockingPasswordDelegate>
|
| + password_delegate_;
|
| +};
|
| +
|
| +void ClientCertIdentityNSS::AcquirePrivateKey(
|
| + const base::Callback<void(scoped_refptr<SSLPrivateKey>)>&
|
| + private_key_callback) {
|
| + if (base::PostTaskAndReplyWithResult(
|
| + base::WorkerPool::GetTaskRunner(true /* task_is_slow */).get(),
|
| + FROM_HERE,
|
| + base::Bind(&FetchClientCertPrivateKey,
|
| + base::RetainedRef(certificate()),
|
| + base::RetainedRef(password_delegate_)),
|
| + private_key_callback)) {
|
| + return;
|
| + }
|
| + // If the task could not be posted, behave as if there was no key.
|
| + private_key_callback.Run(nullptr);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| ClientCertStoreNSS::ClientCertStoreNSS(
|
| const PasswordDelegateFactory& password_delegate_factory)
|
| : password_delegate_factory_(password_delegate_factory) {}
|
| @@ -36,40 +78,37 @@ ClientCertStoreNSS::~ClientCertStoreNSS() {}
|
| void ClientCertStoreNSS::GetClientCerts(
|
| const SSLCertRequestInfo& request,
|
| const ClientCertListCallback& callback) {
|
| - std::unique_ptr<crypto::CryptoModuleBlockingPasswordDelegate>
|
| - password_delegate;
|
| - if (!password_delegate_factory_.is_null()) {
|
| - password_delegate.reset(
|
| - password_delegate_factory_.Run(request.host_and_port));
|
| - }
|
| + scoped_refptr<crypto::CryptoModuleBlockingPasswordDelegate> password_delegate;
|
| + if (!password_delegate_factory_.is_null())
|
| + password_delegate = password_delegate_factory_.Run(request.host_and_port);
|
| if (base::PostTaskAndReplyWithResult(
|
| base::WorkerPool::GetTaskRunner(true /* task_is_slow */).get(),
|
| FROM_HERE,
|
| base::Bind(&ClientCertStoreNSS::GetAndFilterCertsOnWorkerThread,
|
| // Caller is responsible for keeping the ClientCertStore
|
| // alive until the callback is run.
|
| - base::Unretained(this), base::Passed(&password_delegate),
|
| + base::Unretained(this), std::move(password_delegate),
|
| &request),
|
| callback)) {
|
| return;
|
| }
|
| // If the task could not be posted, behave as if there were no certificates.
|
| - callback.Run(CertificateList());
|
| + callback.Run(ClientCertIdentityList());
|
| }
|
|
|
| // static
|
| void ClientCertStoreNSS::FilterCertsOnWorkerThread(
|
| - const CertificateList& certs,
|
| - const SSLCertRequestInfo& request,
|
| - CertificateList* filtered_certs) {
|
| - DCHECK(filtered_certs);
|
| + ClientCertIdentityList* identities,
|
| + const SSLCertRequestInfo& request) {
|
| + size_t num_raw = 0;
|
|
|
| - filtered_certs->clear();
|
| + auto keep_iter = identities->begin();
|
|
|
| - size_t num_raw = 0;
|
| - for (const auto& cert : certs) {
|
| + for (auto examine_iter = identities->begin();
|
| + examine_iter != identities->end(); ++examine_iter) {
|
| ++num_raw;
|
| - X509Certificate::OSCertHandle handle = cert->os_cert_handle();
|
| + X509Certificate::OSCertHandle handle =
|
| + (*examine_iter)->certificate()->os_cert_handle();
|
|
|
| // Only offer unexpired certificates.
|
| if (CERT_CheckCertValidTimes(handle, PR_Now(), PR_TRUE) !=
|
| @@ -97,34 +136,36 @@ void ClientCertStoreNSS::FilterCertsOnWorkerThread(
|
| // 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));
|
| - // |handle| was successfully parsed by |cert|, so this should never fail.
|
| - DCHECK(filtered_certs->back());
|
| + (*examine_iter)->SetIntermediates(intermediates_raw);
|
| +
|
| + if (examine_iter == keep_iter)
|
| + ++keep_iter;
|
| + else
|
| + *keep_iter++ = std::move(*examine_iter);
|
| }
|
| - DVLOG(2) << "num_raw:" << num_raw
|
| - << " num_filtered:" << filtered_certs->size();
|
| + identities->erase(keep_iter, identities->end());
|
| +
|
| + DVLOG(2) << "num_raw:" << num_raw << " num_filtered:" << identities->size();
|
|
|
| - std::sort(filtered_certs->begin(), filtered_certs->end(),
|
| - x509_util::ClientCertSorter());
|
| + std::sort(identities->begin(), identities->end(), ClientCertIdentitySorter());
|
| }
|
|
|
| -CertificateList ClientCertStoreNSS::GetAndFilterCertsOnWorkerThread(
|
| - std::unique_ptr<crypto::CryptoModuleBlockingPasswordDelegate>
|
| +ClientCertIdentityList ClientCertStoreNSS::GetAndFilterCertsOnWorkerThread(
|
| + scoped_refptr<crypto::CryptoModuleBlockingPasswordDelegate>
|
| password_delegate,
|
| const SSLCertRequestInfo* request) {
|
| - CertificateList platform_certs;
|
| - GetPlatformCertsOnWorkerThread(std::move(password_delegate), &platform_certs);
|
| - CertificateList selected_certs;
|
| - FilterCertsOnWorkerThread(platform_certs, *request, &selected_certs);
|
| - return selected_certs;
|
| + ClientCertIdentityList selected_identities;
|
| + GetPlatformCertsOnWorkerThread(std::move(password_delegate),
|
| + &selected_identities);
|
| + FilterCertsOnWorkerThread(&selected_identities, *request);
|
| + return selected_identities;
|
| }
|
|
|
| // static
|
| void ClientCertStoreNSS::GetPlatformCertsOnWorkerThread(
|
| - std::unique_ptr<crypto::CryptoModuleBlockingPasswordDelegate>
|
| + scoped_refptr<crypto::CryptoModuleBlockingPasswordDelegate>
|
| password_delegate,
|
| - net::CertificateList* certs) {
|
| + ClientCertIdentityList* identities) {
|
| CERTCertList* found_certs =
|
| CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(), certUsageSSLClient,
|
| PR_FALSE, PR_FALSE, password_delegate.get());
|
| @@ -140,7 +181,8 @@ void ClientCertStoreNSS::GetPlatformCertsOnWorkerThread(
|
| DVLOG(2) << "X509Certificate::CreateFromHandle failed";
|
| continue;
|
| }
|
| - certs->push_back(std::move(cert));
|
| + identities->push_back(
|
| + base::MakeUnique<ClientCertIdentityNSS>(cert, password_delegate));
|
| }
|
| CERT_DestroyCertList(found_certs);
|
| }
|
|
|