Chromium Code Reviews| Index: net/base/x509_certificate_win.cc |
| diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc |
| index 1336f8c62ad2681f69e008e0f3b3984a9203034e..0ab4c334284d6e863d3be88f16dc6ede8aca1cc5 100644 |
| --- a/net/base/x509_certificate_win.cc |
| +++ b/net/base/x509_certificate_win.cc |
| @@ -18,7 +18,6 @@ |
| #include "net/base/cert_verify_result.h" |
| #include "net/base/ev_root_ca_metadata.h" |
| #include "net/base/net_errors.h" |
| -#include "net/base/scoped_cert_chain_context.h" |
| #include "net/base/test_root_certs.h" |
| #include "net/base/x509_certificate_known_roots_win.h" |
| @@ -30,11 +29,6 @@ namespace net { |
| namespace { |
| -typedef crypto::ScopedCAPIHandle< |
| - HCERTSTORE, |
| - crypto::CAPIDestroyerWithFlags<HCERTSTORE, |
| - CertCloseStore, 0> > ScopedHCERTSTORE; |
| - |
| struct FreeChainEngineFunctor { |
| void operator()(HCERTCHAINENGINE engine) const { |
| if (engine) |
| @@ -42,9 +36,35 @@ struct FreeChainEngineFunctor { |
| } |
| }; |
| +struct FreeCertContextFunctor { |
| + void operator()(PCCERT_CONTEXT context) const { |
| + if (context) |
| + CertFreeCertificateContext(context); |
| + } |
| +}; |
| + |
| +struct FreeCertChainContextFunctor { |
| + void operator()(PCCERT_CHAIN_CONTEXT chain_context) const { |
| + if (context) |
| + CertFreeCertificateChain(context); |
| + } |
| +}; |
| + |
| +typedef crypto::ScopedCAPIHandle< |
| + HCERTSTORE, |
| + crypto::CAPIDestroyerWithFlags<HCERTSTORE, |
| + CertCloseStore, 0> > ScopedHCERTSTORE; |
| + |
| typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor> |
| ScopedHCERTCHAINENGINE; |
| +typedef scoped_ptr_malloc<const CERT_CONTEXT, |
| + FreeCertContextFunctor> ScopedCertContext; |
| + |
| +typedef scoped_ptr_malloc<const CERT_CHAIN_CONTEXT, |
| + FreeCertChainContextFunctor> ScopedCertChainContext; |
| + |
|
wtc
2011/10/04 18:00:52
Nit: delete one blank line.
|
| + |
| //----------------------------------------------------------------------------- |
| // TODO(wtc): This is a copy of the MapSecurityError function in |
| @@ -704,6 +724,46 @@ HCERTSTORE X509Certificate::cert_store() { |
| return g_cert_store.Get().cert_store(); |
| } |
| +X509Certificate::OSCertListHandle |
| +X509Certificate::CreateOSCertListHandle() const { |
| + // Create an in-memory certificate store to hold |cert_handle_| and any |
| + // associated intermediate certificates. The store will be referenced in the |
| + // returned OSCertListHandle, and will not be freed until the |
| + // OSCertListHandle is freed. |
| + OSCertListHandle cert_list = NULL; |
| + DWORD flags = CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG; |
| + HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, |
| + NULL, flags, NULL); |
| + |
| + if (store) { |
| + // NOTE: This preserves all of the properties of |cert_handle_| except for |
| + // CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two |
| + // properties that hold access to already-opened private keys. If a handle |
| + // has already been unlocked (eg: PIN prompt), then the first time that |
| + // the identity is used for client auth, it may prompt the user again. |
| + BOOL ok = CertAddCertificateContextToStore(store, cert_handle_, |
| + CERT_STORE_ADD_ALWAYS, |
| + &cert_list); |
| + if (ok && cert_list) { |
| + for (size_t i = 0; ok && i < intermediate_ca_certs_.size(); ++i) { |
| + ok = CertAddCertificateContextToStore(store, intermediate_ca_certs_[i], |
| + CERT_STORE_ADD_ALWAYS, NULL); |
| + } |
| + } |
| + |
| + // If |cert_list| points to a valid certificate, this will not actually |
| + // close and free |store| until |cert_list| is freed. |
| + CertCloseStore(store, 0); |
| + |
| + if (!ok) { |
| + FreeOSCertListHandle(cert_list); |
| + return NULL; |
| + } |
| + } |
| + |
| + return cert_list; |
| +} |
| + |
| int X509Certificate::VerifyInternal(const std::string& hostname, |
| int flags, |
| CertVerifyResult* verify_result) const { |
| @@ -770,21 +830,23 @@ int X509Certificate::VerifyInternal(const std::string& hostname, |
| if (TestRootCerts::HasInstance()) |
| chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); |
| + ScopedPCCERT_CONTEXT cert_list(CreateOSCertListHandle()); |
|
wtc
2011/10/04 18:00:52
I don't see where the ScopedPCCERT_CONTEXT type is
|
| PCCERT_CHAIN_CONTEXT chain_context; |
| // IE passes a non-NULL pTime argument that specifies the current system |
| // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the |
| // chain_flags argument. |
| if (!CertGetCertificateChain( |
| chain_engine, |
| - cert_handle_, |
| + cert_list, |
| NULL, // current system time |
| - cert_handle_->hCertStore, |
| + cert_list->hCertStore, |
| &chain_para, |
| chain_flags, |
| NULL, // reserved |
| &chain_context)) { |
| return MapSecurityError(GetLastError()); |
| } |
| + |
| if (chain_context->TrustStatus.dwErrorStatus & |
| CERT_TRUST_IS_NOT_VALID_FOR_USAGE) { |
| ev_policy_oid = NULL; |
| @@ -793,9 +855,9 @@ int X509Certificate::VerifyInternal(const std::string& hostname, |
| CertFreeCertificateChain(chain_context); |
| if (!CertGetCertificateChain( |
| chain_engine, |
| - cert_handle_, |
| + cert_list, |
| NULL, // current system time |
| - cert_handle_->hCertStore, |
| + cert_list->hCertStore, |
| &chain_para, |
| chain_flags, |
| NULL, // reserved |
| @@ -803,6 +865,7 @@ int X509Certificate::VerifyInternal(const std::string& hostname, |
| return MapSecurityError(GetLastError()); |
| } |
| } |
| + |
| ScopedCertChainContext scoped_chain_context(chain_context); |
| GetCertChainInfo(chain_context, verify_result); |
| @@ -1011,6 +1074,11 @@ void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
| } |
| // static |
| +void X509Certificate::FreeOSCertListHandle(OSCertListHandle cert_list) { |
| + CertFreeCertificateContext(cert_list); |
| +} |
| + |
| +// static |
| SHA1Fingerprint X509Certificate::CalculateFingerprint( |
| OSCertHandle cert) { |
| DCHECK(NULL != cert->pbCertEncoded); |