Fix QNetworkAccessManager hang with low integrity level sandboxing

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 <forderud@gmail.com>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
(cherry picked from commit 4d11ba66de81310ca79491035123392b923a39e2)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Jøger Hansegård 2023-10-17 19:09:49 +02:00 committed by Qt Cherry-pick Bot
parent e8f931f2dc
commit a75ad8ddc5
2 changed files with 12 additions and 3 deletions

View File

@ -363,7 +363,9 @@ QList<QSslCertificate> systemCaCertificates()
QList<QSslCertificate> 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) {

View File

@ -292,7 +292,11 @@ QList<QSslCertificate> QSchannelBackend::systemCaCertificatesImplementation()
// Similar to non-Darwin version found in qtlsbackend_openssl.cpp,
// QTlsPrivate::systemCaCertificates function.
QList<QSslCertificate> 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!");