Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package qt6-base for openSUSE:Factory 
checked in at 2023-06-05 18:08:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/qt6-base (Old)
 and      /work/SRC/openSUSE:Factory/.qt6-base.new.15902 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "qt6-base"

Mon Jun  5 18:08:10 2023 rev:33 rq:1090900 version:6.5.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/qt6-base/qt6-base.changes        2023-05-28 
19:21:52.648617485 +0200
+++ /work/SRC/openSUSE:Factory/.qt6-base.new.15902/qt6-base.changes     
2023-06-05 18:08:27.339788454 +0200
@@ -1,0 +2,7 @@
+Mon Jun  5 08:59:52 UTC 2023 - Christophe Marin <[email protected]>
+
+- Add upstream changes (CVE-2023-34410, boo#1211994):
+  * 0001-Schannel-Reject-certificate-not-signed-by-a-configur.patch
+  * 0001-Ssl-Copy-the-on-demand-cert-loading-bool-from-defaul.patch
+
+-------------------------------------------------------------------

New:
----
  0001-Schannel-Reject-certificate-not-signed-by-a-configur.patch
  0001-Ssl-Copy-the-on-demand-cert-loading-bool-from-defaul.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ qt6-base.spec ++++++
--- /var/tmp/diff_new_pack.I2Rn01/_old  2023-06-05 18:08:28.235793746 +0200
+++ /var/tmp/diff_new_pack.I2Rn01/_new  2023-06-05 18:08:28.239793769 +0200
@@ -39,6 +39,8 @@
 Source:         
https://download.qt.io/official_releases/qt/%{short_version}/%{real_version}%{tar_suffix}/submodules/%{tar_name}-%{real_version}%{tar_suffix}.tar.xz
 Source99:       qt6-base-rpmlintrc
 # Patches 0-100 are upstream patches #
+Patch0:         0001-Schannel-Reject-certificate-not-signed-by-a-configur.patch
+Patch1:         0001-Ssl-Copy-the-on-demand-cert-loading-bool-from-defaul.patch
 # Patches 100-200 are openSUSE and/or non-upstream(able) patches #
 Patch100:       0001-Tell-the-truth-about-private-API.patch
 # No need to pollute the library dir with object files, install them in the 
qt6 subfolder

++++++ 0001-Schannel-Reject-certificate-not-signed-by-a-configur.patch ++++++
>From ada2c573c1a25f8d96577734968fe317ddfa292a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= <[email protected]>
Date: Wed, 10 May 2023 16:43:41 +0200
Subject: [PATCH] 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 <[email protected]>
Reviewed-by: Volker Hilsheimer <[email protected]>
---
 src/plugins/tls/schannel/qtls_schannel.cpp    |  21 ++++
 .../network/ssl/client-auth/CMakeLists.txt    |  24 ++++
 .../network/ssl/client-auth/certs/.gitignore  |   4 +
 .../client-auth/certs/accepted-client.conf    |  14 +++
 .../network/ssl/client-auth/certs/generate.sh |  33 +++++
 .../tst_manual_ssl_client_auth.cpp            | 118 ++++++++++++++++++
 6 files changed, 214 insertions(+)
 create mode 100644 tests/manual/network/ssl/client-auth/CMakeLists.txt
 create mode 100644 tests/manual/network/ssl/client-auth/certs/.gitignore
 create mode 100644 
tests/manual/network/ssl/client-auth/certs/accepted-client.conf
 create mode 100755 tests/manual/network/ssl/client-auth/certs/generate.sh
 create mode 100644 
tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp

diff --git a/src/plugins/tls/schannel/qtls_schannel.cpp 
b/src/plugins/tls/schannel/qtls_schannel.cpp
index d72aaa5a36..ae9ff06eae 100644
--- a/src/plugins/tls/schannel/qtls_schannel.cpp
+++ b/src/plugins/tls/schannel/qtls_schannel.cpp
@@ -2066,6 +2066,27 @@ bool 
TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext)
         verifyDepth = DWORD(q->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;
+        }
+    }
+
     QList<QSslCertificate> peerCertificateChain;
     for (DWORD i = 0; i < verifyDepth; i++) {
         CERT_CHAIN_ELEMENT *element = chain->rgpElement[i];
diff --git a/tests/manual/network/ssl/client-auth/CMakeLists.txt 
b/tests/manual/network/ssl/client-auth/CMakeLists.txt
new file mode 100644
index 0000000000..67ecc20bf4
--- /dev/null
+++ b/tests/manual/network/ssl/client-auth/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_internal_add_manual_test(tst_manual_ssl_client_auth
+    SOURCES
+        tst_manual_ssl_client_auth.cpp
+    LIBRARIES
+        Qt::Network
+)
+
+qt_internal_add_resource(tst_manual_ssl_client_auth 
"tst_manual_ssl_client_auth"
+    PREFIX
+        "/"
+    FILES
+        "certs/127.0.0.1.pem"
+        "certs/127.0.0.1-key.pem"
+        "certs/127.0.0.1-client.pem"
+        "certs/127.0.0.1-client-key.pem"
+        "certs/accepted-client.pem"
+        "certs/accepted-client-key.pem"
+        "certs/rootCA.pem"
+    BASE
+        "certs"
+)
diff --git a/tests/manual/network/ssl/client-auth/certs/.gitignore 
b/tests/manual/network/ssl/client-auth/certs/.gitignore
new file mode 100644
index 0000000000..5866f7b609
--- /dev/null
+++ b/tests/manual/network/ssl/client-auth/certs/.gitignore
@@ -0,0 +1,4 @@
+*
+!/.gitignore
+!/generate.sh
+!/accepted-client.conf
diff --git a/tests/manual/network/ssl/client-auth/certs/accepted-client.conf 
b/tests/manual/network/ssl/client-auth/certs/accepted-client.conf
new file mode 100644
index 0000000000..a88b276efe
--- /dev/null
+++ b/tests/manual/network/ssl/client-auth/certs/accepted-client.conf
@@ -0,0 +1,14 @@
+[req]
+default_md = sha512
+basicConstraints = CA:FALSE
+extendedKeyUsage = clientAuth
+[req]
+distinguished_name = client_distinguished_name
+prompt = no
+[client_distinguished_name]
+C   = NO
+ST  = Oslo
+L   = Oslo
+O   = The Qt Project
+OU  = The Qt Project
+CN  = Fake Qt Project Client Certificate
diff --git a/tests/manual/network/ssl/client-auth/certs/generate.sh 
b/tests/manual/network/ssl/client-auth/certs/generate.sh
new file mode 100755
index 0000000000..5dbe3b3712
--- /dev/null
+++ b/tests/manual/network/ssl/client-auth/certs/generate.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH 
Qt-GPL-exception-1.0
+
+# Requires mkcert and openssl
+
+warn () { echo "$@" >&2; }
+die () { warn "$@"; exit 1; }
+
+
+command -v mkcert 1>/dev/null 2>&1 || die "Failed to find mkcert"
+command -v openssl 1>/dev/null 2>&1 || die "Failed to find openssl"
+
+SCRIPT=$(realpath "$0")
+SCRIPTPATH=$(dirname "$SCRIPT")
+
+pushd "$SCRIPTPATH" || die "Unable to pushd to $SCRIPTPATH"
+mkcert 127.0.0.1
+mkcert -client 127.0.0.1
+warn "Remember to run mkcert -install if you haven't already"
+
+# Generate CA
+openssl genrsa -out ca-key.pem 2048
+openssl req -new -x509 -noenc -days 365 -key ca-key.pem -out rootCA.pem
+
+# Generate accepted client certificate
+openssl genrsa -out accepted-client-key.pem 2048
+openssl req -new -sha512 -nodes -key accepted-client-key.pem -out 
accepted-client.csr -config accepted-client.conf
+openssl x509 -req -sha512 -days 45 -in accepted-client.csr -CA rootCA.pem 
-CAkey ca-key.pem -CAcreateserial -out accepted-client.pem
+rm accepted-client.csr
+rm rootCA.srl
+
+popd || die "Unable to popd"
diff --git 
a/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp 
b/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp
new file mode 100644
index 0000000000..2307cbb191
--- /dev/null
+++ b/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp
@@ -0,0 +1,118 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH 
Qt-GPL-exception-1.0
+
+#include <QtCore/qcoreapplication.h>
+
+#include <QtCore/qthread.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qdir.h>
+
+#include <QtNetwork/qsslsocket.h>
+#include <QtNetwork/qsslserver.h>
+#include <QtNetwork/qsslconfiguration.h>
+#include <QtNetwork/qsslkey.h>
+
+// Client and/or server presents a certificate signed by a system-trusted CA
+// but the other side presents a certificate signed by a different CA.
+constexpr bool TestServerPresentsIncorrectCa = false;
+constexpr bool TestClientPresentsIncorrectCa = true;
+
+class ServerThread : public QThread
+{
+    Q_OBJECT
+public:
+    void run() override
+    {
+        QSslServer server;
+
+        QSslConfiguration config = server.sslConfiguration();
+        QList<QSslCertificate> certs = 
QSslCertificate::fromPath(QStringLiteral(":/rootCA.pem"));
+        config.setCaCertificates(certs);
+        
config.setLocalCertificate(QSslCertificate::fromPath(QStringLiteral(":/127.0.0.1.pem"))
+                                           .first());
+        QFile keyFile(QStringLiteral(":/127.0.0.1-key.pem"));
+        if (!keyFile.open(QIODevice::ReadOnly))
+            qFatal("Failed to open key file");
+        config.setPrivateKey(QSslKey(&keyFile, QSsl::Rsa));
+        config.setPeerVerifyMode(QSslSocket::VerifyPeer);
+        server.setSslConfiguration(config);
+
+        connect(&server, &QSslServer::pendingConnectionAvailable, [&server]() {
+            QSslSocket *socket = static_cast<QSslSocket 
*>(server.nextPendingConnection());
+            qDebug() << "[s] newConnection" << socket->peerAddress() << 
socket->peerPort();
+            socket->disconnectFromHost();
+            qApp->quit();
+        });
+        connect(&server, &QSslServer::startedEncryptionHandshake, 
[](QSslSocket *socket) {
+            qDebug() << "[s] new handshake" << socket->peerAddress() << 
socket->peerPort();
+        });
+        connect(&server, &QSslServer::errorOccurred,
+                [](QSslSocket *socket, QAbstractSocket::SocketError error) {
+                    qDebug() << "[s] errorOccurred" << socket->peerAddress() 
<< socket->peerPort()
+                             << error << socket->errorString();
+                });
+        connect(&server, &QSslServer::peerVerifyError,
+                [](QSslSocket *socket, const QSslError &error) {
+                    qDebug() << "[s] peerVerifyError" << socket->peerAddress() 
<< socket->peerPort()
+                             << error;
+                });
+        server.listen(QHostAddress::LocalHost, 24242);
+
+        exec();
+
+        server.close();
+    }
+};
+
+int main(int argc, char **argv)
+{
+    QCoreApplication app(argc, argv);
+
+    using namespace Qt::StringLiterals;
+
+    if (!QFileInfo(u":/rootCA.pem"_s).exists())
+        qFatal("rootCA.pem not found. Did you run generate.sh in the certs 
directory?");
+
+    ServerThread serverThread;
+    serverThread.start();
+
+    QSslSocket socket;
+    QSslConfiguration config = socket.sslConfiguration();
+    QString certificatePath;
+    QString keyFileName;
+    if constexpr (TestClientPresentsIncorrectCa) { // true: Present cert 
signed with incorrect CA: should fail
+        certificatePath = u":/127.0.0.1-client.pem"_s;
+        keyFileName = u":/127.0.0.1-client-key.pem"_s;
+    } else { // false: Use correct CA: should succeed
+        certificatePath = u":/accepted-client.pem"_s;
+        keyFileName = u":/accepted-client-key.pem"_s;
+    }
+    
config.setLocalCertificate(QSslCertificate::fromPath(certificatePath).first());
+    if (TestServerPresentsIncorrectCa) // true: Verify server using incorrect 
CA: should fail
+        config.setCaCertificates(QSslCertificate::fromPath(u":/rootCA.pem"_s));
+    QFile keyFile(keyFileName);
+    if (!keyFile.open(QIODevice::ReadOnly))
+        qFatal("Failed to open key file");
+    config.setPrivateKey(QSslKey(&keyFile, QSsl::Rsa));
+    socket.setSslConfiguration(config);
+
+    QObject::connect(&socket, &QSslSocket::encrypted, []() { qDebug() << "[c] 
encrypted"; });
+    QObject::connect(&socket, &QSslSocket::errorOccurred,
+            [&socket](QAbstractSocket::SocketError error) {
+                qDebug() << "[c] errorOccurred" << error << 
socket.errorString();
+                qApp->quit();
+            });
+    QObject::connect(&socket, &QSslSocket::sslErrors, [](const 
QList<QSslError> &errors) {
+        qDebug() << "[c] sslErrors" << errors;
+    });
+    QObject::connect(&socket, &QSslSocket::connected, []() { qDebug() << "[c] 
connected"; });
+
+    socket.connectToHostEncrypted(QStringLiteral("127.0.0.1"), 24242);
+
+    const int res = app.exec();
+    serverThread.quit();
+    serverThread.wait();
+    return res;
+}
+
+#include "tst_manual_ssl_client_auth.moc"
-- 
2.40.1


++++++ 0001-Ssl-Copy-the-on-demand-cert-loading-bool-from-defaul.patch ++++++
>From 57ba6260c0801055b7188fdaa1818b940590f5f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= <[email protected]>
Date: Thu, 25 May 2023 14:40:29 +0200
Subject: [PATCH] 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 <[email protected]>
---
 src/network/ssl/qsslsocket.cpp                |  5 ++++
 .../tst_manual_ssl_client_auth.cpp            | 24 ++++++++++++++++---
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 4eefe43929..0563fd0663 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -1973,6 +1973,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;
 
     const auto *tlsBackend = tlsBackendInUse();
     if (!tlsBackend) {
@@ -2281,6 +2285,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;
diff --git 
a/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp 
b/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp
index 2307cbb191..4d4aaca7e3 100644
--- a/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp
+++ b/tests/manual/network/ssl/client-auth/tst_manual_ssl_client_auth.cpp
@@ -16,6 +16,9 @@
 // but the other side presents a certificate signed by a different CA.
 constexpr bool TestServerPresentsIncorrectCa = false;
 constexpr bool TestClientPresentsIncorrectCa = true;
+// Decides whether or not to put the root CA into the global ssl configuration
+// or into the socket's specific ssl configuration.
+constexpr bool UseGlobalConfiguration = true;
 
 class ServerThread : public QThread
 {
@@ -26,8 +29,10 @@ public:
         QSslServer server;
 
         QSslConfiguration config = server.sslConfiguration();
-        QList<QSslCertificate> certs = 
QSslCertificate::fromPath(QStringLiteral(":/rootCA.pem"));
-        config.setCaCertificates(certs);
+        if (!UseGlobalConfiguration) {
+            QList<QSslCertificate> certs = 
QSslCertificate::fromPath(QStringLiteral(":/rootCA.pem"));
+            config.setCaCertificates(certs);
+        }
         
config.setLocalCertificate(QSslCertificate::fromPath(QStringLiteral(":/127.0.0.1.pem"))
                                            .first());
         QFile keyFile(QStringLiteral(":/127.0.0.1-key.pem"));
@@ -73,6 +78,12 @@ int main(int argc, char **argv)
     if (!QFileInfo(u":/rootCA.pem"_s).exists())
         qFatal("rootCA.pem not found. Did you run generate.sh in the certs 
directory?");
 
+    if (UseGlobalConfiguration) {
+        QSslConfiguration config = QSslConfiguration::defaultConfiguration();
+        config.setCaCertificates(QSslCertificate::fromPath(u":/rootCA.pem"_s));
+        QSslConfiguration::setDefaultConfiguration(config);
+    }
+
     ServerThread serverThread;
     serverThread.start();
 
@@ -88,12 +99,19 @@ int main(int argc, char **argv)
         keyFileName = u":/accepted-client-key.pem"_s;
     }
     
config.setLocalCertificate(QSslCertificate::fromPath(certificatePath).first());
-    if (TestServerPresentsIncorrectCa) // true: Verify server using incorrect 
CA: should fail
+    if (!UseGlobalConfiguration && TestServerPresentsIncorrectCa) {
+        // Verify server using incorrect CA: should fail
         config.setCaCertificates(QSslCertificate::fromPath(u":/rootCA.pem"_s));
+    } else if (UseGlobalConfiguration && !TestServerPresentsIncorrectCa) {
+        // Verify server using correct CA, we need to explicitly set the
+        // system CAs when the global config is overridden.
+        config.setCaCertificates(QSslConfiguration::systemCaCertificates());
+    }
     QFile keyFile(keyFileName);
     if (!keyFile.open(QIODevice::ReadOnly))
         qFatal("Failed to open key file");
     config.setPrivateKey(QSslKey(&keyFile, QSsl::Rsa));
+
     socket.setSslConfiguration(config);
 
     QObject::connect(&socket, &QSslSocket::encrypted, []() { qDebug() << "[c] 
encrypted"; });
-- 
2.40.1

Reply via email to