actually validate the chain before adding
This commit is contained in:
parent
f644ba56a3
commit
80212c0ab4
1 changed files with 110 additions and 25 deletions
|
@ -12,31 +12,13 @@
|
|||
|
||||
namespace certificate_trust {
|
||||
|
||||
void ShowCertificateTrust(atom::NativeWindow* parent_window,
|
||||
const scoped_refptr<net::X509Certificate>& 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<net::X509Certificate>& 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<net::X509Certificate>& 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<net::X509Certificate>& 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<net::X509Certificate>& 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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue