e7496ce04f
flaw in certificate validation (CVE-2023-34410) (version #2) Resolves: bz#2212754
55 lines
2.7 KiB
Diff
55 lines
2.7 KiB
Diff
--- a/src/network/ssl/qsslsocket_schannel.cpp
|
|
+++ b/src/network/ssl/qsslsocket_schannel.cpp
|
|
@@ -1880,6 +1880,28 @@ bool QSslSocketBackendPrivate::verifyCertContext(CERT_CONTEXT *certContext)
|
|
if (configuration.peerVerifyDepth > 0 && DWORD(configuration.peerVerifyDepth) < verifyDepth)
|
|
verifyDepth = DWORD(configuration.peerVerifyDepth);
|
|
|
|
+ const auto &caCertificates = q->sslConfiguration().caCertificates();
|
|
+
|
|
+ if (!rootCertOnDemandLoadingAllowed()
|
|
+ && !(chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_PARTIAL_CHAIN)
|
|
+ && (q->peerVerifyMode() == QSslSocket::VerifyPeer
|
|
+ || (isClient && q->peerVerifyMode() == QSslSocket::AutoVerifyPeer))) {
|
|
+ // When verifying a peer Windows "helpfully" builds a chain that
|
|
+ // may include roots from the system store. But we don't want that if
|
|
+ // the user has set their own CA certificates.
|
|
+ // Since Windows claims this is not a partial chain the root is included
|
|
+ // and we have to check that it is one of our configured CAs.
|
|
+ CERT_CHAIN_ELEMENT *element = chain->rgpElement[chain->cElement - 1];
|
|
+ QSslCertificate certificate = getCertificateFromChainElement(element);
|
|
+ if (!caCertificates.contains(certificate)) {
|
|
+ auto error = QSslError(QSslError::CertificateUntrusted, certificate);
|
|
+ sslErrors += error;
|
|
+ emit q->peerVerifyError(error);
|
|
+ if (q->state() != QAbstractSocket::ConnectedState)
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
for (DWORD i = 0; i < verifyDepth; i++) {
|
|
CERT_CHAIN_ELEMENT *element = chain->rgpElement[i];
|
|
QSslCertificate certificate = getCertificateFromChainElement(element);
|
|
|
|
|
|
--- a/src/network/ssl/qsslsocket.cpp
|
|
+++ b/src/network/ssl/qsslsocket.cpp
|
|
@@ -2221,6 +2221,10 @@ QSslSocketPrivate::QSslSocketPrivate()
|
|
, flushTriggered(false)
|
|
{
|
|
QSslConfigurationPrivate::deepCopyDefaultConfiguration(&configuration);
|
|
+ // If the global configuration doesn't allow root certificates to be loaded
|
|
+ // on demand then we have to disable it for this socket as well.
|
|
+ if (!configuration.allowRootCertOnDemandLoading)
|
|
+ allowRootCertOnDemandLoading = false;
|
|
}
|
|
|
|
/*!
|
|
@@ -2470,6 +2474,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
|
|
ptr->sessionProtocol = global->sessionProtocol;
|
|
ptr->ciphers = global->ciphers;
|
|
ptr->caCertificates = global->caCertificates;
|
|
+ ptr->allowRootCertOnDemandLoading = global->allowRootCertOnDemandLoading;
|
|
ptr->protocol = global->protocol;
|
|
ptr->peerVerifyMode = global->peerVerifyMode;
|
|
ptr->peerVerifyDepth = global->peerVerifyDepth;
|