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..09b594fd71da39bd5b72aac3378943834a04e08b 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,47 @@ |
#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 { |
+ 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); |
+ } |
+ |
+ private: |
+ scoped_refptr<crypto::CryptoModuleBlockingPasswordDelegate> |
+ password_delegate_; |
+}; |
+ |
+} // namespace |
+ |
ClientCertStoreNSS::ClientCertStoreNSS( |
const PasswordDelegateFactory& password_delegate_factory) |
: password_delegate_factory_(password_delegate_factory) {} |
@@ -36,40 +74,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 +132,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 +177,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); |
} |