Chromium Code Reviews| Index: net/ssl/client_cert_store_win.cc |
| diff --git a/net/ssl/client_cert_store_win.cc b/net/ssl/client_cert_store_win.cc |
| index fec9c33ae67b7d108e0468e4d686e606822213a1..891161f368a1083c6219221f702aeade8b0d2061 100644 |
| --- a/net/ssl/client_cert_store_win.cc |
| +++ b/net/ssl/client_cert_store_win.cc |
| @@ -11,15 +11,54 @@ |
| #include <windows.h> |
| #include <security.h> |
| +#include "base/bind.h" |
| +#include "base/bind_helpers.h" |
| #include "base/callback.h" |
| #include "base/logging.h" |
| +#include "base/memory/ptr_util.h" |
| +#include "base/task_runner_util.h" |
| #include "crypto/wincrypt_shim.h" |
| #include "net/cert/x509_util.h" |
| +#include "net/ssl/ssl_platform_key_util.h" |
| +#include "net/ssl/ssl_platform_key_win.h" |
| +#include "net/ssl/ssl_private_key.h" |
| namespace net { |
| namespace { |
| +class ClientCertIdentityWin : public ClientCertIdentity { |
| + public: |
| + // Takes ownership of |cert_context|. |
| + ClientCertIdentityWin(scoped_refptr<net::X509Certificate> cert, |
| + PCCERT_CONTEXT cert_context) |
| + : ClientCertIdentity(std::move(cert)), cert_context_(cert_context) {} |
| + ~ClientCertIdentityWin() override { |
| + CertFreeCertificateContext(cert_context_); |
| + } |
| + |
| + void AcquirePrivateKey( |
| + const base::Callback<void(scoped_refptr<SSLPrivateKey>)>& |
| + private_key_callback) override; |
| + |
| + private: |
| + PCCERT_CONTEXT cert_context_; |
| +}; |
| + |
| +void ClientCertIdentityWin::AcquirePrivateKey( |
| + const base::Callback<void(scoped_refptr<SSLPrivateKey>)>& |
| + private_key_callback) { |
| + if (base::PostTaskAndReplyWithResult( |
| + GetSSLPlatformKeyTaskRunner().get(), FROM_HERE, |
| + base::Bind(&FetchClientCertPrivateKey, |
| + base::Unretained(certificate()), cert_context_), |
| + private_key_callback)) { |
| + return; |
| + } |
| + // If the task could not be posted, behave as if there was no key. |
| + private_key_callback.Run(nullptr); |
| +} |
| + |
| // Callback required by Windows API function CertFindChainInStore(). In addition |
| // to filtering by extended/enhanced key usage, we do not show expired |
| // certificates and require digital signature usage in the key usage extension. |
| @@ -65,8 +104,8 @@ static BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context, |
| void GetClientCertsImpl(HCERTSTORE cert_store, |
| const SSLCertRequestInfo& request, |
| - CertificateList* selected_certs) { |
| - selected_certs->clear(); |
| + ClientCertIdentityList* selected_identities) { |
| + selected_identities->clear(); |
| const size_t auth_count = request.cert_authorities.size(); |
| std::vector<CERT_NAME_BLOB> issuers(auth_count); |
| @@ -149,15 +188,17 @@ void GetClientCertsImpl(HCERTSTORE cert_store, |
| // pair<X509Certificate, SSLPrivateKeyCallback>. |
|
davidben
2017/06/01 23:41:25
I think |cert| should probably be created from byt
mattm
2017/06/02 04:04:20
I was planning to leave this as is in this CL sinc
Ryan Sleevi
2017/06/08 18:13:47
|cert_context2| is not - line 150 handles that.
T
|
| scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( |
| cert_context2, intermediates); |
| - if (cert) |
| - selected_certs->push_back(std::move(cert)); |
| - CertFreeCertificateContext(cert_context2); |
| + if (cert) { |
| + selected_identities->push_back(base::MakeUnique<ClientCertIdentityWin>( |
| + std::move(cert), |
| + cert_context2)); // Takes ownership of |cert_context2| |
| + } |
| for (size_t i = 0; i < intermediates.size(); ++i) |
| CertFreeCertificateContext(intermediates[i]); |
| } |
| - std::sort(selected_certs->begin(), selected_certs->end(), |
| - x509_util::ClientCertSorter()); |
| + std::sort(selected_identities->begin(), selected_identities->end(), |
| + ClientCertIdentitySorter()); |
| } |
| } // namespace |
| @@ -174,13 +215,13 @@ ClientCertStoreWin::~ClientCertStoreWin() {} |
| void ClientCertStoreWin::GetClientCerts( |
| const SSLCertRequestInfo& request, |
| const ClientCertListCallback& callback) { |
|
davidben
2017/06/01 23:41:25
This is probably a Ryan question, but in the same
davidben
2017/06/01 23:46:14
Likewise, should we try to keep thread affinity th
mattm
2017/06/02 04:04:20
Sounds reasonable but I'll wait and see if Ryan ch
davidben
2017/06/07 23:06:16
Fair enough. I guess the main reason we might want
Ryan Sleevi
2017/06/08 18:13:47
Right, so the risk I tried to capture in previous
davidben
2017/06/08 21:40:48
This CL currently moves FetchClientCertPrivateKey
mattm
2017/06/08 21:47:55
So for context:
Before this CL, net::FetchClientC
mattm
2017/06/12 21:28:30
FYI, I have a followup CL (after this CL and after
|
| - CertificateList selected_certs; |
| + ClientCertIdentityList selected_identities; |
| if (cert_store_) { |
| // Use the existing client cert store. Note: Under some situations, |
| // it's possible for this to return certificates that aren't usable |
| // (see below). |
| - GetClientCertsImpl(cert_store_, request, &selected_certs); |
| - callback.Run(std::move(selected_certs)); |
| + GetClientCertsImpl(cert_store_, request, &selected_identities); |
| + callback.Run(std::move(selected_identities)); |
| return; |
| } |
| @@ -191,18 +232,18 @@ void ClientCertStoreWin::GetClientCerts( |
| ScopedHCERTSTORE my_cert_store(CertOpenSystemStore(NULL, L"MY")); |
| if (!my_cert_store) { |
| PLOG(ERROR) << "Could not open the \"MY\" system certificate store: "; |
| - callback.Run(CertificateList()); |
| + callback.Run(ClientCertIdentityList()); |
| return; |
| } |
| - GetClientCertsImpl(my_cert_store, request, &selected_certs); |
| - callback.Run(std::move(selected_certs)); |
| + GetClientCertsImpl(my_cert_store, request, &selected_identities); |
| + callback.Run(std::move(selected_identities)); |
| } |
| bool ClientCertStoreWin::SelectClientCertsForTesting( |
| const CertificateList& input_certs, |
| const SSLCertRequestInfo& request, |
| - CertificateList* selected_certs) { |
| + ClientCertIdentityList* selected_identities) { |
| ScopedHCERTSTORE test_store(CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, |
| NULL)); |
| if (!test_store) |
| @@ -232,7 +273,7 @@ bool ClientCertStoreWin::SelectClientCertsForTesting( |
| return false; |
| } |
| - GetClientCertsImpl(test_store.get(), request, selected_certs); |
| + GetClientCertsImpl(test_store.get(), request, selected_identities); |
| return true; |
| } |