From 8564fd0dae237a3b93269c2076d4a92d1e40cba5 Mon Sep 17 00:00:00 2001 From: Alexander Aprelev Date: Thu, 6 May 2021 00:43:32 +0000 Subject: [PATCH] [io/ssl/win] Look for certificates in local machine store as well current user store. Add certificates from "ca", "trust" and "my" stores in addition to "root". Improve certificate tracing: print certificates as they are added. Clean up error logging. Fixes https://github.com/dart-lang/sdk/issues/45909 TEST=remove certs from current user store, see requests fail to connect, add cert to local machine store, confirm connection works. Change-Id: Ied234098d56b406c9868602a2b806786ae3740be Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/198241 Commit-Queue: Alexander Aprelev Reviewed-by: Zach Anderson --- runtime/bin/secure_socket_utils.cc | 4 +- runtime/bin/security_context_win.cc | 99 +++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 16 deletions(-) diff --git a/runtime/bin/secure_socket_utils.cc b/runtime/bin/secure_socket_utils.cc index e3cdbf434a00..ce38f8fc5b57 100644 --- a/runtime/bin/secure_socket_utils.cc +++ b/runtime/bin/secure_socket_utils.cc @@ -75,10 +75,10 @@ void SecureSocketUtils::CheckStatusSSL(int status, } if (SSL_LOG_STATUS) { int error = ERR_get_error(); - Syslog::PrintErr("Failed: %s status %d", message, status); + Syslog::PrintErr("Failed: %s status: %d ", message, status); char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE]; ERR_error_string_n(error, error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE); - Syslog::PrintErr("ERROR: %d %s\n", error, error_string); + Syslog::PrintErr("%s\n", error_string); } SecureSocketUtils::ThrowIOException(status, type, message, ssl); } diff --git a/runtime/bin/security_context_win.cc b/runtime/bin/security_context_win.cc index effdc5ea3251..950f4be4238d 100644 --- a/runtime/bin/security_context_win.cc +++ b/runtime/bin/security_context_win.cc @@ -39,24 +39,35 @@ static void PrintSSLErr(const char* str) { char error_string[SecureSocketUtils::SSL_ERROR_MESSAGE_BUFFER_SIZE]; ERR_error_string_n(error, error_string, SecureSocketUtils::SSL_ERROR_MESSAGE_BUFFER_SIZE); - Syslog::PrintErr("%s ERROR: %d %s\n", str, error, error_string); + Syslog::PrintErr("%s %s\n", str, error_string); } -// Add certificates from Windows trusted root store. -static bool AddCertificatesFromRootStore(X509_STORE* store) { -// The UWP platform doesn't support CertEnumCertificatesInStore hence -// this function cannot work when compiled in UWP mode. -#ifdef TARGET_OS_WINDOWS_UWP - return false; -#else - // Open root system store. - // Note that only current user certificates are accessible using this method, - // not the local machine store. - HCERTSTORE cert_store = CertOpenSystemStore(NULL, L"ROOT"); +#ifndef TARGET_OS_WINDOWS_UWP +static bool AddCertificatesFromNamedSystemStore(const wchar_t* name, + DWORD store_type, + X509_STORE* store) { + ASSERT(store_type == CERT_SYSTEM_STORE_CURRENT_USER || + store_type == CERT_SYSTEM_STORE_LOCAL_MACHINE); + + if (SSL_LOG_STATUS) { + Syslog::Print("AddCertificatesFromNamedSystemStore %ls type: %s\n", name, + store_type == CERT_SYSTEM_STORE_CURRENT_USER + ? "Current User" + : "Local Machine"); + } + + HCERTSTORE cert_store = + CertOpenStore(CERT_STORE_PROV_SYSTEM, + 0, // the encoding type is not needed + NULL, // use the default HCRYPTPROV + store_type | CERT_STORE_READONLY_FLAG, name); + if (cert_store == NULL) { if (SSL_LOG_STATUS) { DWORD error = GetLastError(); - Syslog::PrintErr("Failed to open Windows root store due to %d\n", error); + Syslog::PrintErr( + "Failed to open Windows root store %ls type %d due to %d\n", name, + store_type, error); } return false; } @@ -84,10 +95,34 @@ static bool AddCertificatesFromRootStore(X509_STORE* store) { continue; } BIO_free(root_cert_bio); + + if (SSL_LOG_STATUS) { + auto s_name = X509_get_subject_name(root_cert); + auto s_issuer_name = X509_get_issuer_name(root_cert); + auto serial_number = X509_get_serialNumber(root_cert); + BIGNUM* bn = ASN1_INTEGER_to_BN(serial_number, nullptr); + char* hex = BN_bn2hex(bn); + Syslog::Print("Considering root certificate serial: %s subject name: ", + hex); + OPENSSL_free(hex); + X509_NAME_print_ex_fp(stdout, s_name, 4, 0); + Syslog::Print(" issuer:"); + X509_NAME_print_ex_fp(stdout, s_issuer_name, 4, 0); + Syslog::Print("\n"); + } + int status = X509_STORE_add_cert(store, root_cert); if (status == 0) { + int error = ERR_get_error(); + if (ERR_GET_REASON(error) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { + if (SSL_LOG_STATUS) { + Syslog::Print("...duplicate\n"); + } + X509_free(root_cert); + continue; + } if (SSL_LOG_STATUS) { - PrintSSLErr("Fail to add certificate to trust store"); + PrintSSLErr("Failed to add certificate to x509 trust store"); } X509_free(root_cert); CertFreeCertificateContext(cert_context); @@ -104,6 +139,42 @@ static bool AddCertificatesFromRootStore(X509_STORE* store) { } return false; } + return true; +} + +static bool AddCertificatesFromSystemStore(DWORD store_type, + X509_STORE* store) { + if (!AddCertificatesFromNamedSystemStore(L"ROOT", store_type, store)) { + return false; + } + if (!AddCertificatesFromNamedSystemStore(L"CA", store_type, store)) { + return false; + } + if (!AddCertificatesFromNamedSystemStore(L"TRUST", store_type, store)) { + return false; + } + if (!AddCertificatesFromNamedSystemStore(L"MY", store_type, store)) { + return false; + } + return true; +} +#endif // ifdef TARGET_OS_WINDOWS_UWP + +// Add certificates from Windows trusted root store. +static bool AddCertificatesFromRootStore(X509_STORE* store) { +// The UWP platform doesn't support CertEnumCertificatesInStore hence +// this function cannot work when compiled in UWP mode. +#ifdef TARGET_OS_WINDOWS_UWP + return false; +#else + if (!AddCertificatesFromSystemStore(CERT_SYSTEM_STORE_CURRENT_USER, store)) { + return false; + } + + if (!AddCertificatesFromSystemStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, store)) { + return false; + } + return true; #endif // ifdef TARGET_OS_WINDOWS_UWP }