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