Index: net/base/x509_certificate_win.cc |
diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc |
index 9e018fdde6564e76aee70b28754af7936de735b8..2ba6b02981cd20812265afcc281f77ddbf800ddb 100644 |
--- a/net/base/x509_certificate_win.cc |
+++ b/net/base/x509_certificate_win.cc |
@@ -4,6 +4,7 @@ |
#include "net/base/x509_certificate.h" |
+#include "base/crypto/scoped_capi_types.h" |
#include "base/logging.h" |
#include "base/pickle.h" |
#include "base/string_tokenizer.h" |
@@ -14,6 +15,7 @@ |
#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" |
#pragma comment(lib, "crypt32.lib") |
@@ -23,6 +25,11 @@ namespace net { |
namespace { |
+typedef base::ScopedCAPIHandle< |
+ HCERTSTORE, |
+ base::CAPIDestroyerWithFlags<HCERTSTORE, |
+ CertCloseStore, 0> > ScopedHCERTSTORE; |
+ |
//----------------------------------------------------------------------------- |
// TODO(wtc): This is a copy of the MapSecurityError function in |
@@ -428,6 +435,47 @@ X509Certificate::OSCertHandles ParsePKCS7(const char* data, size_t length) { |
return results; |
} |
+// Returns a new HCERTSTORE containing both |cert_store| and any temporarily |
+// trusted root certificates. If there are no temporarily trusted root |
+// certificates, returns NULL. |
+HCERTSTORE CreateStoreForTestsIfNeeded(HCERTSTORE cert_store) { |
+ TestRootCerts* temporary_roots = TestRootCerts::GetInstance(); |
+ if (temporary_roots->IsEmpty()) |
+ return NULL; |
+ if (!cert_store) { |
+ // If |cert_store| is empty, just return a copy of the temporary store, |
+ // as no merging is needed. |
+ return CertDuplicateStore(temporary_roots->temporary_roots()); |
+ } |
+ |
+ HCERTSTORE collection_store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, |
+ NULL, 0, NULL); |
+ if (!collection_store) { |
+ DPLOG(ERROR) << "Unable to create temporary linked certificate store"; |
+ return NULL; |
+ } |
+ |
+ // Add the temporary roots with priority 0, so that certificates from the |
+ // temporary roots will be of a higher priority for chain building. If |
+ // set to a lower priority, it is possible that the chain building |
+ // algorithm will prefer a root from |cert_store|, which may be a |
+ // compatible-but-different certificate than the one in |
+ // |temporary_roots|. If this happens, FixupChainContext() may fail to |
+ // override the trust failure. |
+ BOOL ok = CertAddStoreToCollection(collection_store, |
+ temporary_roots->temporary_roots(), |
+ 0, 0); |
+ if (ok) |
+ ok = CertAddStoreToCollection(collection_store, cert_store, 0, 1); |
+ if (!ok) { |
+ DPLOG(ERROR) << "Unable to create temporary linked certificate store"; |
+ CertCloseStore(collection_store, 0); |
+ return NULL; |
+ } |
+ |
+ return collection_store; |
+} |
+ |
} // namespace |
void X509Certificate::Initialize() { |
@@ -605,15 +653,22 @@ int X509Certificate::Verify(const std::string& hostname, |
} |
} |
+ ScopedHCERTSTORE scoped_test_store( |
+ CreateStoreForTestsIfNeeded(cert_handle_->hCertStore)); |
+ HCERTSTORE intermediates_store = scoped_test_store ? |
+ scoped_test_store : cert_handle_->hCertStore; |
+ |
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. |
+ // TODO(rsleevi): Add support for Windows 7's hExclusiveRoot to work around |
+ // the issues described in TestRootCerts. |
if (!CertGetCertificateChain( |
NULL, // default chain engine, HCCE_CURRENT_USER |
cert_handle_, |
NULL, // current system time |
- cert_handle_->hCertStore, // search this store |
+ intermediates_store, |
&chain_para, |
chain_flags, |
NULL, // reserved |
@@ -630,7 +685,7 @@ int X509Certificate::Verify(const std::string& hostname, |
NULL, // default chain engine, HCCE_CURRENT_USER |
cert_handle_, |
NULL, // current system time |
- cert_handle_->hCertStore, // search this store |
+ intermediates_store, |
&chain_para, |
chain_flags, |
NULL, // reserved |
@@ -640,8 +695,11 @@ int X509Certificate::Verify(const std::string& hostname, |
} |
ScopedCertChainContext scoped_chain_context(chain_context); |
- GetCertChainInfo(chain_context, verify_result); |
+ TestRootCerts* root_certs = TestRootCerts::GetInstance(); |
bulach
2010/11/18 12:42:12
nit: test_root_certs, and similar comment to the m
|
+ root_certs->FixupChainContext( |
+ const_cast<PCERT_CHAIN_CONTEXT>(chain_context)); |
+ GetCertChainInfo(chain_context, verify_result); |
verify_result->cert_status |= MapCertChainErrorStatusToCertStatus( |
chain_context->TrustStatus.dwErrorStatus); |