diff --git a/atom/browser/ui/certificate_trust_win.cc b/atom/browser/ui/certificate_trust_win.cc index 49d74367a0..892441cec9 100644 --- a/atom/browser/ui/certificate_trust_win.cc +++ b/atom/browser/ui/certificate_trust_win.cc @@ -12,31 +12,13 @@ namespace certificate_trust { -void ShowCertificateTrust(atom::NativeWindow* parent_window, - const scoped_refptr& cert, - const std::string& message, - const ShowTrustCallback& callback) { - // opening the Trusted Root Certificate store for the current user - auto hCertStore = CertOpenStore( - CERT_STORE_PROV_SYSTEM, - 0, - NULL, - CERT_SYSTEM_STORE_CURRENT_USER, - // installing into Trusted Root Certificate Authorities, not Personal - L"Root"); - - if (hCertStore == NULL) { - callback.Run(); - return; - } - - auto pCertContext = cert->CreateOSCertChainForCert(); - - // This is a blocking call which displays a prompt to the user to confirm - // they trust this certificate +BOOL AddCertificateAndRefresh( + const HCERTSTORE certStore, + const PCCERT_CONTEXT certContext, + const scoped_refptr& cert) { auto result = CertAddCertificateContextToStore( - hCertStore, - pCertContext, + certStore, + certContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL); @@ -47,7 +29,110 @@ void ShowCertificateTrust(atom::NativeWindow* parent_window, cert_db->NotifyObserversCertDBChanged(cert.get()); } - CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG); + return result; +} + + +// Add the provided certificate to the Trusted Root +// Certificate Authorities store for the current user. +// +// This requires prompting the user to confirm they +// trust the certificate. +BOOL AddToTrustedRootStore(const PCCERT_CONTEXT certContext, + const scoped_refptr& cert) { + auto rootCertStore = CertOpenStore( + CERT_STORE_PROV_SYSTEM, + 0, + NULL, + CERT_SYSTEM_STORE_CURRENT_USER, + L"Root"); + + if (rootCertStore == NULL) { + // could not resolve the certificate store, giving up + return false; + } + + auto result = AddCertificateAndRefresh(rootCertStore, certContext, cert); + + CertCloseStore(rootCertStore, CERT_CLOSE_STORE_FORCE_FLAG); + + return result; +} + +// Add the provided certificate to the Personal +// certificate store for the current user. +BOOL AddToPersonalStore(const PCCERT_CONTEXT certContext, + const scoped_refptr& cert) { + auto userCertStore = CertOpenStore( + CERT_STORE_PROV_SYSTEM, + 0, + NULL, + CERT_SYSTEM_STORE_CURRENT_USER, + L"My"); + + if (userCertStore == NULL) { + // could not resolve the certificate store, giving up + return false; + } + + auto result = AddCertificateAndRefresh(userCertStore, certContext, cert); + + CertCloseStore(userCertStore, CERT_CLOSE_STORE_FORCE_FLAG); + + return result; +} + +CERT_CHAIN_PARA GetCertificateChainParameters() { + CERT_ENHKEY_USAGE enhkeyUsage; + enhkeyUsage.cUsageIdentifier = 0; + enhkeyUsage.rgpszUsageIdentifier = NULL; + + CERT_USAGE_MATCH CertUsage; + // ensure the rules are applied to the entire chain + CertUsage.dwType = USAGE_MATCH_TYPE_AND; + CertUsage.Usage = enhkeyUsage; + + CERT_CHAIN_PARA params = { sizeof(CERT_CHAIN_PARA) }; + params.RequestedUsage = CertUsage; + + return params; +} + +void ShowCertificateTrust(atom::NativeWindow* parent_window, + const scoped_refptr& cert, + const std::string& message, + const ShowTrustCallback& callback) { + PCCERT_CHAIN_CONTEXT chainContext; + + auto pCertContext = cert->CreateOSCertChainForCert(); + + auto params = GetCertificateChainParameters(); + + if (CertGetCertificateChain(NULL, + pCertContext, + NULL, + NULL, + ¶ms, + NULL, + NULL, + &chainContext)) { + switch (chainContext->TrustStatus.dwErrorStatus) { + case CERT_TRUST_NO_ERROR: + AddToPersonalStore(pCertContext, cert); + break; + + case CERT_TRUST_IS_UNTRUSTED_ROOT: + case CERT_TRUST_IS_SELF_SIGNED: + AddToTrustedRootStore(pCertContext, cert); + break; + + default: + // we can't handle other scenarios, giving up + break; + } + + CertFreeCertificateChain(chainContext); + } CertFreeCertificateContext(pCertContext);