electron/atom/browser/ui/certificate_trust_win.cc

137 lines
3.7 KiB
C++
Raw Normal View History

2017-04-06 01:01:58 +00:00
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/ui/certificate_trust.h"
#include <wincrypt.h>
2017-04-21 02:23:50 +00:00
#include <windows.h>
2017-04-06 01:01:58 +00:00
2017-04-21 02:47:11 +00:00
#include "base/callback.h"
#include "net/cert/cert_database.h"
2017-04-21 02:47:11 +00:00
2017-04-06 01:01:58 +00:00
namespace certificate_trust {
2017-04-27 05:01:55 +00:00
BOOL AddCertificate(const HCERTSTORE certStore,
const PCCERT_CONTEXT certContext,
const scoped_refptr<net::X509Certificate>& cert) {
auto result = CertAddCertificateContextToStore(
certStore,
certContext,
CERT_STORE_ADD_REPLACE_EXISTING,
NULL);
if (result) {
// force Chromium to reload it's database for this certificate
auto cert_db = net::CertDatabase::GetInstance();
cert_db->NotifyObserversCertDBChanged(cert.get());
}
return result;
}
2017-04-27 05:01:55 +00:00
// Add the provided certificate to the Trusted Root Certificate Authorities
// store for the current user.
//
2017-04-27 05:01:55 +00:00
// This requires prompting the user to confirm they trust the certificate.
BOOL AddToTrustedRootStore(const PCCERT_CONTEXT certContext,
const scoped_refptr<net::X509Certificate>& cert) {
2017-04-27 05:01:55 +00:00
auto rootCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"Root");
2017-04-24 01:49:55 +00:00
2017-04-27 05:01:55 +00:00
if (rootCertStore == NULL) {
return false;
}
2017-04-24 01:49:55 +00:00
2017-04-27 05:01:55 +00:00
auto result = AddCertificate(rootCertStore, certContext, cert);
2017-04-27 05:01:55 +00:00
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) {
2017-04-27 05:01:55 +00:00
auto userCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"My");
2017-04-27 05:01:55 +00:00
if (userCertStore == NULL) {
return false;
}
2017-04-27 05:01:55 +00:00
auto result = AddCertificate(userCertStore, certContext, cert);
2017-04-27 05:01:55 +00:00
CertCloseStore(userCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
return result;
}
CERT_CHAIN_PARA GetCertificateChainParameters() {
2017-04-27 05:01:55 +00:00
CERT_ENHKEY_USAGE enhkeyUsage;
enhkeyUsage.cUsageIdentifier = 0;
enhkeyUsage.rgpszUsageIdentifier = NULL;
2017-04-27 05:01:55 +00:00
CERT_USAGE_MATCH CertUsage;
// ensure the rules are applied to the entire chain
CertUsage.dwType = USAGE_MATCH_TYPE_AND;
CertUsage.Usage = enhkeyUsage;
2017-04-27 05:01:55 +00:00
CERT_CHAIN_PARA params = { sizeof(CERT_CHAIN_PARA) };
params.RequestedUsage = CertUsage;
2017-04-27 05:01:55 +00:00
return params;
}
void ShowCertificateTrust(atom::NativeWindow* parent_window,
const scoped_refptr<net::X509Certificate>& cert,
const std::string& message,
const ShowTrustCallback& callback) {
2017-04-27 05:01:55 +00:00
PCCERT_CHAIN_CONTEXT chainContext;
auto pCertContext = cert->CreateOSCertChainForCert();
auto params = GetCertificateChainParameters();
if (CertGetCertificateChain(NULL,
pCertContext,
NULL,
NULL,
&params,
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;
}
2017-04-27 05:01:55 +00:00
CertFreeCertificateChain(chainContext);
}
CertFreeCertificateContext(pCertContext);
2017-04-27 05:01:55 +00:00
callback.Run();
2017-04-06 01:09:58 +00:00
}
2017-04-06 01:01:58 +00:00
} // namespace certificate_trust