From a75ad8ddc5ad224e99f6b648a2341992a94134e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8ger=20Hanseg=C3=A5rd?= Date: Tue, 17 Oct 2023 19:09:49 +0200 Subject: [PATCH] Fix QNetworkAccessManager hang with low integrity level sandboxing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QNetworkAccessManager may fail to finish with Windows apps that are running with low integrity level sandboxing. The root cause is that such applications are not allowed to open ROOT system certificate store with write privileges. This causes the CertOpenSystemStore helper function to fail, because it attempts to open certificate stores with the option of adding or deleting certificates. We only use the CertOpenSystemStore with the intent of fetching certificates from the certificate store, so we do not need write access. The fix for this issue is threfor to open the system certificate store as read-only by using the lower-level CertOpenStore function. The CERT_SYSTEM_STORE_CURRENT_USER flag is provided to CertOpenStore to keep the documented behavior of CertOpenSystemStore, which states "Only current user certificates are accessible using this method, not the local machine store." Fixes: QTBUG-118192 Pick-to: 6.5 Change-Id: I529b760398f84137a0e95c8088a71b293d302b54 Reviewed-by: Fredrik Orderud Reviewed-by: MÃ¥rten Nordheim Reviewed-by: Qt CI Bot (cherry picked from commit 4d11ba66de81310ca79491035123392b923a39e2) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/tls/openssl/qtlsbackend_openssl.cpp | 4 +++- src/plugins/tls/schannel/qtls_schannel.cpp | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/plugins/tls/openssl/qtlsbackend_openssl.cpp b/src/plugins/tls/openssl/qtlsbackend_openssl.cpp index 5ce5f45a5b0..02f27ce9317 100644 --- a/src/plugins/tls/openssl/qtlsbackend_openssl.cpp +++ b/src/plugins/tls/openssl/qtlsbackend_openssl.cpp @@ -363,7 +363,9 @@ QList systemCaCertificates() QList systemCerts; #if defined(Q_OS_WIN) HCERTSTORE hSystemStore; - hSystemStore = CertOpenSystemStoreW(0, L"ROOT"); + hSystemStore = + CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, + CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, L"ROOT"); if (hSystemStore) { PCCERT_CONTEXT pc = nullptr; while (1) { diff --git a/src/plugins/tls/schannel/qtls_schannel.cpp b/src/plugins/tls/schannel/qtls_schannel.cpp index ae9ff06eae9..422bb041c68 100644 --- a/src/plugins/tls/schannel/qtls_schannel.cpp +++ b/src/plugins/tls/schannel/qtls_schannel.cpp @@ -292,7 +292,11 @@ QList QSchannelBackend::systemCaCertificatesImplementation() // Similar to non-Darwin version found in qtlsbackend_openssl.cpp, // QTlsPrivate::systemCaCertificates function. QList systemCerts; - auto hSystemStore = QHCertStorePointer(CertOpenSystemStore(0, L"ROOT")); + + auto hSystemStore = QHCertStorePointer( + CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, + CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, L"ROOT")); + if (hSystemStore) { PCCERT_CONTEXT pc = nullptr; while ((pc = CertFindCertificateInStore(hSystemStore.get(), X509_ASN_ENCODING, 0, @@ -1952,7 +1956,10 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext) // the Ca list, not just included during verification. // That being said, it's not trivial to add the root certificates (if and only if they // came from the system root store). And I don't see this mentioned in our documentation. - auto rootStore = QHCertStorePointer(CertOpenSystemStore(0, L"ROOT")); + auto rootStore = QHCertStorePointer( + CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, + CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, L"ROOT")); + if (!rootStore) { #ifdef QSSLSOCKET_DEBUG qCWarning(lcTlsBackendSchannel, "Failed to open the system root CA certificate store!");