2017-04-29 09:29:07 +00:00
|
|
|
// Copyright (c) 2017 GitHub, Inc.
|
2017-04-06 01:01:58 +00:00
|
|
|
// Use of this source code is governed by the MIT license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
2019-06-19 20:46:59 +00:00
|
|
|
#include "shell/browser/ui/certificate_trust.h"
|
2017-04-06 01:01:58 +00:00
|
|
|
|
2018-04-19 12:27:57 +00:00
|
|
|
#include <windows.h> // windows.h must be included first
|
|
|
|
|
2017-04-20 11:12:32 +00:00
|
|
|
#include <wincrypt.h>
|
2017-04-06 01:01:58 +00:00
|
|
|
|
2017-04-24 01:10:41 +00:00
|
|
|
#include "net/cert/cert_database.h"
|
2017-09-21 13:24:57 +00:00
|
|
|
#include "net/cert/x509_util_win.h"
|
2020-06-22 16:35:24 +00:00
|
|
|
#include "shell/browser/javascript_environment.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
|
|
|
// Add the provided certificate to the Trusted Root Certificate Authorities
|
|
|
|
// store for the current user.
|
2017-04-27 04:44:58 +00:00
|
|
|
//
|
2017-04-27 05:01:55 +00:00
|
|
|
// This requires prompting the user to confirm they trust the certificate.
|
2017-04-29 09:28:42 +00:00
|
|
|
BOOL AddToTrustedRootStore(const PCCERT_CONTEXT cert_context,
|
2017-04-27 04:44:58 +00:00
|
|
|
const scoped_refptr<net::X509Certificate>& cert) {
|
2018-06-25 20:30:00 +00:00
|
|
|
auto* root_cert_store = CertOpenStore(
|
|
|
|
CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"Root");
|
2017-04-24 01:49:55 +00:00
|
|
|
|
2017-04-29 09:28:42 +00:00
|
|
|
if (root_cert_store == NULL) {
|
2017-04-27 05:01:55 +00:00
|
|
|
return false;
|
|
|
|
}
|
2017-04-24 01:49:55 +00:00
|
|
|
|
2017-04-27 05:06:23 +00:00
|
|
|
auto result = CertAddCertificateContextToStore(
|
2018-04-18 01:55:30 +00:00
|
|
|
root_cert_store, cert_context, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
|
2017-04-24 01:10:41 +00:00
|
|
|
|
2017-04-27 05:06:23 +00:00
|
|
|
if (result) {
|
|
|
|
// force Chromium to reload it's database for this certificate
|
2018-06-25 20:30:00 +00:00
|
|
|
auto* cert_db = net::CertDatabase::GetInstance();
|
2023-06-15 20:37:01 +00:00
|
|
|
cert_db->NotifyObserversTrustStoreChanged();
|
2017-04-27 05:01:55 +00:00
|
|
|
}
|
2017-04-27 04:44:58 +00:00
|
|
|
|
2017-04-29 09:28:42 +00:00
|
|
|
CertCloseStore(root_cert_store, CERT_CLOSE_STORE_FORCE_FLAG);
|
2017-04-27 05:01:55 +00:00
|
|
|
|
|
|
|
return result;
|
2017-04-27 04:44:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CERT_CHAIN_PARA GetCertificateChainParameters() {
|
2017-04-29 09:28:42 +00:00
|
|
|
CERT_ENHKEY_USAGE enhkey_usage;
|
|
|
|
enhkey_usage.cUsageIdentifier = 0;
|
|
|
|
enhkey_usage.rgpszUsageIdentifier = NULL;
|
2017-04-27 04:44:58 +00:00
|
|
|
|
2017-04-29 09:28:42 +00:00
|
|
|
CERT_USAGE_MATCH cert_usage;
|
2017-04-27 05:01:55 +00:00
|
|
|
// ensure the rules are applied to the entire chain
|
2017-04-29 09:28:42 +00:00
|
|
|
cert_usage.dwType = USAGE_MATCH_TYPE_AND;
|
|
|
|
cert_usage.Usage = enhkey_usage;
|
2017-04-27 04:44:58 +00:00
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
CERT_CHAIN_PARA params = {sizeof(CERT_CHAIN_PARA)};
|
2017-04-29 09:28:42 +00:00
|
|
|
params.RequestedUsage = cert_usage;
|
2017-04-27 04:44:58 +00:00
|
|
|
|
2017-04-27 05:01:55 +00:00
|
|
|
return params;
|
2017-04-27 04:44:58 +00:00
|
|
|
}
|
|
|
|
|
2019-03-15 00:02:50 +00:00
|
|
|
v8::Local<v8::Promise> ShowCertificateTrust(
|
|
|
|
electron::NativeWindow* parent_window,
|
|
|
|
const scoped_refptr<net::X509Certificate>& cert,
|
|
|
|
const std::string& message) {
|
2020-06-22 16:35:24 +00:00
|
|
|
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
|
2019-11-01 06:10:32 +00:00
|
|
|
gin_helper::Promise<void> promise(isolate);
|
2019-03-15 00:02:50 +00:00
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
2017-04-27 05:01:55 +00:00
|
|
|
|
2019-03-15 00:02:50 +00:00
|
|
|
PCCERT_CHAIN_CONTEXT chain_context;
|
2017-09-21 13:24:57 +00:00
|
|
|
auto cert_context = net::x509_util::CreateCertContextWithChain(cert.get());
|
2017-04-27 05:01:55 +00:00
|
|
|
auto params = GetCertificateChainParameters();
|
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
if (CertGetCertificateChain(NULL, cert_context.get(), NULL, NULL, ¶ms,
|
|
|
|
NULL, NULL, &chain_context)) {
|
2017-04-29 09:28:42 +00:00
|
|
|
auto error_status = chain_context->TrustStatus.dwErrorStatus;
|
2017-05-03 23:22:56 +00:00
|
|
|
if (error_status == CERT_TRUST_IS_SELF_SIGNED ||
|
|
|
|
error_status == CERT_TRUST_IS_UNTRUSTED_ROOT) {
|
|
|
|
// these are the only scenarios we're interested in supporting
|
2017-09-21 13:24:57 +00:00
|
|
|
AddToTrustedRootStore(cert_context.get(), cert);
|
2017-04-27 04:44:58 +00:00
|
|
|
}
|
2017-04-20 11:12:32 +00:00
|
|
|
|
2017-04-29 09:28:42 +00:00
|
|
|
CertFreeCertificateChain(chain_context);
|
2017-04-27 05:01:55 +00:00
|
|
|
}
|
|
|
|
|
2019-03-15 00:02:50 +00:00
|
|
|
promise.Resolve();
|
|
|
|
return handle;
|
2017-04-06 01:09:58 +00:00
|
|
|
}
|
2017-04-06 01:01:58 +00:00
|
|
|
|
|
|
|
} // namespace certificate_trust
|