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