certificate_trust_win.cc 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Copyright (c) 2017 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "atom/browser/ui/certificate_trust.h"
  5. #include <wincrypt.h>
  6. #include <windows.h>
  7. #include "base/callback.h"
  8. #include "net/cert/cert_database.h"
  9. #include "net/cert/x509_util_win.h"
  10. namespace certificate_trust {
  11. // Add the provided certificate to the Trusted Root Certificate Authorities
  12. // store for the current user.
  13. //
  14. // This requires prompting the user to confirm they trust the certificate.
  15. BOOL AddToTrustedRootStore(const PCCERT_CONTEXT cert_context,
  16. const scoped_refptr<net::X509Certificate>& cert) {
  17. auto root_cert_store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL,
  18. CERT_SYSTEM_STORE_CURRENT_USER, L"Root");
  19. if (root_cert_store == NULL) {
  20. return false;
  21. }
  22. auto result = CertAddCertificateContextToStore(
  23. root_cert_store, cert_context, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
  24. if (result) {
  25. // force Chromium to reload it's database for this certificate
  26. auto cert_db = net::CertDatabase::GetInstance();
  27. cert_db->NotifyObserversCertDBChanged();
  28. }
  29. CertCloseStore(root_cert_store, CERT_CLOSE_STORE_FORCE_FLAG);
  30. return result;
  31. }
  32. CERT_CHAIN_PARA GetCertificateChainParameters() {
  33. CERT_ENHKEY_USAGE enhkey_usage;
  34. enhkey_usage.cUsageIdentifier = 0;
  35. enhkey_usage.rgpszUsageIdentifier = NULL;
  36. CERT_USAGE_MATCH cert_usage;
  37. // ensure the rules are applied to the entire chain
  38. cert_usage.dwType = USAGE_MATCH_TYPE_AND;
  39. cert_usage.Usage = enhkey_usage;
  40. CERT_CHAIN_PARA params = {sizeof(CERT_CHAIN_PARA)};
  41. params.RequestedUsage = cert_usage;
  42. return params;
  43. }
  44. void ShowCertificateTrust(atom::NativeWindow* parent_window,
  45. const scoped_refptr<net::X509Certificate>& cert,
  46. const std::string& message,
  47. const ShowTrustCallback& callback) {
  48. PCCERT_CHAIN_CONTEXT chain_context;
  49. auto cert_context = net::x509_util::CreateCertContextWithChain(cert.get());
  50. auto params = GetCertificateChainParameters();
  51. if (CertGetCertificateChain(NULL, cert_context.get(), NULL, NULL, &params,
  52. NULL, NULL, &chain_context)) {
  53. auto error_status = chain_context->TrustStatus.dwErrorStatus;
  54. if (error_status == CERT_TRUST_IS_SELF_SIGNED ||
  55. error_status == CERT_TRUST_IS_UNTRUSTED_ROOT) {
  56. // these are the only scenarios we're interested in supporting
  57. AddToTrustedRootStore(cert_context.get(), cert);
  58. }
  59. CertFreeCertificateChain(chain_context);
  60. }
  61. callback.Run();
  62. }
  63. } // namespace certificate_trust