summaryrefslogtreecommitdiff
path: root/dev-qt/qtnetwork/files/qtnetwork-5.15.9-CVE-2023-34410.patch
blob: 3c9145256328d18c55680633176cabe3febff629 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
From 51a3c8d7b8140f0bf6912d14a58bcd0092b868a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= <marten.nordheim@qt.io>
Date: Wed, 10 May 2023 16:43:41 +0200
Subject: [PATCH 1/2] Schannel: Reject certificate not signed by a configured
 CA certificate

Not entirely clear why, but when building the certificate chain for a
peer the system certificate store is searched for root certificates.
General expectation is that after calling
`sslConfiguration.setCaCertificates()` the system certificates will
not be taken into consideration.

To work around this behavior, we do a manual check that the root of the
chain is part of the configured CA certificates.

Pick-to: 6.5 6.2 5.15
Change-Id: I03666a4d9b0eac39ae97e150b4743120611a11b3
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit ada2c573c1a25f8d96577734968fe317ddfa292a)
---
 src/network/ssl/qsslsocket_schannel.cpp | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/src/network/ssl/qsslsocket_schannel.cpp b/src/network/ssl/qsslsocket_schannel.cpp
index c956ce3c2b..d1b23af29b 100644
--- 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);
-- 
2.41.0


From a933f89e1f69b97ccb9d1e5f82d9a619c02afcd2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= <marten.nordheim@qt.io>
Date: Thu, 25 May 2023 14:40:29 +0200
Subject: [PATCH 2/2] Ssl: Copy the on-demand cert loading bool from default
 config

Otherwise individual sockets will still load system certificates when
a chain doesn't match against the configured CA certificates.
That's not intended behavior, since specifically setting the CA
certificates means you don't want the system certificates to be used.

Follow-up to/amends ada2c573c1a25f8d96577734968fe317ddfa292a

This is potentially a breaking change because now, if you ever add a
CA to the default config, it will disable loading system certificates
on demand for all sockets. And the only way to re-enable it is to
create a null-QSslConfiguration and set it as the new default.

Pick-to: 6.5 6.2 5.15
Change-Id: Ic3b2ab125c0cdd58ad654af1cb36173960ce2d1e
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
(cherry picked from commit 57ba6260c0801055b7188fdaa1818b940590f5f1)
---
 src/network/ssl/qsslsocket.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 5bb6e7ee4a..2a0b3a4f1d 100644
--- 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;
-- 
2.41.0