Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Unified Diff: net/base/x509_certificate_win.cc

Issue 7324039: Ensure X509Certificate::OSCertHandles are safe to be used on both UI and IO threads on Win (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review feedback Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);

Powered by Google App Engine
This is Rietveld 408576698