diff options
Diffstat (limited to 'src/plugins/tls/openssl')
20 files changed, 1116 insertions, 1486 deletions
diff --git a/src/plugins/tls/openssl/CMakeLists.txt b/src/plugins/tls/openssl/CMakeLists.txt index 266292c62a..0e0a7a1552 100644 --- a/src/plugins/tls/openssl/CMakeLists.txt +++ b/src/plugins/tls/openssl/CMakeLists.txt @@ -1,7 +1,10 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + qt_internal_add_plugin(QTlsBackendOpenSSLPlugin - OUTPUT_NAME opensslbackend + OUTPUT_NAME qopensslbackend CLASS_NAME QTlsBackendOpenSSL - TYPE tls + PLUGIN_TYPE tls SOURCES ../shared/qx509_base.cpp ../shared/qx509_base_p.h ../shared/qtlskey_base.cpp ../shared/qtlskey_base_p.h @@ -14,13 +17,17 @@ qt_internal_add_plugin(QTlsBackendOpenSSLPlugin qsslcontext_openssl.cpp qsslcontext_openssl_p.h qsslsocket_openssl_symbols.cpp qsslsocket_openssl_symbols_p.h qopenssl_p.h - PUBLIC_LIBRARIES + LIBRARIES Qt::NetworkPrivate Qt::CorePrivate DEFINES OPENSSL_API_COMPAT=0x10100000L ) +if (WIN32) # Windows header issues + set_target_properties(QTlsBackendOpenSSLPlugin PROPERTIES UNITY_BUILD OFF) +endif() + qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION QT_FEATURE_dtls SOURCES qdtls_openssl.cpp qdtls_openssl_p.h @@ -35,13 +42,12 @@ qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION APPLE ${FWSecurity} ) -qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION ANDROID AND NOT ANDROID_EMBEDDED +qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION ANDROID SOURCES qsslsocket_openssl_android.cpp ) -qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION QT_FEATURE_openssl - AND QT_FEATURE_ssl AND WIN32 +qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION WIN32 SOURCES qwindowscarootfetcher.cpp qwindowscarootfetcher_p.h ../shared/qwincrypt_p.h @@ -49,3 +55,9 @@ qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION QT_FEATURE_openssl crypt32 ) +if(QT_FEATURE_openssl_linked) + target_link_libraries(QTlsBackendOpenSSLPlugin PRIVATE WrapOpenSSL::WrapOpenSSL) +else() + qt_internal_add_target_include_dirs(QTlsBackendOpenSSLPlugin + WrapOpenSSLHeaders::WrapOpenSSLHeaders) +endif() diff --git a/src/plugins/tls/openssl/qdtls_openssl.cpp b/src/plugins/tls/openssl/qdtls_openssl.cpp index 55a82f7fd4..fc07a29ec8 100644 --- a/src/plugins/tls/openssl/qdtls_openssl.cpp +++ b/src/plugins/tls/openssl/qdtls_openssl.cpp @@ -1,47 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef NOMINMAX -#define NOMINMAX -#endif // NOMINMAX - -#include <QtNetwork/private/qnativesocketengine_p.h> +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include <QtNetwork/private/qnativesocketengine_p_p.h> #include "qsslsocket_openssl_symbols_p.h" #include "qdtls_openssl_p.h" @@ -218,7 +178,7 @@ extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst, QMessageAuthenticationCode hmac(dtls->hashAlgorithm, dtls->secret); hmac.addData(peerData); - const QByteArray cookie = hmac.result(); + const QByteArrayView cookie = hmac.resultView(); Q_ASSERT(cookie.size() >= 0); // DTLS1_COOKIE_LENGTH is erroneously 256 bytes long, must be 255 - RFC 6347, 4.2.1. *cookieLength = qMin(DTLS1_COOKIE_LENGTH - 1, cookie.size()); @@ -241,7 +201,7 @@ extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie, return 0; return newCookieLength == cookieLength - && !std::memcmp(cookie, newCookie, cookieLength); + && !q_CRYPTO_memcmp(cookie, newCookie, size_t(cookieLength)); } extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx) @@ -605,7 +565,7 @@ bool DtlsState::init(QDtlsBasePrivate *dtlsBase, QUdpSocket *socket, Q_ASSERT(dtlsBase); Q_ASSERT(socket); - if (!tlsContext.data() && !initTls(dtlsBase)) + if (!tlsContext && !initTls(dtlsBase)) return false; udpSocket = socket; @@ -632,7 +592,7 @@ void DtlsState::reset() bool DtlsState::initTls(QDtlsBasePrivate *dtlsBase) { - if (tlsContext.data()) + if (tlsContext) return true; if (!QSslSocket::supportsSsl()) @@ -653,7 +613,7 @@ bool DtlsState::initTls(QDtlsBasePrivate *dtlsBase) static QString msgFunctionFailed(const char *function) { //: %1: Some function - return QDtls::tr("%1 failed").arg(QLatin1String(function)); + return QDtls::tr("%1 failed").arg(QLatin1StringView(function)); } bool DtlsState::initCtxAndConnection(QDtlsBasePrivate *dtlsBase) @@ -716,7 +676,7 @@ bool DtlsState::initCtxAndConnection(QDtlsBasePrivate *dtlsBase) bool DtlsState::initBIO(QDtlsBasePrivate *dtlsBase) { Q_ASSERT(dtlsBase); - Q_ASSERT(tlsContext.data() && tlsConnection.data()); + Q_ASSERT(tlsContext && tlsConnection); BioMethod customMethod(q_BIO_meth_new(BIO_TYPE_DGRAM, dtlsbio::qdtlsMethodName), dtlsutil::delete_bio_method); @@ -1288,12 +1248,12 @@ unsigned QDtlsPrivateOpenSSL::pskClientCallback(const char *hint, char *identity return 0; // Copy data back into OpenSSL - const int identityLength = qMin(pskAuthenticator.identity().length(), + const int identityLength = qMin(pskAuthenticator.identity().size(), pskAuthenticator.maximumIdentityLength()); std::memcpy(identity, pskAuthenticator.identity().constData(), identityLength); identity[identityLength] = 0; - const int pskLength = qMin(pskAuthenticator.preSharedKey().length(), + const int pskLength = qMin(pskAuthenticator.preSharedKey().size(), pskAuthenticator.maximumPreSharedKeyLength()); std::memcpy(psk, pskAuthenticator.preSharedKey().constData(), pskLength); @@ -1319,7 +1279,7 @@ unsigned QDtlsPrivateOpenSSL::pskServerCallback(const char *identity, unsigned c return 0; // Copy data back into OpenSSL - const int pskLength = qMin(pskAuthenticator.preSharedKey().length(), + const int pskLength = qMin(pskAuthenticator.preSharedKey().size(), pskAuthenticator.maximumPreSharedKeyLength()); std::memcpy(psk, pskAuthenticator.preSharedKey().constData(), pskLength); @@ -1364,7 +1324,7 @@ bool QDtlsPrivateOpenSSL::verifyPeer() // Translate errors from the error list into QSslErrors using CertClass = QTlsPrivate::X509CertificateOpenSSL; errors.reserve(errors.size() + opensslErrors.size()); - for (const auto &error : qAsConst(opensslErrors)) { + for (const auto &error : std::as_const(opensslErrors)) { const auto value = peerCertificateChain.value(error.depth); errors << CertClass::openSSLErrorToQSslError(error.code, value); } @@ -1421,9 +1381,12 @@ void QDtlsPrivateOpenSSL::fetchNegotiatedParameters() // TLS 1.2, that's how it's set by OpenSSL (and that's what they are?). switch (q_SSL_version(dtls.tlsConnection.data())) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case DTLS1_VERSION: sessionProtocol = QSsl::DtlsV1_0; break; +QT_WARNING_POP case DTLS1_2_VERSION: sessionProtocol = QSsl::DtlsV1_2; break; diff --git a/src/plugins/tls/openssl/qdtls_openssl_p.h b/src/plugins/tls/openssl/qdtls_openssl_p.h index d10d4ce584..44be86f1ed 100644 --- a/src/plugins/tls/openssl/qdtls_openssl_p.h +++ b/src/plugins/tls/openssl/qdtls_openssl_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QDTLS_OPENSSL_P_H #define QDTLS_OPENSSL_P_H @@ -92,7 +56,7 @@ public: using BioMethod = QSharedPointer<BIO_METHOD>; BioMethod bioMethod; - using TlsContext = QSharedPointer<QSslContext>; + using TlsContext = std::shared_ptr<QSslContext>; TlsContext tlsContext; using TlsConnection = QSharedPointer<SSL>; diff --git a/src/plugins/tls/openssl/qopenssl_p.h b/src/plugins/tls/openssl/qopenssl_p.h index 6daf72a2f8..370b974630 100644 --- a/src/plugins/tls/openssl/qopenssl_p.h +++ b/src/plugins/tls/openssl/qopenssl_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only /**************************************************************************** ** diff --git a/src/plugins/tls/openssl/qsslcontext_openssl.cpp b/src/plugins/tls/openssl/qsslcontext_openssl.cpp index c0afc32e47..75c192bd01 100644 --- a/src/plugins/tls/openssl/qsslcontext_openssl.cpp +++ b/src/plugins/tls/openssl/qsslcontext_openssl.cpp @@ -1,44 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2014 BlackBerry Limited. All rights reserved. -** Copyright (C) 2014 Governikus GmbH & Co. KG. -** Copyright (C) 2016 Richard J. Moore <rich@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2014 BlackBerry Limited. All rights reserved. +// Copyright (C) 2014 Governikus GmbH & Co. KG. +// Copyright (C) 2016 Richard J. Moore <rich@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <QtNetwork/qsslsocket.h> #include <QtNetwork/qssldiffiehellmanparameters.h> @@ -46,6 +10,7 @@ #include "qsslsocket_openssl_symbols_p.h" #include "qsslcontext_openssl_p.h" #include "qtlsbackend_openssl_p.h" +#include "qtlskey_openssl_p.h" #include "qopenssl_p.h" #include <QtNetwork/private/qssl_p.h> @@ -98,17 +63,20 @@ static inline QString msgErrorSettingEllipticCurves(const QString &why) return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why); } -long QSslContext::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions) +qssloptions QSslContext::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions) { - long options; + qssloptions options; switch (protocol) { - case QSsl::SecureProtocols: +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::TlsV1_0OrLater: options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; break; case QSsl::TlsV1_1OrLater: options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1; break; +QT_WARNING_POP + case QSsl::SecureProtocols: case QSsl::TlsV1_2OrLater: options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1; break; @@ -169,21 +137,15 @@ QSslContext::~QSslContext() q_SSL_SESSION_free(session); } -QSslContext* QSslContext::fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading) -{ - QSslContext *sslContext = new QSslContext(); - initSslContext(sslContext, mode, configuration, allowRootCertOnDemandLoading); - return sslContext; -} - -QSharedPointer<QSslContext> QSslContext::sharedFromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading) +std::shared_ptr<QSslContext> QSslContext::sharedFromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading) { - QSharedPointer<QSslContext> sslContext = QSharedPointer<QSslContext>::create(); - initSslContext(sslContext.data(), mode, configuration, allowRootCertOnDemandLoading); + struct AccessToPrivateCtor : QSslContext {}; + std::shared_ptr<QSslContext> sslContext = std::make_shared<AccessToPrivateCtor>(); + initSslContext(sslContext.get(), mode, configuration, allowRootCertOnDemandLoading); return sslContext; } -QSharedPointer<QSslContext> QSslContext::sharedFromPrivateConfiguration(QSslSocket::SslMode mode, QSslConfigurationPrivate *privConfiguration, +std::shared_ptr<QSslContext> QSslContext::sharedFromPrivateConfiguration(QSslSocket::SslMode mode, QSslConfigurationPrivate *privConfiguration, bool allowRootCertOnDemandLoading) { return sharedFromConfiguration(mode, privConfiguration, allowRootCertOnDemandLoading); @@ -256,7 +218,7 @@ SSL* QSslContext::createSsl() QList<QByteArray> protocols = sslConfiguration.d.constData()->nextAllowedProtocols; if (!protocols.isEmpty()) { m_supportedNPNVersions.clear(); - for (int a = 0; a < protocols.count(); ++a) { + for (int a = 0; a < protocols.size(); ++a) { if (protocols.at(a).size() > 255) { qCWarning(lcTlsBackend) << "TLS NPN extension" << protocols.at(a) << "is too long and will be ignored."; @@ -268,7 +230,7 @@ SSL* QSslContext::createSsl() } if (m_supportedNPNVersions.size()) { m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data()); - m_npnContext.len = m_supportedNPNVersions.count(); + m_npnContext.len = m_supportedNPNVersions.size(); m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone; // Callback's type has a parameter 'const unsigned char ** out' // since it was introduced in 1.0.2. Internally, OpenSSL's own code @@ -363,8 +325,11 @@ void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mo bool isDtls = false; init_context: switch (sslContext->sslConfiguration.protocol()) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::DtlsV1_0: case QSsl::DtlsV1_0OrLater: +QT_WARNING_POP case QSsl::DtlsV1_2: case QSsl::DtlsV1_2OrLater: #if QT_CONFIG(dtls) @@ -419,6 +384,8 @@ init_context: long maxVersion = anyVersion; switch (sslContext->sslConfiguration.protocol()) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::TlsV1_0: minVersion = TLS1_VERSION; maxVersion = TLS1_VERSION; @@ -427,6 +394,7 @@ init_context: minVersion = TLS1_1_VERSION; maxVersion = TLS1_1_VERSION; break; +QT_WARNING_POP case QSsl::TlsV1_2: minVersion = TLS1_2_VERSION; maxVersion = TLS1_2_VERSION; @@ -443,7 +411,8 @@ init_context: break; // Ranges: case QSsl::AnyProtocol: - case QSsl::SecureProtocols: +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::TlsV1_0OrLater: minVersion = TLS1_VERSION; maxVersion = 0; @@ -452,25 +421,30 @@ init_context: minVersion = TLS1_1_VERSION; maxVersion = 0; break; +QT_WARNING_POP + case QSsl::SecureProtocols: case QSsl::TlsV1_2OrLater: minVersion = TLS1_2_VERSION; maxVersion = 0; break; +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::DtlsV1_0: minVersion = DTLS1_VERSION; maxVersion = DTLS1_VERSION; break; case QSsl::DtlsV1_0OrLater: minVersion = DTLS1_VERSION; - maxVersion = DTLS_MAX_VERSION; + maxVersion = 0; break; +QT_WARNING_POP case QSsl::DtlsV1_2: minVersion = DTLS1_2_VERSION; maxVersion = DTLS1_2_VERSION; break; case QSsl::DtlsV1_2OrLater: minVersion = DTLS1_2_VERSION; - maxVersion = DTLS_MAX_VERSION; + maxVersion = 0; break; case QSsl::TlsV1_3OrLater: #ifdef TLS1_3_VERSION @@ -502,7 +476,7 @@ init_context: } // Enable bug workarounds. - const long options = setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); + const qssloptions options = setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); q_SSL_CTX_set_options(sslContext->ctx, options); // Tell OpenSSL to release memory early @@ -617,6 +591,13 @@ init_context: if (configuration.d->privateKey.algorithm() == QSsl::Opaque) { sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle()); } else { +#ifdef OPENSSL_NO_DEPRECATED_3_0 + auto qtKey = QTlsBackend::backend<QTlsPrivate::TlsKeyOpenSSL>(configuration.d->privateKey); + Q_ASSERT(qtKey); + sslContext->pkey = qtKey->genericKey; + Q_ASSERT(sslContext->pkey); + q_EVP_PKEY_up_ref(sslContext->pkey); +#else // Load private key sslContext->pkey = q_EVP_PKEY_new(); // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free. @@ -629,7 +610,8 @@ init_context: #ifndef OPENSSL_NO_EC else if (configuration.d->privateKey.algorithm() == QSsl::Ec) q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle())); -#endif +#endif // OPENSSL_NO_EC +#endif // OPENSSL_NO_DEPRECATED_3_0 } auto pkey = sslContext->pkey; if (configuration.d->privateKey.algorithm() == QSsl::Opaque) @@ -650,7 +632,7 @@ init_context: // If we have any intermediate certificates then we need to add them to our chain bool first = true; - for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) { + for (const QSslCertificate &cert : std::as_const(configuration.d->localCertificateChain)) { if (first) { first = false; continue; @@ -715,15 +697,21 @@ init_context: return; } - if (!dhparams.isEmpty()) { + if (dhparams.isEmpty()) { + q_SSL_CTX_set_dh_auto(sslContext->ctx, 1); + } else { +#ifndef OPENSSL_NO_DEPRECATED_3_0 const QByteArray ¶ms = dhparams.d->derData; const char *ptr = params.constData(); DH *dh = q_d2i_DHparams(nullptr, reinterpret_cast<const unsigned char **>(&ptr), - params.length()); + params.size()); if (dh == nullptr) qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form"); q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh); q_DH_free(dh); +#else + qCWarning(lcTlsBackend, "Diffie-Hellman parameters are not supported, because OpenSSL v3 was built with deprecated API removed"); +#endif } #ifndef OPENSSL_NO_PSK diff --git a/src/plugins/tls/openssl/qsslcontext_openssl_p.h b/src/plugins/tls/openssl/qsslcontext_openssl_p.h index c350a93f5e..3bd39baf0c 100644 --- a/src/plugins/tls/openssl/qsslcontext_openssl_p.h +++ b/src/plugins/tls/openssl/qsslcontext_openssl_p.h @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2014 BlackBerry Limited. All rights reserved. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2014 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSSLCONTEXT_OPENSSL_P_H @@ -69,13 +33,12 @@ public: ~QSslContext(); - static QSslContext* fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, - bool allowRootCertOnDemandLoading); - static QSharedPointer<QSslContext> sharedFromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, + static std::shared_ptr<QSslContext> sharedFromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading); - static QSharedPointer<QSslContext> sharedFromPrivateConfiguration(QSslSocket::SslMode mode, QSslConfigurationPrivate *privConfiguration, + static std::shared_ptr<QSslContext> sharedFromPrivateConfiguration(QSslSocket::SslMode mode, QSslConfigurationPrivate *privConfiguration, bool allowRootCertOnDemandLoading); - static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions); + + static qssloptions setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions); QSslError::SslError error() const; QString errorString() const; @@ -105,7 +68,6 @@ public: protected: QSslContext(); - friend class QSharedPointer<QSslContext>; private: static void initSslContext(QSslContext* sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, diff --git a/src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp b/src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp index a917a20744..16e31e605f 100644 --- a/src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp +++ b/src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk> -** Copyright (C) 2016 Richard J. Moore <rich@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk> +// Copyright (C) 2016 Richard J. Moore <rich@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qsslsocket_openssl_symbols_p.h" #include "qtlsbackend_openssl_p.h" @@ -53,58 +17,9 @@ QT_BEGIN_NAMESPACE -namespace { - -#ifdef OPENSSL_NO_DEPRECATED_3_0 - -int q_DH_check(DH *dh, int *status) -{ - // DH_check was first deprecated in OpenSSL 3.0.0, as low-level - // API; the EVP_PKEY family of functions was advised as an alternative. - // As of now EVP_PKEY_params_check ends up calling ... DH_check, - // which is good enough. - - Q_ASSERT(dh); - Q_ASSERT(status); - - EVP_PKEY *key = q_EVP_PKEY_new(); - if (!key) { - qCWarning(lcSsl, "EVP_PKEY_new failed"); - QTlsBackendOpenSSL::logAndClearErrorQueue(); - return 0; - } - const auto keyDeleter = qScopeGuard([key](){ - q_EVP_PKEY_free(key); - }); - if (!q_EVP_PKEY_set1_DH(key, dh)) { - qCWarning(lcTlsBackend, "EVP_PKEY_set1_DH failed"); - QTlsBackendOpenSSL::logAndClearErrorQueue(); - return 0; - } +#ifndef OPENSSL_NO_DEPRECATED_3_0 - EVP_PKEY_CTX *keyCtx = q_EVP_PKEY_CTX_new(key, nullptr); - if (!keyCtx) { - qCWarning(lcTlsBackend, "EVP_PKEY_CTX_new failed"); - QTlsBackendOpenSSL::logAndClearErrorQueue(); - return 0; - } - const auto ctxDeleter = qScopeGuard([keyCtx]{ - q_EVP_PKEY_CTX_free(keyCtx); - }); - - const int result = q_EVP_PKEY_param_check(keyCtx); - QTlsBackendOpenSSL::logAndClearErrorQueue(); - // Note: unlike DH_check, we cannot obtain the 'status', - // if the 'result' is 0 (actually the result is 1 only - // if this 'status' was 0). We could probably check the - // errors from the error queue, but it's not needed anyway - // - see the 'isSafeDH' below, how it returns immediately - // on 0. - Q_UNUSED(status); - - return result; -} -#endif // OPENSSL_NO_DEPRECATED_3_0 +namespace { bool isSafeDH(DH *dh) { @@ -153,8 +68,11 @@ bool isSafeDH(DH *dh) } // unnamed namespace +#endif + int QTlsBackendOpenSSL::dhParametersFromDer(const QByteArray &der, QByteArray *derData) const { +#ifndef OPENSSL_NO_DEPRECATED_3_0 Q_ASSERT(derData); if (der.isEmpty()) @@ -178,12 +96,17 @@ int QTlsBackendOpenSSL::dhParametersFromDer(const QByteArray &der, QByteArray *d } else { return DHParams::InvalidInputDataError; } - +#else + Q_UNUSED(der); + Q_UNUSED(derData); + qCWarning(lcTlsBackend, "Diffie-Hellman parameters are not supported, because OpenSSL v3 was built with deprecated API removed"); +#endif return DHParams::NoError; } int QTlsBackendOpenSSL::dhParametersFromPem(const QByteArray &pem, QByteArray *data) const { +#ifndef OPENSSL_NO_DEPRECATED_3_0 Q_ASSERT(data); if (pem.isEmpty()) @@ -214,8 +137,9 @@ int QTlsBackendOpenSSL::dhParametersFromPem(const QByteArray &pem, QByteArray *d if (isSafeDH(dh)) { char *buf = nullptr; const int len = q_i2d_DHparams(dh, reinterpret_cast<unsigned char **>(&buf)); + const auto freeBuf = qScopeGuard([&] { q_OPENSSL_free(buf); }); if (len > 0) - *data = QByteArray(buf, len); + data->assign({buf, len}); else return DHParams::InvalidInputDataError; } else { @@ -224,7 +148,11 @@ int QTlsBackendOpenSSL::dhParametersFromPem(const QByteArray &pem, QByteArray *d } else { return DHParams::InvalidInputDataError; } - +#else + Q_UNUSED(pem); + Q_UNUSED(data); + qCWarning(lcTlsBackend, "Diffie-Hellman parameters are not supported, because OpenSSL v3 was built with deprecated API removed"); +#endif return DHParams::NoError; } diff --git a/src/plugins/tls/openssl/qsslsocket_openssl_android.cpp b/src/plugins/tls/openssl/qsslsocket_openssl_android.cpp index 1c11377c0e..6c02215c55 100644 --- a/src/plugins/tls/openssl/qsslsocket_openssl_android.cpp +++ b/src/plugins/tls/openssl/qsslsocket_openssl_android.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only /**************************************************************************** ** @@ -54,6 +18,8 @@ #include <QtCore/QJniEnvironment> #include <QtCore/QJniObject> +#include <QtCore/QList> +#include <QtCore/QByteArray> QT_BEGIN_NAMESPACE diff --git a/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp b/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp index 6b4601163b..4aa9ca6fb1 100644 --- a/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp +++ b/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp @@ -1,43 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2014 BlackBerry Limited. All rights reserved. -** Copyright (C) 2016 Richard J. Moore <rich@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2014 BlackBerry Limited. All rights reserved. +// Copyright (C) 2016 Richard J. Moore <rich@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only /**************************************************************************** ** @@ -55,6 +19,7 @@ ****************************************************************************/ #include "qsslsocket_openssl_symbols_p.h" +#include "qtlsbackend_openssl_p.h" #include <QtNetwork/private/qssl_p.h> @@ -63,7 +28,6 @@ #elif QT_CONFIG(library) # include <QtCore/qlibrary.h> #endif -#include <QtCore/qmutex.h> #include <QtCore/qdatetime.h> #if defined(Q_OS_UNIX) #include <QtCore/qdir.h> @@ -80,6 +44,8 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + /* Note to maintainer: ------------------- @@ -149,9 +115,6 @@ DEFINEFUNC(int, EVP_PKEY_up_ref, EVP_PKEY *a, a, return 0, return) DEFINEFUNC2(EVP_PKEY_CTX *, EVP_PKEY_CTX_new, EVP_PKEY *pkey, pkey, ENGINE *e, e, return nullptr, return) DEFINEFUNC(int, EVP_PKEY_param_check, EVP_PKEY_CTX *ctx, ctx, return 0, return) DEFINEFUNC(void, EVP_PKEY_CTX_free, EVP_PKEY_CTX *ctx, ctx, return, return) -DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return) -DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return) -DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return) DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return) DEFINEFUNC2(void, OPENSSL_sk_pop_free, OPENSSL_STACK *a, a, void (*b)(void*), b, return, DUMMYARG) DEFINEFUNC(OPENSSL_STACK *, OPENSSL_sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return) @@ -159,7 +122,7 @@ DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMM DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG) DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, return) DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return) -DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return) +DEFINEFUNC2(qssloptions, SSL_CTX_set_options, SSL_CTX *ctx, ctx, qssloptions op, op, return 0, return) using info_callback = void (*) (const SSL *ssl, int type, int val); DEFINEFUNC2(void, SSL_set_info_callback, SSL *ssl, ssl, info_callback cb, cb, return, return) DEFINEFUNC(const char *, SSL_alert_type_string, int value, value, return nullptr, return) @@ -183,6 +146,8 @@ DEFINEFUNC(const SSL_METHOD *, TLS_server_method, DUMMYARG, DUMMYARG, return nul DEFINEFUNC(void, X509_up_ref, X509 *a, a, return, DUMMYARG) DEFINEFUNC(ASN1_TIME *, X509_getm_notBefore, X509 *a, a, return nullptr, return) DEFINEFUNC(ASN1_TIME *, X509_getm_notAfter, X509 *a, a, return nullptr, return) +DEFINEFUNC2(void, ASN1_item_free, ASN1_VALUE *val, val, const ASN1_ITEM *it, it, return, return) +DEFINEFUNC(void, X509V3_conf_free, CONF_VALUE *val, val, return, return) DEFINEFUNC(long, X509_get_version, X509 *a, a, return -1, return) DEFINEFUNC(EVP_PKEY *, X509_get_pubkey, X509 *a, a, return nullptr, return) DEFINEFUNC2(void, X509_STORE_set_verify_cb, X509_STORE *a, a, X509_STORE_CTX_verify_cb verify_cb, verify_cb, return, DUMMYARG) @@ -190,11 +155,10 @@ DEFINEFUNC3(int, X509_STORE_set_ex_data, X509_STORE *a, a, int idx, idx, void *d DEFINEFUNC2(void *, X509_STORE_get_ex_data, X509_STORE *r, r, int idx, idx, return nullptr, return) DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get0_chain, X509_STORE_CTX *a, a, return nullptr, return) DEFINEFUNC3(void, CRYPTO_free, void *str, str, const char *file, file, int line, line, return, DUMMYARG) +DEFINEFUNC3(int, CRYPTO_memcmp, const void * in_a, in_a, const void * in_b, in_b, size_t len, len, return 1, return); DEFINEFUNC(long, OpenSSL_version_num, void, DUMMYARG, return 0, return) DEFINEFUNC(const char *, OpenSSL_version, int a, a, return nullptr, return) DEFINEFUNC(unsigned long, SSL_SESSION_get_ticket_lifetime_hint, const SSL_SESSION *session, session, return 0, return) -DEFINEFUNC4(void, DH_get0_pqg, const DH *dh, dh, const BIGNUM **p, p, const BIGNUM **q, q, const BIGNUM **g, g, return, DUMMYARG) -DEFINEFUNC(int, DH_bits, DH *dh, dh, return 0, return) #if QT_CONFIG(dtls) DEFINEFUNC2(int, DTLSv1_listen, SSL *s, s, BIO_ADDR *c, c, return -1, return) @@ -239,6 +203,7 @@ DEFINEFUNC6(int, OCSP_basic_sign, OCSP_BASICRESP *br, br, X509 *signer, signer, const EVP_MD *dg, dg, STACK_OF(X509) *cs, cs, unsigned long flags, flags, return 0, return) #endif // ocsp +DEFINEFUNC(void, AUTHORITY_INFO_ACCESS_free, AUTHORITY_INFO_ACCESS *p, p, return, return) DEFINEFUNC2(void, BIO_set_data, BIO *a, a, void *ptr, ptr, return, DUMMYARG) DEFINEFUNC(void *, BIO_get_data, BIO *a, a, return nullptr, return) DEFINEFUNC2(void, BIO_set_init, BIO *a, a, int init, init, return, DUMMYARG) @@ -258,12 +223,6 @@ DEFINEFUNC3(int, BIO_read, BIO *a, a, void *b, b, int c, c, return -1, return) DEFINEFUNC3(int, BIO_write, BIO *a, a, const void *b, b, int c, c, return -1, return) DEFINEFUNC(int, BN_num_bits, const BIGNUM *a, a, return 0, return) DEFINEFUNC2(BN_ULONG, BN_mod_word, const BIGNUM *a, a, BN_ULONG w, w, return static_cast<BN_ULONG>(-1), return) -#ifndef OPENSSL_NO_EC -DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return nullptr, return) -DEFINEFUNC(int, EC_GROUP_get_degree, const EC_GROUP* g, g, return 0, return) -#endif -DEFINEFUNC(DSA *, DSA_new, DUMMYARG, DUMMYARG, return nullptr, return) -DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG) DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c, return nullptr, return) DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return nullptr, return) DEFINEFUNC3(void, ERR_error_string_n, unsigned long e, e, char *b, b, size_t len, len, return, DUMMYARG) @@ -290,21 +249,7 @@ DEFINEFUNC(const EVP_CIPHER *, EVP_aes_192_cbc, DUMMYARG, DUMMYARG, return nullp DEFINEFUNC(const EVP_CIPHER *, EVP_aes_256_cbc, DUMMYARG, DUMMYARG, return nullptr, return) #endif DEFINEFUNC(const EVP_MD *, EVP_sha1, DUMMYARG, DUMMYARG, return nullptr, return) -DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, void *r, r, return -1, return) -DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return) -DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return) -DEFINEFUNC2(int, EVP_PKEY_set1_DH, EVP_PKEY *a, a, DH *b, b, return -1, return) -#ifndef OPENSSL_NO_EC -DEFINEFUNC2(int, EVP_PKEY_set1_EC_KEY, EVP_PKEY *a, a, EC_KEY *b, b, return -1, return) -#endif -DEFINEFUNC2(int, EVP_PKEY_cmp, const EVP_PKEY *a, a, const EVP_PKEY *b, b, return -1, return) DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG) -DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return nullptr, return) -DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return nullptr, return) -DEFINEFUNC(DH *, EVP_PKEY_get1_DH, EVP_PKEY *a, a, return nullptr, return) -#ifndef OPENSSL_NO_EC -DEFINEFUNC(EC_KEY *, EVP_PKEY_get1_EC_KEY, EVP_PKEY *a, a, return nullptr, return) -#endif DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC(int, EVP_PKEY_type, int a, a, return NID_undef, return) DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return) @@ -316,31 +261,14 @@ DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, retur DEFINEFUNC4(int, OBJ_obj2txt, char *a, a, int b, b, ASN1_OBJECT *c, c, int d, d, return -1, return) DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return) DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PrivateKey, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) - -#ifndef OPENSSL_NO_EC -DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) -DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, return) -#endif // OPENSSL_NO_EC -DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) -DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) DEFINEFUNC7(int, PEM_write_bio_PrivateKey, BIO *a, a, EVP_PKEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) +DEFINEFUNC7(int, PEM_write_bio_PrivateKey_traditional, BIO *a, a, EVP_PKEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PUBKEY, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return) -DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return) DEFINEFUNC2(int, PEM_write_bio_PUBKEY, BIO *a, a, EVP_PKEY *b, b, return 0, return) DEFINEFUNC2(void, RAND_seed, const void *a, a, int b, b, return, DUMMYARG) DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return) DEFINEFUNC2(int, RAND_bytes, unsigned char *b, b, int n, n, return 0, return) -DEFINEFUNC(RSA *, RSA_new, DUMMYARG, DUMMYARG, return nullptr, return) -DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG) DEFINEFUNC(int, SSL_accept, SSL *a, a, return -1, return) DEFINEFUNC(int, SSL_clear, SSL *a, a, return -1, return) DEFINEFUNC3(char *, SSL_CIPHER_description, const SSL_CIPHER *a, a, char *b, b, int c, c, return nullptr, return) @@ -359,7 +287,6 @@ DEFINEFUNC2(void, SSL_CTX_set_verify_depth, SSL_CTX *a, a, int b, b, return, DUM DEFINEFUNC2(int, SSL_CTX_use_certificate, SSL_CTX *a, a, X509 *b, b, return -1, return) DEFINEFUNC3(int, SSL_CTX_use_certificate_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return) DEFINEFUNC2(int, SSL_CTX_use_PrivateKey, SSL_CTX *a, a, EVP_PKEY *b, b, return -1, return) -DEFINEFUNC2(int, SSL_CTX_use_RSAPrivateKey, SSL_CTX *a, a, RSA *b, b, return -1, return) DEFINEFUNC3(int, SSL_CTX_use_PrivateKey_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return) DEFINEFUNC(X509_STORE *, SSL_CTX_get_cert_store, const SSL_CTX *a, a, return nullptr, return) DEFINEFUNC(SSL_CONF_CTX *, SSL_CONF_CTX_new, DUMMYARG, DUMMYARG, return nullptr, return); @@ -374,7 +301,16 @@ DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return) DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return) DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return nullptr, return) + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +DEFINEFUNC(X509 *, SSL_get1_peer_certificate, SSL *a, a, return nullptr, return) +DEFINEFUNC(int, EVP_PKEY_get_bits, const EVP_PKEY *pkey, pkey, return -1, return) +DEFINEFUNC(int, EVP_PKEY_get_base_id, const EVP_PKEY *pkey, pkey, return -1, return) +#else DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return nullptr, return) +DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return) +#endif // OPENSSL_VERSION_MAJOR >= 3 + DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return) DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return nullptr, return) DEFINEFUNC(SSL_CTX *, SSL_get_SSL_CTX, SSL *a, a, return nullptr, return) @@ -491,19 +427,22 @@ DEFINEFUNC2(void *, BIO_get_ex_data, BIO *b, b, int idx, idx, return nullptr, re DEFINEFUNC3(int, BIO_set_ex_data, BIO *b, b, int idx, idx, void *data, data, return -1, return) DEFINEFUNC3(void *, CRYPTO_malloc, size_t num, num, const char *file, file, int line, line, return nullptr, return) + +#ifndef OPENSSL_NO_DEPRECATED_3_0 DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG) +DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return) +DEFINEFUNC4(void, DH_get0_pqg, const DH *dh, dh, const BIGNUM **p, p, const BIGNUM **q, q, const BIGNUM **g, g, return, DUMMYARG) + DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return nullptr, return) DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return) -#ifndef OPENSSL_NO_DEPRECATED_3_0 -DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return) -#endif // OPENSSL_NO_DEPRECATED_3_0 + +DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +#endif DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return nullptr, return) + #ifndef OPENSSL_NO_EC -DEFINEFUNC(EC_KEY *, EC_KEY_dup, const EC_KEY *ec, ec, return nullptr, return) -DEFINEFUNC(EC_KEY *, EC_KEY_new_by_curve_name, int nid, nid, return nullptr, return) -DEFINEFUNC(void, EC_KEY_free, EC_KEY *ecdh, ecdh, return, DUMMYARG) DEFINEFUNC2(size_t, EC_get_builtin_curves, EC_builtin_curve * r, r, size_t nitems, nitems, return 0, return) DEFINEFUNC(int, EC_curve_nist2nid, const char *name, name, return 0, return) #endif // OPENSSL_NO_EC @@ -513,6 +452,65 @@ DEFINEFUNC5(int, PKCS12_parse, PKCS12 *p12, p12, const char *pass, pass, EVP_PKE DEFINEFUNC2(PKCS12 *, d2i_PKCS12_bio, BIO *bio, bio, PKCS12 **pkcs12, pkcs12, return nullptr, return); DEFINEFUNC(void, PKCS12_free, PKCS12 *pkcs12, pkcs12, return, DUMMYARG) +#ifndef OPENSSL_NO_DEPRECATED_3_0 + +DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) + +DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return) +DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return) +DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) +DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) + +DEFINEFUNC2(int, SSL_CTX_use_RSAPrivateKey, SSL_CTX *a, a, RSA *b, b, return -1, return) + +DEFINEFUNC(DSA *, DSA_new, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG) + +DEFINEFUNC(RSA *, RSA_new, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG) + +DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return) +DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return) +DEFINEFUNC(int, DH_bits, DH *dh, dh, return 0, return) + +DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return nullptr, return) +DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return nullptr, return) +DEFINEFUNC(DH *, EVP_PKEY_get1_DH, EVP_PKEY *a, a, return nullptr, return) + +DEFINEFUNC2(int, EVP_PKEY_cmp, const EVP_PKEY *a, a, const EVP_PKEY *b, b, return -1, return) +DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, void *r, r, return -1, return) + +DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return) +DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return) +DEFINEFUNC2(int, EVP_PKEY_set1_DH, EVP_PKEY *a, a, DH *b, b, return -1, return) + +#ifndef OPENSSL_NO_EC + +DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) + +DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, return) +DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) + +DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return nullptr, return) +DEFINEFUNC(int, EC_GROUP_get_degree, const EC_GROUP* g, g, return 0, return) + +DEFINEFUNC2(int, EVP_PKEY_set1_EC_KEY, EVP_PKEY *a, a, EC_KEY *b, b, return -1, return) +DEFINEFUNC(EC_KEY *, EVP_PKEY_get1_EC_KEY, EVP_PKEY *a, a, return nullptr, return) + +DEFINEFUNC(EC_KEY *, EC_KEY_dup, const EC_KEY *ec, ec, return nullptr, return) +DEFINEFUNC(EC_KEY *, EC_KEY_new_by_curve_name, int nid, nid, return nullptr, return) +DEFINEFUNC(void, EC_KEY_free, EC_KEY *ecdh, ecdh, return, DUMMYARG) + +#endif // OPENSSL_NO_EC + + + +#endif + #define RESOLVEFUNC(func) \ if (!(_q_##func = _q_PTR_##func(libs.ssl->resolve(#func))) \ && !(_q_##func = _q_PTR_##func(libs.crypto->resolve(#func)))) \ @@ -557,9 +555,9 @@ struct LibGreaterThan typedef bool result_type; result_type operator()(QStringView lhs, QStringView rhs) const { - const auto lhsparts = lhs.split(QLatin1Char('.')); - const auto rhsparts = rhs.split(QLatin1Char('.')); - Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1); + const auto lhsparts = lhs.split(u'.'); + const auto rhsparts = rhs.split(u'.'); + Q_ASSERT(lhsparts.size() > 1 && rhsparts.size() > 1); // note: checking rhs < lhs, the same as lhs > rhs return std::lexicographical_compare(rhsparts.begin() + 1, rhsparts.end(), @@ -589,8 +587,7 @@ static QStringList libraryPathList() { QStringList paths; # ifdef Q_OS_DARWIN - paths = QString::fromLatin1(qgetenv("DYLD_LIBRARY_PATH")) - .split(QLatin1Char(':'), Qt::SkipEmptyParts); + paths = QString::fromLatin1(qgetenv("DYLD_LIBRARY_PATH")).split(u':', Qt::SkipEmptyParts); // search in .app/Contents/Frameworks UInt32 packageType; @@ -601,15 +598,14 @@ static QStringList libraryPathList() paths << bundleUrl.resolved(frameworksUrl).path(); } # else - paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH")) - .split(QLatin1Char(':'), Qt::SkipEmptyParts); + paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH")).split(u':', Qt::SkipEmptyParts); # endif - paths << QLatin1String("/lib") << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib"); - paths << QLatin1String("/lib64") << QLatin1String("/usr/lib64") << QLatin1String("/usr/local/lib64"); - paths << QLatin1String("/lib32") << QLatin1String("/usr/lib32") << QLatin1String("/usr/local/lib32"); + paths << "/lib"_L1 << "/usr/lib"_L1 << "/usr/local/lib"_L1; + paths << "/lib64"_L1 << "/usr/lib64"_L1 << "/usr/local/lib64"_L1; + paths << "/lib32"_L1 << "/usr/lib32"_L1 << "/usr/local/lib32"_L1; #if defined(Q_OS_ANDROID) - paths << QLatin1String("/system/lib"); + paths << "/system/lib"_L1; #elif defined(Q_OS_LINUX) // discover paths of already loaded libraries QDuplicateTracker<QString> loadedPaths; @@ -621,7 +617,7 @@ static QStringList libraryPathList() } Q_NEVER_INLINE -static QStringList findAllLibs(QLatin1String filter) +static QStringList findAllLibs(QLatin1StringView filter) { const QStringList paths = libraryPathList(); QStringList found; @@ -632,8 +628,8 @@ static QStringList findAllLibs(QLatin1String filter) QStringList entryList = dir.entryList(filters, QDir::Files); std::sort(entryList.begin(), entryList.end(), LibGreaterThan()); - for (const QString &entry : qAsConst(entryList)) - found << path + QLatin1Char('/') + entry; + for (const QString &entry : std::as_const(entryList)) + found << path + u'/' + entry; } return found; @@ -641,22 +637,28 @@ static QStringList findAllLibs(QLatin1String filter) static QStringList findAllLibSsl() { - return findAllLibs(QLatin1String("libssl.*")); + return findAllLibs("libssl.*"_L1); } static QStringList findAllLibCrypto() { - return findAllLibs(QLatin1String("libcrypto.*")); + return findAllLibs("libcrypto.*"_L1); } # endif +#if (OPENSSL_VERSION_NUMBER >> 28) < 3 +#define QT_OPENSSL_VERSION "1_1" +#elif OPENSSL_VERSION_MAJOR == 3 // Starting with 3.0 this define is available +#define QT_OPENSSL_VERSION "3" +#endif // > 3 intentionally left undefined + #ifdef Q_OS_WIN struct LoadedOpenSsl { std::unique_ptr<QSystemLibrary> ssl, crypto; }; -static bool tryToLoadOpenSslWin32Library(QLatin1String ssleay32LibName, QLatin1String libeay32LibName, LoadedOpenSsl &result) +static bool tryToLoadOpenSslWin32Library(QLatin1StringView ssleay32LibName, QLatin1StringView libeay32LibName, LoadedOpenSsl &result) { auto ssleay32 = std::make_unique<QSystemLibrary>(ssleay32LibName); if (!ssleay32->load(false)) { @@ -678,7 +680,8 @@ static LoadedOpenSsl loadOpenSsl() LoadedOpenSsl result; // With OpenSSL 1.1 the names have changed to libssl-1_1 and libcrypto-1_1 for builds using - // MSVC and GCC, with architecture suffixes for non-x86 builds. + // MSVC and GCC. For 3.0 the version suffix changed again, to just '3'. + // For non-x86 builds, an architecture suffix is also appended. #if defined(Q_PROCESSOR_X86_64) #define QT_SSL_SUFFIX "-x64" @@ -690,13 +693,13 @@ static LoadedOpenSsl loadOpenSsl() #define QT_SSL_SUFFIX #endif - tryToLoadOpenSslWin32Library(QLatin1String("libssl-1_1" QT_SSL_SUFFIX), - QLatin1String("libcrypto-1_1" QT_SSL_SUFFIX), result); + tryToLoadOpenSslWin32Library("libssl-" QT_OPENSSL_VERSION QT_SSL_SUFFIX ""_L1, + "libcrypto-" QT_OPENSSL_VERSION QT_SSL_SUFFIX ""_L1, result); #undef QT_SSL_SUFFIX return result; } -#else +#else // !Q_OS_WIN: struct LoadedOpenSsl { std::unique_ptr<QLibrary> ssl, crypto; @@ -746,10 +749,22 @@ static LoadedOpenSsl loadOpenSsl() #ifdef Q_OS_OPENBSD libcrypto->setLoadHints(QLibrary::ExportExternalSymbolsHint); #endif -#if defined(SHLIB_VERSION_NUMBER) && !defined(Q_OS_QNX) // on QNX, the libs are always libssl.so and libcrypto.so + +#if !defined(Q_OS_QNX) // on QNX, the libs are always libssl.so and libcrypto.so + +#if defined(OPENSSL_SHLIB_VERSION) + // OpenSSL v.3 does not have SLIB_VERSION_NUMBER but has OPENSSL_SHLIB_VERSION. + // The comment about OPENSSL_SHLIB_VERSION in opensslv.h is a bit troublesome: + // "This is defined in free form." + auto shlibVersion = QString("%1"_L1).arg(OPENSSL_SHLIB_VERSION); + libssl->setFileNameAndVersion("ssl"_L1, shlibVersion); + libcrypto->setFileNameAndVersion("crypto"_L1, shlibVersion); +#elif defined(SHLIB_VERSION_NUMBER) // first attempt: the canonical name is libssl.so.<SHLIB_VERSION_NUMBER> - libssl->setFileNameAndVersion(QLatin1String("ssl"), QLatin1String(SHLIB_VERSION_NUMBER)); - libcrypto->setFileNameAndVersion(QLatin1String("crypto"), QLatin1String(SHLIB_VERSION_NUMBER)); + libssl->setFileNameAndVersion("ssl"_L1, SHLIB_VERSION_NUMBER ""_L1); + libcrypto->setFileNameAndVersion("crypto"_L1, SHLIB_VERSION_NUMBER ""_L1); +#endif // OPENSSL_SHLIB_VERSION + if (libcrypto->load() && libssl->load()) { // libssl.so.<SHLIB_VERSION_NUMBER> and libcrypto.so.<SHLIB_VERSION_NUMBER> found return result; @@ -757,7 +772,7 @@ static LoadedOpenSsl loadOpenSsl() libssl->unload(); libcrypto->unload(); } -#endif +#endif // !defined(Q_OS_QNX) #ifndef Q_OS_DARWIN // second attempt: find the development files libssl.so and libcrypto.so @@ -775,13 +790,13 @@ static LoadedOpenSsl loadOpenSsl() return suffix; }; - static QString suffix = QString::fromLatin1(openSSLSuffix("_1_1")); + static QString suffix = QString::fromLatin1(openSSLSuffix("_" QT_OPENSSL_VERSION)); - libssl->setFileNameAndVersion(QLatin1String("ssl") + suffix, -1); - libcrypto->setFileNameAndVersion(QLatin1String("crypto") + suffix, -1); + libssl->setFileNameAndVersion("ssl"_L1 + suffix, -1); + libcrypto->setFileNameAndVersion("crypto"_L1 + suffix, -1); # else - libssl->setFileNameAndVersion(QLatin1String("ssl"), -1); - libcrypto->setFileNameAndVersion(QLatin1String("crypto"), -1); + libssl->setFileNameAndVersion("ssl"_L1, -1); + libcrypto->setFileNameAndVersion("crypto"_L1, -1); # endif if (libcrypto->load() && libssl->load()) { // libssl.so.0 and libcrypto.so.0 found @@ -797,6 +812,11 @@ static LoadedOpenSsl loadOpenSsl() const QStringList cryptoList = findAllLibCrypto(); for (const QString &crypto : cryptoList) { +#ifdef Q_OS_DARWIN + // Clients should not load the unversioned libcrypto dylib as it does not have a stable ABI + if (crypto.endsWith("libcrypto.dylib")) + continue; +#endif libcrypto->setFileNameAndVersion(crypto, -1); if (libcrypto->load()) { QFileInfo fi(crypto); @@ -830,380 +850,405 @@ static LoadedOpenSsl loadOpenSsl() } #endif -static QBasicMutex symbolResolveMutex; -static QBasicAtomicInt symbolsResolved = Q_BASIC_ATOMIC_INITIALIZER(false); -static bool triedToResolveSymbols = false; - bool q_resolveOpenSslSymbols() { - if (symbolsResolved.loadAcquire()) - return true; - QMutexLocker locker(&symbolResolveMutex); - if (symbolsResolved.loadRelaxed()) - return true; - if (triedToResolveSymbols) - return false; - triedToResolveSymbols = true; - - LoadedOpenSsl libs = loadOpenSsl(); - if (!libs.ssl || !libs.crypto) - // failed to load them - return false; - - RESOLVEFUNC(OPENSSL_init_ssl) - RESOLVEFUNC(OPENSSL_init_crypto) - RESOLVEFUNC(ASN1_STRING_get0_data) - RESOLVEFUNC(EVP_CIPHER_CTX_reset) - RESOLVEFUNC(EVP_PKEY_up_ref) - RESOLVEFUNC(EVP_PKEY_CTX_new) - RESOLVEFUNC(EVP_PKEY_param_check) - RESOLVEFUNC(EVP_PKEY_CTX_free) - RESOLVEFUNC(EVP_PKEY_base_id) - RESOLVEFUNC(RSA_bits) - RESOLVEFUNC(OPENSSL_sk_new_null) - RESOLVEFUNC(OPENSSL_sk_push) - RESOLVEFUNC(OPENSSL_sk_free) - RESOLVEFUNC(OPENSSL_sk_num) - RESOLVEFUNC(OPENSSL_sk_pop_free) - RESOLVEFUNC(OPENSSL_sk_value) - RESOLVEFUNC(DH_get0_pqg) - RESOLVEFUNC(SSL_CTX_set_options) - RESOLVEFUNC(SSL_set_info_callback) - RESOLVEFUNC(SSL_alert_type_string) - RESOLVEFUNC(SSL_alert_desc_string_long) - RESOLVEFUNC(SSL_CTX_get_security_level) - RESOLVEFUNC(SSL_CTX_set_security_level) + static bool symbolsResolved = []() { + LoadedOpenSsl libs = loadOpenSsl(); + if (!libs.ssl || !libs.crypto) { + qCWarning(lcTlsBackend, "Failed to load libssl/libcrypto."); + return false; + } + + RESOLVEFUNC(OPENSSL_init_ssl) + RESOLVEFUNC(OPENSSL_init_crypto) + RESOLVEFUNC(ASN1_STRING_get0_data) + RESOLVEFUNC(EVP_CIPHER_CTX_reset) + RESOLVEFUNC(AUTHORITY_INFO_ACCESS_free) + RESOLVEFUNC(EVP_PKEY_up_ref) + RESOLVEFUNC(EVP_PKEY_CTX_new) + RESOLVEFUNC(EVP_PKEY_param_check) + RESOLVEFUNC(EVP_PKEY_CTX_free) + RESOLVEFUNC(OPENSSL_sk_new_null) + RESOLVEFUNC(OPENSSL_sk_push) + RESOLVEFUNC(OPENSSL_sk_free) + RESOLVEFUNC(OPENSSL_sk_num) + RESOLVEFUNC(OPENSSL_sk_pop_free) + RESOLVEFUNC(OPENSSL_sk_value) + RESOLVEFUNC(SSL_CTX_set_options) + RESOLVEFUNC(SSL_set_info_callback) + RESOLVEFUNC(SSL_alert_type_string) + RESOLVEFUNC(SSL_alert_desc_string_long) + RESOLVEFUNC(SSL_CTX_get_security_level) + RESOLVEFUNC(SSL_CTX_set_security_level) #ifdef TLS1_3_VERSION - RESOLVEFUNC(SSL_CTX_set_ciphersuites) - RESOLVEFUNC(SSL_set_psk_use_session_callback) - RESOLVEFUNC(SSL_CTX_sess_set_new_cb) - RESOLVEFUNC(SSL_SESSION_is_resumable) + RESOLVEFUNC(SSL_CTX_set_ciphersuites) + RESOLVEFUNC(SSL_set_psk_use_session_callback) + RESOLVEFUNC(SSL_CTX_sess_set_new_cb) + RESOLVEFUNC(SSL_SESSION_is_resumable) #endif // TLS 1.3 or OpenSSL > 1.1.1 - RESOLVEFUNC(SSL_get_client_random) - RESOLVEFUNC(SSL_SESSION_get_master_key) - RESOLVEFUNC(SSL_session_reused) - RESOLVEFUNC(SSL_get_session) - RESOLVEFUNC(SSL_set_options) - RESOLVEFUNC(CRYPTO_get_ex_new_index) - RESOLVEFUNC(TLS_method) - RESOLVEFUNC(TLS_client_method) - RESOLVEFUNC(TLS_server_method) - RESOLVEFUNC(X509_up_ref) - RESOLVEFUNC(X509_STORE_CTX_get0_chain) - RESOLVEFUNC(X509_getm_notBefore) - RESOLVEFUNC(X509_getm_notAfter) - RESOLVEFUNC(X509_get_version) - RESOLVEFUNC(X509_get_pubkey) - RESOLVEFUNC(X509_STORE_set_verify_cb) - RESOLVEFUNC(X509_STORE_set_ex_data) - RESOLVEFUNC(X509_STORE_get_ex_data) - RESOLVEFUNC(CRYPTO_free) - RESOLVEFUNC(OpenSSL_version_num) - RESOLVEFUNC(OpenSSL_version) - - if (!_q_OpenSSL_version) { - // Apparently, we were built with OpenSSL 1.1 enabled but are now using - // a wrong library. - qCWarning(lcTlsBackend, "Incompatible version of OpenSSL"); - return false; - } + RESOLVEFUNC(SSL_get_client_random) + RESOLVEFUNC(SSL_SESSION_get_master_key) + RESOLVEFUNC(SSL_session_reused) + RESOLVEFUNC(SSL_get_session) + RESOLVEFUNC(SSL_set_options) + RESOLVEFUNC(CRYPTO_get_ex_new_index) + RESOLVEFUNC(TLS_method) + RESOLVEFUNC(TLS_client_method) + RESOLVEFUNC(TLS_server_method) + RESOLVEFUNC(X509_up_ref) + RESOLVEFUNC(X509_STORE_CTX_get0_chain) + RESOLVEFUNC(X509_getm_notBefore) + RESOLVEFUNC(X509_getm_notAfter) + RESOLVEFUNC(ASN1_item_free) + RESOLVEFUNC(X509V3_conf_free) + RESOLVEFUNC(X509_get_version) + RESOLVEFUNC(X509_get_pubkey) + RESOLVEFUNC(X509_STORE_set_verify_cb) + RESOLVEFUNC(X509_STORE_set_ex_data) + RESOLVEFUNC(X509_STORE_get_ex_data) + RESOLVEFUNC(CRYPTO_free) + RESOLVEFUNC(CRYPTO_memcmp) + RESOLVEFUNC(OpenSSL_version_num) + RESOLVEFUNC(OpenSSL_version) + + if (!_q_OpenSSL_version || !_q_OpenSSL_version_num) { + // Apparently, we were built with OpenSSL 1.1 enabled but are now using + // a wrong library. + qCWarning(lcTlsBackend, "Incompatible version of OpenSSL"); + return false; + } - RESOLVEFUNC(SSL_SESSION_get_ticket_lifetime_hint) - RESOLVEFUNC(DH_bits) - RESOLVEFUNC(DSA_bits) +#if OPENSSL_VERSION_NUMBER >= 0x30000000 + if (q_OpenSSL_version_num() < 0x30000000) { + qCWarning(lcTlsBackend, "Incompatible version of OpenSSL (built with OpenSSL >= 3.x, runtime version is < 3.x)"); + return false; + } +#else + if (q_OpenSSL_version_num() >= 0x30000000) { + qCWarning(lcTlsBackend, "Incompatible version of OpenSSL (built with OpenSSL 1.x, runtime version is >= 3.x)"); + return false; + } +#endif // OPENSSL_VERSION_NUMBER + + RESOLVEFUNC(SSL_SESSION_get_ticket_lifetime_hint) #if QT_CONFIG(dtls) - RESOLVEFUNC(DTLSv1_listen) - RESOLVEFUNC(BIO_ADDR_new) - RESOLVEFUNC(BIO_ADDR_free) - RESOLVEFUNC(BIO_meth_new) - RESOLVEFUNC(BIO_meth_free) - RESOLVEFUNC(BIO_meth_set_write) - RESOLVEFUNC(BIO_meth_set_read) - RESOLVEFUNC(BIO_meth_set_puts) - RESOLVEFUNC(BIO_meth_set_ctrl) - RESOLVEFUNC(BIO_meth_set_create) - RESOLVEFUNC(BIO_meth_set_destroy) + RESOLVEFUNC(DTLSv1_listen) + RESOLVEFUNC(BIO_ADDR_new) + RESOLVEFUNC(BIO_ADDR_free) + RESOLVEFUNC(BIO_meth_new) + RESOLVEFUNC(BIO_meth_free) + RESOLVEFUNC(BIO_meth_set_write) + RESOLVEFUNC(BIO_meth_set_read) + RESOLVEFUNC(BIO_meth_set_puts) + RESOLVEFUNC(BIO_meth_set_ctrl) + RESOLVEFUNC(BIO_meth_set_create) + RESOLVEFUNC(BIO_meth_set_destroy) #endif // dtls #if QT_CONFIG(ocsp) - RESOLVEFUNC(OCSP_SINGLERESP_get0_id) - RESOLVEFUNC(d2i_OCSP_RESPONSE) - RESOLVEFUNC(OCSP_RESPONSE_free) - RESOLVEFUNC(OCSP_response_status) - RESOLVEFUNC(OCSP_response_get1_basic) - RESOLVEFUNC(OCSP_BASICRESP_free) - RESOLVEFUNC(OCSP_basic_verify) - RESOLVEFUNC(OCSP_resp_count) - RESOLVEFUNC(OCSP_resp_get0) - RESOLVEFUNC(OCSP_single_get0_status) - RESOLVEFUNC(OCSP_check_validity) - RESOLVEFUNC(OCSP_cert_to_id) - RESOLVEFUNC(OCSP_id_get0_info) - RESOLVEFUNC(OCSP_resp_get0_certs) - RESOLVEFUNC(OCSP_basic_sign) - RESOLVEFUNC(OCSP_response_create) - RESOLVEFUNC(i2d_OCSP_RESPONSE) - RESOLVEFUNC(OCSP_basic_add1_status) - RESOLVEFUNC(OCSP_BASICRESP_new) - RESOLVEFUNC(OCSP_CERTID_free) - RESOLVEFUNC(OCSP_cert_to_id) - RESOLVEFUNC(OCSP_id_cmp) + RESOLVEFUNC(OCSP_SINGLERESP_get0_id) + RESOLVEFUNC(d2i_OCSP_RESPONSE) + RESOLVEFUNC(OCSP_RESPONSE_free) + RESOLVEFUNC(OCSP_response_status) + RESOLVEFUNC(OCSP_response_get1_basic) + RESOLVEFUNC(OCSP_BASICRESP_free) + RESOLVEFUNC(OCSP_basic_verify) + RESOLVEFUNC(OCSP_resp_count) + RESOLVEFUNC(OCSP_resp_get0) + RESOLVEFUNC(OCSP_single_get0_status) + RESOLVEFUNC(OCSP_check_validity) + RESOLVEFUNC(OCSP_cert_to_id) + RESOLVEFUNC(OCSP_id_get0_info) + RESOLVEFUNC(OCSP_resp_get0_certs) + RESOLVEFUNC(OCSP_basic_sign) + RESOLVEFUNC(OCSP_response_create) + RESOLVEFUNC(i2d_OCSP_RESPONSE) + RESOLVEFUNC(OCSP_basic_add1_status) + RESOLVEFUNC(OCSP_BASICRESP_new) + RESOLVEFUNC(OCSP_CERTID_free) + RESOLVEFUNC(OCSP_cert_to_id) + RESOLVEFUNC(OCSP_id_cmp) #endif // ocsp - RESOLVEFUNC(BIO_set_data) - RESOLVEFUNC(BIO_get_data) - RESOLVEFUNC(BIO_set_init) - RESOLVEFUNC(BIO_get_shutdown) - RESOLVEFUNC(BIO_set_shutdown) - RESOLVEFUNC(ASN1_INTEGER_get) - RESOLVEFUNC(ASN1_INTEGER_cmp) - RESOLVEFUNC(ASN1_STRING_length) - RESOLVEFUNC(ASN1_STRING_to_UTF8) - RESOLVEFUNC(ASN1_TIME_to_tm) - RESOLVEFUNC(BIO_ctrl) - RESOLVEFUNC(BIO_free) - RESOLVEFUNC(BIO_new) - RESOLVEFUNC(BIO_new_mem_buf) - RESOLVEFUNC(BIO_read) - RESOLVEFUNC(BIO_s_mem) - RESOLVEFUNC(BIO_write) - RESOLVEFUNC(BIO_set_flags) - RESOLVEFUNC(BIO_clear_flags) - RESOLVEFUNC(BIO_set_ex_data) - RESOLVEFUNC(BIO_get_ex_data) - -#ifndef OPENSSL_NO_EC - RESOLVEFUNC(EC_KEY_get0_group) - RESOLVEFUNC(EC_GROUP_get_degree) -#endif - RESOLVEFUNC(BN_num_bits) - RESOLVEFUNC(BN_is_word) - RESOLVEFUNC(BN_mod_word) - RESOLVEFUNC(DSA_new) - RESOLVEFUNC(DSA_free) - RESOLVEFUNC(ERR_error_string) - RESOLVEFUNC(ERR_error_string_n) - RESOLVEFUNC(ERR_get_error) - RESOLVEFUNC(EVP_CIPHER_CTX_new) - RESOLVEFUNC(EVP_CIPHER_CTX_free) - RESOLVEFUNC(EVP_CIPHER_CTX_ctrl) - RESOLVEFUNC(EVP_CIPHER_CTX_set_key_length) - RESOLVEFUNC(EVP_CipherInit) - RESOLVEFUNC(EVP_CipherInit_ex) - RESOLVEFUNC(EVP_CipherUpdate) - RESOLVEFUNC(EVP_CipherFinal) - RESOLVEFUNC(EVP_get_digestbyname) + RESOLVEFUNC(BIO_set_data) + RESOLVEFUNC(BIO_get_data) + RESOLVEFUNC(BIO_set_init) + RESOLVEFUNC(BIO_get_shutdown) + RESOLVEFUNC(BIO_set_shutdown) + RESOLVEFUNC(ASN1_INTEGER_get) + RESOLVEFUNC(ASN1_INTEGER_cmp) + RESOLVEFUNC(ASN1_STRING_length) + RESOLVEFUNC(ASN1_STRING_to_UTF8) + RESOLVEFUNC(ASN1_TIME_to_tm) + RESOLVEFUNC(BIO_ctrl) + RESOLVEFUNC(BIO_free) + RESOLVEFUNC(BIO_new) + RESOLVEFUNC(BIO_new_mem_buf) + RESOLVEFUNC(BIO_read) + RESOLVEFUNC(BIO_s_mem) + RESOLVEFUNC(BIO_write) + RESOLVEFUNC(BIO_set_flags) + RESOLVEFUNC(BIO_clear_flags) + RESOLVEFUNC(BIO_set_ex_data) + RESOLVEFUNC(BIO_get_ex_data) + RESOLVEFUNC(BN_num_bits) + RESOLVEFUNC(BN_is_word) + RESOLVEFUNC(BN_mod_word) + RESOLVEFUNC(ERR_error_string) + RESOLVEFUNC(ERR_error_string_n) + RESOLVEFUNC(ERR_get_error) + RESOLVEFUNC(EVP_CIPHER_CTX_new) + RESOLVEFUNC(EVP_CIPHER_CTX_free) + RESOLVEFUNC(EVP_CIPHER_CTX_ctrl) + RESOLVEFUNC(EVP_CIPHER_CTX_set_key_length) + RESOLVEFUNC(EVP_CipherInit) + RESOLVEFUNC(EVP_CipherInit_ex) + RESOLVEFUNC(EVP_CipherUpdate) + RESOLVEFUNC(EVP_CipherFinal) + RESOLVEFUNC(EVP_get_digestbyname) #ifndef OPENSSL_NO_DES - RESOLVEFUNC(EVP_des_cbc) - RESOLVEFUNC(EVP_des_ede3_cbc) + RESOLVEFUNC(EVP_des_cbc) + RESOLVEFUNC(EVP_des_ede3_cbc) #endif #ifndef OPENSSL_NO_RC2 - RESOLVEFUNC(EVP_rc2_cbc) + RESOLVEFUNC(EVP_rc2_cbc) #endif #ifndef OPENSSL_NO_AES - RESOLVEFUNC(EVP_aes_128_cbc) - RESOLVEFUNC(EVP_aes_192_cbc) - RESOLVEFUNC(EVP_aes_256_cbc) + RESOLVEFUNC(EVP_aes_128_cbc) + RESOLVEFUNC(EVP_aes_192_cbc) + RESOLVEFUNC(EVP_aes_256_cbc) #endif - RESOLVEFUNC(EVP_sha1) - RESOLVEFUNC(EVP_PKEY_assign) - RESOLVEFUNC(EVP_PKEY_set1_RSA) - RESOLVEFUNC(EVP_PKEY_set1_DSA) - RESOLVEFUNC(EVP_PKEY_set1_DH) + RESOLVEFUNC(EVP_sha1) + RESOLVEFUNC(EVP_PKEY_free) + RESOLVEFUNC(EVP_PKEY_new) + RESOLVEFUNC(EVP_PKEY_type) + RESOLVEFUNC(OBJ_nid2sn) + RESOLVEFUNC(OBJ_nid2ln) + RESOLVEFUNC(OBJ_sn2nid) + RESOLVEFUNC(OBJ_ln2nid) + RESOLVEFUNC(i2t_ASN1_OBJECT) + RESOLVEFUNC(OBJ_obj2txt) + RESOLVEFUNC(OBJ_obj2nid) + RESOLVEFUNC(PEM_read_bio_PrivateKey) + RESOLVEFUNC(PEM_write_bio_PrivateKey) + RESOLVEFUNC(PEM_write_bio_PrivateKey_traditional) + RESOLVEFUNC(PEM_read_bio_PUBKEY) + RESOLVEFUNC(PEM_write_bio_PUBKEY) + RESOLVEFUNC(RAND_seed) + RESOLVEFUNC(RAND_status) + RESOLVEFUNC(RAND_bytes) + RESOLVEFUNC(SSL_CIPHER_description) + RESOLVEFUNC(SSL_CIPHER_get_bits) + RESOLVEFUNC(SSL_get_rbio) + RESOLVEFUNC(SSL_CTX_check_private_key) + RESOLVEFUNC(SSL_CTX_ctrl) + RESOLVEFUNC(SSL_CTX_free) + RESOLVEFUNC(SSL_CTX_new) + RESOLVEFUNC(SSL_CTX_set_cipher_list) + RESOLVEFUNC(SSL_CTX_callback_ctrl) + RESOLVEFUNC(SSL_CTX_set_default_verify_paths) + RESOLVEFUNC(SSL_CTX_set_verify) + RESOLVEFUNC(SSL_CTX_set_verify_depth) + RESOLVEFUNC(SSL_CTX_use_certificate) + RESOLVEFUNC(SSL_CTX_use_certificate_file) + RESOLVEFUNC(SSL_CTX_use_PrivateKey) + RESOLVEFUNC(SSL_CTX_use_PrivateKey_file) + RESOLVEFUNC(SSL_CTX_get_cert_store); + RESOLVEFUNC(SSL_CONF_CTX_new); + RESOLVEFUNC(SSL_CONF_CTX_free); + RESOLVEFUNC(SSL_CONF_CTX_set_ssl_ctx); + RESOLVEFUNC(SSL_CONF_CTX_set_flags); + RESOLVEFUNC(SSL_CONF_CTX_finish); + RESOLVEFUNC(SSL_CONF_cmd); + RESOLVEFUNC(SSL_accept) + RESOLVEFUNC(SSL_clear) + RESOLVEFUNC(SSL_connect) + RESOLVEFUNC(SSL_free) + RESOLVEFUNC(SSL_get_ciphers) + RESOLVEFUNC(SSL_get_current_cipher) + RESOLVEFUNC(SSL_version) + RESOLVEFUNC(SSL_get_error) + RESOLVEFUNC(SSL_get_peer_cert_chain) + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + RESOLVEFUNC(SSL_get1_peer_certificate) + RESOLVEFUNC(EVP_PKEY_get_bits) + RESOLVEFUNC(EVP_PKEY_get_base_id) +#else + RESOLVEFUNC(SSL_get_peer_certificate) + RESOLVEFUNC(EVP_PKEY_base_id) +#endif // OPENSSL_VERSION_MAJOR >= 3 + +#ifndef OPENSSL_NO_DEPRECATED_3_0 + RESOLVEFUNC(DH_new) + RESOLVEFUNC(DH_free) + RESOLVEFUNC(DH_check) + RESOLVEFUNC(DH_get0_pqg) + + RESOLVEFUNC(d2i_DHparams) + RESOLVEFUNC(i2d_DHparams) + + RESOLVEFUNC(PEM_read_bio_DHparams) + + RESOLVEFUNC(EVP_PKEY_assign) + RESOLVEFUNC(EVP_PKEY_cmp) + + RESOLVEFUNC(EVP_PKEY_set1_RSA) + RESOLVEFUNC(EVP_PKEY_set1_DSA) + RESOLVEFUNC(EVP_PKEY_set1_DH) + + RESOLVEFUNC(EVP_PKEY_get1_DSA) + RESOLVEFUNC(EVP_PKEY_get1_RSA) + RESOLVEFUNC(EVP_PKEY_get1_DH) + + RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY) + RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY) + RESOLVEFUNC(PEM_read_bio_DSAPrivateKey) + RESOLVEFUNC(PEM_read_bio_RSAPrivateKey) + + RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY) + RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY) + RESOLVEFUNC(PEM_write_bio_DSAPrivateKey) + RESOLVEFUNC(PEM_write_bio_RSAPrivateKey) + RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey) + + RESOLVEFUNC(DSA_new) + RESOLVEFUNC(DSA_free) + + RESOLVEFUNC(RSA_new) + RESOLVEFUNC(RSA_free) + + RESOLVEFUNC(DH_bits) + RESOLVEFUNC(DSA_bits) + RESOLVEFUNC(RSA_bits) #ifndef OPENSSL_NO_EC - RESOLVEFUNC(EVP_PKEY_set1_EC_KEY) - RESOLVEFUNC(EVP_PKEY_get1_EC_KEY) - RESOLVEFUNC(PEM_read_bio_ECPrivateKey) - RESOLVEFUNC(PEM_write_bio_ECPrivateKey) - RESOLVEFUNC(PEM_read_bio_EC_PUBKEY) - RESOLVEFUNC(PEM_write_bio_EC_PUBKEY) + + RESOLVEFUNC(EVP_PKEY_set1_EC_KEY) + RESOLVEFUNC(EVP_PKEY_get1_EC_KEY) + RESOLVEFUNC(PEM_read_bio_EC_PUBKEY) + RESOLVEFUNC(PEM_read_bio_ECPrivateKey) + RESOLVEFUNC(PEM_write_bio_EC_PUBKEY) + RESOLVEFUNC(PEM_write_bio_ECPrivateKey) + RESOLVEFUNC(EC_KEY_get0_group) + RESOLVEFUNC(EC_GROUP_get_degree) + RESOLVEFUNC(EC_KEY_dup) + RESOLVEFUNC(EC_KEY_new_by_curve_name) + RESOLVEFUNC(EC_KEY_free) + #endif // OPENSSL_NO_EC - RESOLVEFUNC(EVP_PKEY_cmp) - RESOLVEFUNC(EVP_PKEY_free) - RESOLVEFUNC(EVP_PKEY_get1_DSA) - RESOLVEFUNC(EVP_PKEY_get1_RSA) - RESOLVEFUNC(EVP_PKEY_get1_DH) - RESOLVEFUNC(EVP_PKEY_new) - RESOLVEFUNC(EVP_PKEY_type) - RESOLVEFUNC(OBJ_nid2sn) - RESOLVEFUNC(OBJ_nid2ln) - RESOLVEFUNC(OBJ_sn2nid) - RESOLVEFUNC(OBJ_ln2nid) - RESOLVEFUNC(i2t_ASN1_OBJECT) - RESOLVEFUNC(OBJ_obj2txt) - RESOLVEFUNC(OBJ_obj2nid) - RESOLVEFUNC(PEM_read_bio_PrivateKey) - RESOLVEFUNC(PEM_read_bio_DSAPrivateKey) - RESOLVEFUNC(PEM_read_bio_RSAPrivateKey) - RESOLVEFUNC(PEM_read_bio_DHparams) - RESOLVEFUNC(PEM_write_bio_DSAPrivateKey) - RESOLVEFUNC(PEM_write_bio_RSAPrivateKey) - RESOLVEFUNC(PEM_write_bio_PrivateKey) - RESOLVEFUNC(PEM_read_bio_PUBKEY) - RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY) - RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY) - RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY) - RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY) - RESOLVEFUNC(PEM_write_bio_PUBKEY) - RESOLVEFUNC(RAND_seed) - RESOLVEFUNC(RAND_status) - RESOLVEFUNC(RAND_bytes) - RESOLVEFUNC(RSA_new) - RESOLVEFUNC(RSA_free) - RESOLVEFUNC(SSL_CIPHER_description) - RESOLVEFUNC(SSL_CIPHER_get_bits) - RESOLVEFUNC(SSL_get_rbio) - RESOLVEFUNC(SSL_CTX_check_private_key) - RESOLVEFUNC(SSL_CTX_ctrl) - RESOLVEFUNC(SSL_CTX_free) - RESOLVEFUNC(SSL_CTX_new) - RESOLVEFUNC(SSL_CTX_set_cipher_list) - RESOLVEFUNC(SSL_CTX_callback_ctrl) - RESOLVEFUNC(SSL_CTX_set_default_verify_paths) - RESOLVEFUNC(SSL_CTX_set_verify) - RESOLVEFUNC(SSL_CTX_set_verify_depth) - RESOLVEFUNC(SSL_CTX_use_certificate) - RESOLVEFUNC(SSL_CTX_use_certificate_file) - RESOLVEFUNC(SSL_CTX_use_PrivateKey) - RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey) - RESOLVEFUNC(SSL_CTX_use_PrivateKey_file) - RESOLVEFUNC(SSL_CTX_get_cert_store); - RESOLVEFUNC(SSL_CONF_CTX_new); - RESOLVEFUNC(SSL_CONF_CTX_free); - RESOLVEFUNC(SSL_CONF_CTX_set_ssl_ctx); - RESOLVEFUNC(SSL_CONF_CTX_set_flags); - RESOLVEFUNC(SSL_CONF_CTX_finish); - RESOLVEFUNC(SSL_CONF_cmd); - RESOLVEFUNC(SSL_accept) - RESOLVEFUNC(SSL_clear) - RESOLVEFUNC(SSL_connect) - RESOLVEFUNC(SSL_free) - RESOLVEFUNC(SSL_get_ciphers) - RESOLVEFUNC(SSL_get_current_cipher) - RESOLVEFUNC(SSL_version) - RESOLVEFUNC(SSL_get_error) - RESOLVEFUNC(SSL_get_peer_cert_chain) - RESOLVEFUNC(SSL_get_peer_certificate) - RESOLVEFUNC(SSL_get_verify_result) - RESOLVEFUNC(SSL_new) - RESOLVEFUNC(SSL_get_SSL_CTX) - RESOLVEFUNC(SSL_ctrl) - RESOLVEFUNC(SSL_read) - RESOLVEFUNC(SSL_set_accept_state) - RESOLVEFUNC(SSL_set_bio) - RESOLVEFUNC(SSL_set_connect_state) - RESOLVEFUNC(SSL_shutdown) - RESOLVEFUNC(SSL_in_init) - RESOLVEFUNC(SSL_get_shutdown) - RESOLVEFUNC(SSL_set_session) - RESOLVEFUNC(SSL_SESSION_free) - RESOLVEFUNC(SSL_get1_session) - RESOLVEFUNC(SSL_get_session) - RESOLVEFUNC(SSL_set_ex_data) - RESOLVEFUNC(SSL_get_ex_data) - RESOLVEFUNC(SSL_get_ex_data_X509_STORE_CTX_idx) +#endif // OPENSSL_NO_DEPRECATED_3_0 + + RESOLVEFUNC(SSL_get_verify_result) + RESOLVEFUNC(SSL_new) + RESOLVEFUNC(SSL_get_SSL_CTX) + RESOLVEFUNC(SSL_ctrl) + RESOLVEFUNC(SSL_read) + RESOLVEFUNC(SSL_set_accept_state) + RESOLVEFUNC(SSL_set_bio) + RESOLVEFUNC(SSL_set_connect_state) + RESOLVEFUNC(SSL_shutdown) + RESOLVEFUNC(SSL_in_init) + RESOLVEFUNC(SSL_get_shutdown) + RESOLVEFUNC(SSL_set_session) + RESOLVEFUNC(SSL_SESSION_free) + RESOLVEFUNC(SSL_get1_session) + RESOLVEFUNC(SSL_get_session) + RESOLVEFUNC(SSL_set_ex_data) + RESOLVEFUNC(SSL_get_ex_data) + RESOLVEFUNC(SSL_get_ex_data_X509_STORE_CTX_idx) #ifndef OPENSSL_NO_PSK - RESOLVEFUNC(SSL_set_psk_client_callback) - RESOLVEFUNC(SSL_set_psk_server_callback) - RESOLVEFUNC(SSL_CTX_use_psk_identity_hint) + RESOLVEFUNC(SSL_set_psk_client_callback) + RESOLVEFUNC(SSL_set_psk_server_callback) + RESOLVEFUNC(SSL_CTX_use_psk_identity_hint) #endif // !OPENSSL_NO_PSK - RESOLVEFUNC(SSL_write) - RESOLVEFUNC(X509_NAME_entry_count) - RESOLVEFUNC(X509_NAME_get_entry) - RESOLVEFUNC(X509_NAME_ENTRY_get_data) - RESOLVEFUNC(X509_NAME_ENTRY_get_object) - RESOLVEFUNC(X509_PUBKEY_get) - RESOLVEFUNC(X509_STORE_free) - RESOLVEFUNC(X509_STORE_new) - RESOLVEFUNC(X509_STORE_add_cert) - RESOLVEFUNC(X509_STORE_CTX_free) - RESOLVEFUNC(X509_STORE_CTX_init) - RESOLVEFUNC(X509_STORE_CTX_new) - RESOLVEFUNC(X509_STORE_CTX_set_purpose) - RESOLVEFUNC(X509_STORE_CTX_get_error) - RESOLVEFUNC(X509_STORE_CTX_get_error_depth) - RESOLVEFUNC(X509_STORE_CTX_get_current_cert) - RESOLVEFUNC(X509_STORE_CTX_get0_store) - RESOLVEFUNC(X509_cmp) - RESOLVEFUNC(X509_STORE_CTX_get_ex_data) - RESOLVEFUNC(X509_dup) - RESOLVEFUNC(X509_print) - RESOLVEFUNC(X509_digest) - RESOLVEFUNC(X509_EXTENSION_get_object) - RESOLVEFUNC(X509_free) - RESOLVEFUNC(X509_gmtime_adj) - RESOLVEFUNC(ASN1_TIME_free) - RESOLVEFUNC(X509_get_ext) - RESOLVEFUNC(X509_get_ext_count) - RESOLVEFUNC(X509_get_ext_d2i) - RESOLVEFUNC(X509V3_EXT_get) - RESOLVEFUNC(X509V3_EXT_d2i) - RESOLVEFUNC(X509_EXTENSION_get_critical) - RESOLVEFUNC(X509_EXTENSION_get_data) - RESOLVEFUNC(BASIC_CONSTRAINTS_free) - RESOLVEFUNC(AUTHORITY_KEYID_free) - RESOLVEFUNC(GENERAL_NAME_free) - RESOLVEFUNC(ASN1_STRING_print) - RESOLVEFUNC(X509_check_issued) - RESOLVEFUNC(X509_get_issuer_name) - RESOLVEFUNC(X509_get_subject_name) - RESOLVEFUNC(X509_get_serialNumber) - RESOLVEFUNC(X509_verify_cert) - RESOLVEFUNC(d2i_X509) - RESOLVEFUNC(i2d_X509) + RESOLVEFUNC(SSL_write) + RESOLVEFUNC(X509_NAME_entry_count) + RESOLVEFUNC(X509_NAME_get_entry) + RESOLVEFUNC(X509_NAME_ENTRY_get_data) + RESOLVEFUNC(X509_NAME_ENTRY_get_object) + RESOLVEFUNC(X509_PUBKEY_get) + RESOLVEFUNC(X509_STORE_free) + RESOLVEFUNC(X509_STORE_new) + RESOLVEFUNC(X509_STORE_add_cert) + RESOLVEFUNC(X509_STORE_CTX_free) + RESOLVEFUNC(X509_STORE_CTX_init) + RESOLVEFUNC(X509_STORE_CTX_new) + RESOLVEFUNC(X509_STORE_CTX_set_purpose) + RESOLVEFUNC(X509_STORE_CTX_get_error) + RESOLVEFUNC(X509_STORE_CTX_get_error_depth) + RESOLVEFUNC(X509_STORE_CTX_get_current_cert) + RESOLVEFUNC(X509_STORE_CTX_get0_store) + RESOLVEFUNC(X509_cmp) + RESOLVEFUNC(X509_STORE_CTX_get_ex_data) + RESOLVEFUNC(X509_dup) + RESOLVEFUNC(X509_print) + RESOLVEFUNC(X509_digest) + RESOLVEFUNC(X509_EXTENSION_get_object) + RESOLVEFUNC(X509_free) + RESOLVEFUNC(X509_gmtime_adj) + RESOLVEFUNC(ASN1_TIME_free) + RESOLVEFUNC(X509_get_ext) + RESOLVEFUNC(X509_get_ext_count) + RESOLVEFUNC(X509_get_ext_d2i) + RESOLVEFUNC(X509V3_EXT_get) + RESOLVEFUNC(X509V3_EXT_d2i) + RESOLVEFUNC(X509_EXTENSION_get_critical) + RESOLVEFUNC(X509_EXTENSION_get_data) + RESOLVEFUNC(BASIC_CONSTRAINTS_free) + RESOLVEFUNC(AUTHORITY_KEYID_free) + RESOLVEFUNC(GENERAL_NAME_free) + RESOLVEFUNC(ASN1_STRING_print) + RESOLVEFUNC(X509_check_issued) + RESOLVEFUNC(X509_get_issuer_name) + RESOLVEFUNC(X509_get_subject_name) + RESOLVEFUNC(X509_get_serialNumber) + RESOLVEFUNC(X509_verify_cert) + RESOLVEFUNC(d2i_X509) + RESOLVEFUNC(i2d_X509) #if OPENSSL_VERSION_MAJOR < 3 - RESOLVEFUNC(SSL_CTX_load_verify_locations) + RESOLVEFUNC(SSL_CTX_load_verify_locations) #else - RESOLVEFUNC(SSL_CTX_load_verify_dir) + RESOLVEFUNC(SSL_CTX_load_verify_dir) #endif // OPENSSL_VERSION_MAJOR - RESOLVEFUNC(i2d_SSL_SESSION) - RESOLVEFUNC(d2i_SSL_SESSION) + RESOLVEFUNC(i2d_SSL_SESSION) + RESOLVEFUNC(d2i_SSL_SESSION) #ifndef OPENSSL_NO_NEXTPROTONEG - RESOLVEFUNC(SSL_select_next_proto) - RESOLVEFUNC(SSL_CTX_set_next_proto_select_cb) - RESOLVEFUNC(SSL_get0_next_proto_negotiated) - RESOLVEFUNC(SSL_set_alpn_protos) - RESOLVEFUNC(SSL_CTX_set_alpn_select_cb) - RESOLVEFUNC(SSL_get0_alpn_selected) + RESOLVEFUNC(SSL_select_next_proto) + RESOLVEFUNC(SSL_CTX_set_next_proto_select_cb) + RESOLVEFUNC(SSL_get0_next_proto_negotiated) + RESOLVEFUNC(SSL_set_alpn_protos) + RESOLVEFUNC(SSL_CTX_set_alpn_select_cb) + RESOLVEFUNC(SSL_get0_alpn_selected) #endif // !OPENSSL_NO_NEXTPROTONEG #if QT_CONFIG(dtls) - RESOLVEFUNC(SSL_CTX_set_cookie_generate_cb) - RESOLVEFUNC(SSL_CTX_set_cookie_verify_cb) - RESOLVEFUNC(DTLS_server_method) - RESOLVEFUNC(DTLS_client_method) + RESOLVEFUNC(SSL_CTX_set_cookie_generate_cb) + RESOLVEFUNC(SSL_CTX_set_cookie_verify_cb) + RESOLVEFUNC(DTLS_server_method) + RESOLVEFUNC(DTLS_client_method) #endif // dtls - RESOLVEFUNC(CRYPTO_malloc) - RESOLVEFUNC(DH_new) - RESOLVEFUNC(DH_free) - RESOLVEFUNC(d2i_DHparams) - RESOLVEFUNC(i2d_DHparams) -#ifndef OPENSSL_NO_DEPRECATED_3_0 - RESOLVEFUNC(DH_check) -#endif // OPENSSL_NO_DEPRECATED_3_0 - RESOLVEFUNC(BN_bin2bn) + RESOLVEFUNC(CRYPTO_malloc) + RESOLVEFUNC(BN_bin2bn) #ifndef OPENSSL_NO_EC - RESOLVEFUNC(EC_KEY_dup) - RESOLVEFUNC(EC_KEY_new_by_curve_name) - RESOLVEFUNC(EC_KEY_free) - RESOLVEFUNC(EC_get_builtin_curves) + RESOLVEFUNC(EC_get_builtin_curves) #endif // OPENSSL_NO_EC - RESOLVEFUNC(PKCS12_parse) - RESOLVEFUNC(d2i_PKCS12_bio) - RESOLVEFUNC(PKCS12_free) + RESOLVEFUNC(PKCS12_parse) + RESOLVEFUNC(d2i_PKCS12_bio) + RESOLVEFUNC(PKCS12_free) + return true; + }(); - symbolsResolved.storeRelease(true); - return true; + return symbolsResolved; } #endif // QT_CONFIG(library) diff --git a/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h b/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h index 1eb6387c23..a93c110b3f 100644 --- a/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h +++ b/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2014 BlackBerry Limited. All rights reserved. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2014 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only /**************************************************************************** ** @@ -221,7 +185,11 @@ QT_BEGIN_NAMESPACE // **************** Static declarations ****************** #endif // !defined QT_LINKED_OPENSSL - +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +typedef uint64_t qssloptions; +#else +typedef unsigned long qssloptions; +#endif // TODO: the following lines previously were a part of 1.1 - specific header. // To reduce the amount of the change, I'm directly copying and pasting the // content of the header here. Later, can be better sorted/split into groups, @@ -232,14 +200,12 @@ const unsigned char * q_ASN1_STRING_get0_data(const ASN1_STRING *x); BIO *q_BIO_new(const BIO_METHOD *a); const BIO_METHOD *q_BIO_s_mem(); -int q_DSA_bits(DSA *a); +void q_AUTHORITY_INFO_ACCESS_free(AUTHORITY_INFO_ACCESS *a); int q_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c); int q_EVP_PKEY_up_ref(EVP_PKEY *a); EVP_PKEY_CTX *q_EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); void q_EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); int q_EVP_PKEY_param_check(EVP_PKEY_CTX *ctx); -int q_EVP_PKEY_base_id(EVP_PKEY *a); -int q_RSA_bits(RSA *a); int q_OPENSSL_sk_num(OPENSSL_STACK *a); void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *)); OPENSSL_STACK *q_OPENSSL_sk_new_null(); @@ -247,7 +213,7 @@ void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data); void q_OPENSSL_sk_free(OPENSSL_STACK *a); void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b); int q_SSL_session_reused(SSL *a); -unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op); +qssloptions q_SSL_CTX_set_options(SSL_CTX *ctx, qssloptions op); int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen); size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen); @@ -257,6 +223,8 @@ const SSL_METHOD *q_TLS_client_method(); const SSL_METHOD *q_TLS_server_method(); ASN1_TIME *q_X509_getm_notBefore(X509 *a); ASN1_TIME *q_X509_getm_notAfter(X509 *a); +void q_ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it); +void q_X509V3_conf_free(CONF_VALUE *val); void q_X509_up_ref(X509 *a); long q_X509_get_version(X509 *a); @@ -265,8 +233,6 @@ void q_X509_STORE_set_verify_cb(X509_STORE *ctx, X509_STORE_CTX_verify_cb verify int q_X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data); void *q_X509_STORE_get_ex_data(X509_STORE *r, int idx); STACK_OF(X509) *q_X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx); -void q_DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); -int q_DH_bits(DH *dh); # define q_SSL_load_error_strings() q_OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL) @@ -281,7 +247,6 @@ int q_DH_bits(DH *dh); | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL) int q_OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); -void q_CRYPTO_free(void *str, const char *file, int line); long q_OpenSSL_version_num(); const char *q_OpenSSL_version(int type); @@ -380,13 +345,6 @@ int q_BN_num_bits(const BIGNUM *a); int q_BN_is_word(BIGNUM *a, BN_ULONG w); BN_ULONG q_BN_mod_word(const BIGNUM *a, BN_ULONG w); -#ifndef OPENSSL_NO_EC -const EC_GROUP* q_EC_KEY_get0_group(const EC_KEY* k); -int q_EC_GROUP_get_degree(const EC_GROUP* g); -#endif // OPENSSL_NO_EC - -DSA *q_DSA_new(); -void q_DSA_free(DSA *a); X509 *q_d2i_X509(X509 **a, const unsigned char **b, long c); char *q_ERR_error_string(unsigned long a, char *b); void q_ERR_error_string_n(unsigned long e, char *buf, size_t len); @@ -417,23 +375,8 @@ const EVP_CIPHER *q_EVP_aes_256_cbc(); #endif // OPENSSL_NO_AES const EVP_MD *q_EVP_sha1(); -int q_EVP_PKEY_assign(EVP_PKEY *a, int b, void *r); -int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b); -int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b); -int q_EVP_PKEY_set1_DH(EVP_PKEY *a, DH *b); -#ifndef OPENSSL_NO_EC -int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b); -#endif - -int q_EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b); void q_EVP_PKEY_free(EVP_PKEY *a); -RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a); -DSA *q_EVP_PKEY_get1_DSA(EVP_PKEY *a); -DH *q_EVP_PKEY_get1_DH(EVP_PKEY *a); -#ifndef OPENSSL_NO_EC -EC_KEY *q_EVP_PKEY_get1_EC_KEY(EVP_PKEY *a); -#endif int q_EVP_PKEY_type(int a); EVP_PKEY *q_EVP_PKEY_new(); int q_i2d_X509(X509 *a, unsigned char **b); @@ -446,36 +389,17 @@ int q_OBJ_obj2txt(char *buf, int buf_len, ASN1_OBJECT *obj, int no_name); int q_OBJ_obj2nid(const ASN1_OBJECT *a); #define q_EVP_get_digestbynid(a) q_EVP_get_digestbyname(q_OBJ_nid2sn(a)) EVP_PKEY *q_PEM_read_bio_PrivateKey(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d); -DSA *q_PEM_read_bio_DSAPrivateKey(BIO *a, DSA **b, pem_password_cb *c, void *d); -RSA *q_PEM_read_bio_RSAPrivateKey(BIO *a, RSA **b, pem_password_cb *c, void *d); - -#ifndef OPENSSL_NO_EC -EC_KEY *q_PEM_read_bio_ECPrivateKey(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); -int q_PEM_write_bio_ECPrivateKey(BIO *a, EC_KEY *b, const EVP_CIPHER *c, unsigned char *d, - int e, pem_password_cb *f, void *g); -EC_KEY *q_PEM_read_bio_EC_PUBKEY(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); -int q_PEM_write_bio_EC_PUBKEY(BIO *a, EC_KEY *b); -#endif // OPENSSL_NO_EC -DH *q_PEM_read_bio_DHparams(BIO *a, DH **b, pem_password_cb *c, void *d); -int q_PEM_write_bio_DSAPrivateKey(BIO *a, DSA *b, const EVP_CIPHER *c, unsigned char *d, - int e, pem_password_cb *f, void *g); -int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned char *d, - int e, pem_password_cb *f, void *g); int q_PEM_write_bio_PrivateKey(BIO *a, EVP_PKEY *b, const EVP_CIPHER *c, unsigned char *d, int e, pem_password_cb *f, void *g); +int q_PEM_write_bio_PrivateKey_traditional(BIO *a, EVP_PKEY *b, const EVP_CIPHER *c, unsigned char *d, + int e, pem_password_cb *f, void *g); EVP_PKEY *q_PEM_read_bio_PUBKEY(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d); -DSA *q_PEM_read_bio_DSA_PUBKEY(BIO *a, DSA **b, pem_password_cb *c, void *d); -RSA *q_PEM_read_bio_RSA_PUBKEY(BIO *a, RSA **b, pem_password_cb *c, void *d); -int q_PEM_write_bio_DSA_PUBKEY(BIO *a, DSA *b); -int q_PEM_write_bio_RSA_PUBKEY(BIO *a, RSA *b); int q_PEM_write_bio_PUBKEY(BIO *a, EVP_PKEY *b); void q_RAND_seed(const void *a, int b); int q_RAND_status(); int q_RAND_bytes(unsigned char *b, int n); -RSA *q_RSA_new(); -void q_RSA_free(RSA *a); int q_SSL_accept(SSL *a); int q_SSL_clear(SSL *a); char *q_SSL_CIPHER_description(const SSL_CIPHER *a, char *b, int c); @@ -497,7 +421,6 @@ long q_SSL_CTX_callback_ctrl(SSL_CTX *, int, GenericCallbackType); int q_SSL_CTX_use_certificate(SSL_CTX *a, X509 *b); int q_SSL_CTX_use_certificate_file(SSL_CTX *a, const char *b, int c); int q_SSL_CTX_use_PrivateKey(SSL_CTX *a, EVP_PKEY *b); -int q_SSL_CTX_use_RSAPrivateKey(SSL_CTX *a, RSA *b); int q_SSL_CTX_use_PrivateKey_file(SSL_CTX *a, const char *b, int c); X509_STORE *q_SSL_CTX_get_cert_store(const SSL_CTX *a); SSL_CONF_CTX *q_SSL_CONF_CTX_new(); @@ -512,7 +435,6 @@ const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a); int q_SSL_version(const SSL *a); int q_SSL_get_error(SSL *a, int b); STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a); -X509 *q_SSL_get_peer_certificate(SSL *a); long q_SSL_get_verify_result(const SSL *a); SSL *q_SSL_new(SSL_CTX *a); SSL_CTX *q_SSL_get_SSL_CTX(SSL *a); @@ -580,23 +502,24 @@ X509 *q_X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); X509_STORE *q_X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx); // Diffie-Hellman support +#ifndef OPENSSL_NO_DEPRECATED_3_0 DH *q_DH_new(); void q_DH_free(DH *dh); +int q_DH_check(DH *dh, int *codes); +void q_DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); + DH *q_d2i_DHparams(DH **a, const unsigned char **pp, long length); int q_i2d_DHparams(DH *a, unsigned char **p); -#ifndef OPENSSL_NO_DEPRECATED_3_0 -int q_DH_check(DH *dh, int *codes); +DH *q_PEM_read_bio_DHparams(BIO *a, DH **b, pem_password_cb *c, void *d); #endif // OPENSSL_NO_DEPRECATED_3_0 BIGNUM *q_BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); #define q_SSL_CTX_set_tmp_dh(ctx, dh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_DH, 0, (char *)dh) +#define q_SSL_CTX_set_dh_auto(ctx, onoff) q_SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL) #ifndef OPENSSL_NO_EC // EC Diffie-Hellman support -EC_KEY *q_EC_KEY_dup(const EC_KEY *src); -EC_KEY *q_EC_KEY_new_by_curve_name(int nid); -void q_EC_KEY_free(EC_KEY *ecdh); #define q_SSL_CTX_set_tmp_ecdh(ctx, ecdh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_ECDH, 0, (char *)ecdh) // EC curves management @@ -625,10 +548,6 @@ void q_GENERAL_NAME_free(GENERAL_NAME *a); #define q_sk_SSL_CIPHER_value(st, i) q_SKM_sk_value(SSL_CIPHER, (st), (i)) #define q_SSL_CTX_add_extra_chain_cert(ctx,x509) \ q_SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509) -#define q_EVP_PKEY_assign_RSA(pkey,rsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\ - (char *)(rsa)) -#define q_EVP_PKEY_assign_DSA(pkey,dsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\ - (char *)(dsa)) #define q_OpenSSL_add_all_algorithms() q_OPENSSL_add_all_algorithms_conf() #if OPENSSL_VERSION_MAJOR < 3 @@ -746,6 +665,9 @@ int q_OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b); void *q_CRYPTO_malloc(size_t num, const char *file, int line); #define q_OPENSSL_malloc(num) q_CRYPTO_malloc(num, "", 0) +void q_CRYPTO_free(void *str, const char *file, int line); +# define q_OPENSSL_free(addr) q_CRYPTO_free(addr, "", 0) +int q_CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len); void q_SSL_set_info_callback(SSL *ssl, void (*cb) (const SSL *ssl, int type, int val)); const char *q_SSL_alert_type_string(int value); @@ -754,6 +676,90 @@ const char *q_SSL_alert_desc_string_long(int value); int q_SSL_CTX_get_security_level(const SSL_CTX *ctx); void q_SSL_CTX_set_security_level(SSL_CTX *ctx, int level); +// Here we have the ones that make difference between OpenSSL pre/post v3: +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +X509 *q_SSL_get1_peer_certificate(SSL *a); +#define q_SSL_get_peer_certificate q_SSL_get1_peer_certificate +int q_EVP_PKEY_get_bits(const EVP_PKEY *pkey); +int q_EVP_PKEY_get_base_id(const EVP_PKEY *pkey); +#define q_EVP_PKEY_base_id q_EVP_PKEY_get_base_id +#else +X509 *q_SSL_get_peer_certificate(SSL *a); +int q_EVP_PKEY_base_id(EVP_PKEY *a); +#endif // OPENSSL_VERSION_MAJOR >= 3 + +#ifndef OPENSSL_NO_DEPRECATED_3_0 + +DSA *q_DSA_new(); +void q_DSA_free(DSA *a); + +RSA *q_RSA_new(); +void q_RSA_free(RSA *a); + +#ifndef OPENSSL_NO_EC + +EC_KEY *q_EC_KEY_dup(const EC_KEY *src); +EC_KEY *q_EC_KEY_new_by_curve_name(int nid); +void q_EC_KEY_free(EC_KEY *ecdh); + +#endif // OPENSSL_NO_EC + +int q_SSL_CTX_use_RSAPrivateKey(SSL_CTX *a, RSA *b); + +DSA *q_PEM_read_bio_DSA_PUBKEY(BIO *a, DSA **b, pem_password_cb *c, void *d); +RSA *q_PEM_read_bio_RSA_PUBKEY(BIO *a, RSA **b, pem_password_cb *c, void *d); + +DSA *q_PEM_read_bio_DSAPrivateKey(BIO *a, DSA **b, pem_password_cb *c, void *d); +RSA *q_PEM_read_bio_RSAPrivateKey(BIO *a, RSA **b, pem_password_cb *c, void *d); + +int q_PEM_write_bio_DSA_PUBKEY(BIO *a, DSA *b); +int q_PEM_write_bio_RSA_PUBKEY(BIO *a, RSA *b); + +int q_PEM_write_bio_DSAPrivateKey(BIO *a, DSA *b, const EVP_CIPHER *c, unsigned char *d, + int e, pem_password_cb *f, void *g); +int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned char *d, + int e, pem_password_cb *f, void *g); + +RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a); +DSA *q_EVP_PKEY_get1_DSA(EVP_PKEY *a); +DH *q_EVP_PKEY_get1_DH(EVP_PKEY *a); + +int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b); +int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b); +int q_EVP_PKEY_set1_DH(EVP_PKEY *a, DH *b); + +int q_DH_bits(DH *dh); +int q_RSA_bits(RSA *a); +int q_DSA_bits(DSA *a); + +int q_EVP_PKEY_assign(EVP_PKEY *a, int b, void *r); +int q_EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b); + +#ifndef OPENSSL_NO_EC + +EC_KEY *q_PEM_read_bio_EC_PUBKEY(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); +EC_KEY *q_PEM_read_bio_ECPrivateKey(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); + +int q_PEM_write_bio_ECPrivateKey(BIO *a, EC_KEY *b, const EVP_CIPHER *c, unsigned char *d, + int e, pem_password_cb *f, void *g); +int q_PEM_write_bio_EC_PUBKEY(BIO *a, EC_KEY *b); + +EC_KEY *q_EVP_PKEY_get1_EC_KEY(EVP_PKEY *a); +int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b); + +const EC_GROUP* q_EC_KEY_get0_group(const EC_KEY* k); +int q_EC_GROUP_get_degree(const EC_GROUP* g); + +#define q_EVP_PKEY_assign_RSA(pkey,rsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\ + (char *)(rsa)) +#define q_EVP_PKEY_assign_DSA(pkey,dsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\ + (char *)(dsa)) + + +#endif // OPENSSL_NO_EC + +#endif // OPENSSL_NO_DEPRECATED_3_0 + QT_END_NAMESPACE #endif diff --git a/src/plugins/tls/openssl/qtls_openssl.cpp b/src/plugins/tls/openssl/qtls_openssl.cpp index 9ed9ab7538..57d09a649b 100644 --- a/src/plugins/tls/openssl/qtls_openssl.cpp +++ b/src/plugins/tls/openssl/qtls_openssl.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qsslsocket_openssl_symbols_p.h" #include "qx509_openssl_p.h" @@ -60,6 +24,8 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + namespace { QSsl::AlertLevel tlsAlertLevel(int value) @@ -83,9 +49,9 @@ QSsl::AlertLevel tlsAlertLevel(int value) QString tlsAlertDescription(int value) { - QString description = QLatin1String(q_SSL_alert_desc_string_long(value)); + QString description = QLatin1StringView(q_SSL_alert_desc_string_long(value)); if (!description.size()) - description = QLatin1String("no description provided"); + description = "no description provided"_L1; return description; } @@ -126,7 +92,7 @@ QSslCertificate findCertificateToFetch(const QList<QSslError> &tlsErrors, bool c if (checkAIA) { const auto extensions = certToFetch.extensions(); for (const auto &ext : extensions) { - if (ext.oid() == QStringLiteral("1.3.6.1.5.5.7.1.1")) // See RFC 4325 + if (ext.oid() == u"1.3.6.1.5.5.7.1.1") // See RFC 4325 return certToFetch; } //The only reason we check this extensions is because an application set trusted @@ -169,9 +135,25 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx) // To retrieve this pointer the X509_STORE_CTX_get_ex_data() function can be // used with the correct index." const auto offset = QTlsBackendOpenSSL::s_indexForSSLExtraData - + TlsCryptographOpenSSL::errorOffsetInExData; - if (SSL *ssl = static_cast<SSL *>(q_X509_STORE_CTX_get_ex_data(ctx, q_SSL_get_ex_data_X509_STORE_CTX_idx()))) + + TlsCryptographOpenSSL::errorOffsetInExData; + if (SSL *ssl = static_cast<SSL *>(q_X509_STORE_CTX_get_ex_data( + ctx, q_SSL_get_ex_data_X509_STORE_CTX_idx()))) { + + // We may be in a renegotiation, check if we are inside a call to SSL_read: + const auto tlsOffset = QTlsBackendOpenSSL::s_indexForSSLExtraData + + TlsCryptographOpenSSL::socketOffsetInExData; + auto tls = static_cast<TlsCryptographOpenSSL *>(q_SSL_get_ex_data(ssl, tlsOffset)); + Q_ASSERT(tls); + if (tls->isInSslRead()) { + // We are in a renegotiation, make a note of this for later. + // We'll check that the certificate is the same as the one we got during + // the initial handshake + tls->setRenegotiated(true); + return 1; + } + errors = ErrorListPtr(q_SSL_get_ex_data(ssl, offset)); + } } if (!errors) { @@ -258,15 +240,22 @@ static unsigned q_ssl_psk_restore_client(SSL *ssl, const char *hint, char *ident Q_ASSERT(tls->d); Q_ASSERT(tls->d->tlsMode() == QSslSocket::SslClientMode); #endif + unsigned retVal = 0; + + // Let developers opt-in to having the normal PSK callback get called for TLS 1.3 + // PSK (which works differently in a few ways, and is called at the start of every connection). + // When they do opt-in we just call the old callback from here. + if (qEnvironmentVariableIsSet("QT_USE_TLS_1_3_PSK")) + retVal = q_ssl_psk_client_callback(ssl, hint, identity, max_identity_len, psk, max_psk_len); + q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback); - return 0; + return retVal; } static int q_ssl_psk_use_session_callback(SSL *ssl, const EVP_MD *md, const unsigned char **id, size_t *idlen, SSL_SESSION **sess) { - Q_UNUSED(ssl); Q_UNUSED(md); Q_UNUSED(id); Q_UNUSED(idlen); @@ -326,7 +315,7 @@ int qt_OCSP_status_server_callback(SSL *ssl, void *ocspRequest) return SSL_TLSEXT_ERR_ALERT_FATAL; std::copy(response.data(), response.data() + response.size(), derCopy); - // We don't check the return value: internally OpenSSL simply assignes the + // We don't check the return value: internally OpenSSL simply assigns the // pointer (it assumes it now owns this memory btw!) and the length. q_SSL_set_tlsext_status_ocsp_resp(ssl, derCopy, response.size()); @@ -472,7 +461,7 @@ bool qt_OCSP_certificate_match(OCSP_SINGLERESP *singleResponse, X509 *peerCert, const QSharedPointer<OCSP_CERTID> guard(recreatedId, q_OCSP_CERTID_free); if (q_OCSP_id_cmp(const_cast<OCSP_CERTID *>(certId), recreatedId)) { - qDebug(lcTlsBackend, "Certificate ID mismatch"); + qCDebug(lcTlsBackend, "Certificate ID mismatch"); return false; } // Bingo! @@ -501,16 +490,16 @@ void TlsCryptographOpenSSL::init(QSslSocket *qObj, QSslSocketPrivate *dObj) handshakeInterrupted = false; fetchAuthorityInformation = false; - caToFetch = QSslCertificate{}; + caToFetch.reset(); } -void TlsCryptographOpenSSL::checkSettingSslContext(QSharedPointer<QSslContext> tlsContext) +void TlsCryptographOpenSSL::checkSettingSslContext(std::shared_ptr<QSslContext> tlsContext) { - if (sslContextPointer.isNull()) - sslContextPointer = tlsContext; + if (!sslContextPointer) + sslContextPointer = std::move(tlsContext); } -QSharedPointer<QSslContext> TlsCryptographOpenSSL::sslContext() const +std::shared_ptr<QSslContext> TlsCryptographOpenSSL::sslContext() const { return sslContextPointer; } @@ -588,7 +577,7 @@ bool TlsCryptographOpenSSL::startHandshake() auto configuration = q->sslConfiguration(); if (!errorsReportedFromCallback) { const auto &peerCertificateChain = configuration.peerCertificateChain(); - for (const auto ¤tError : qAsConst(lastErrors)) { + for (const auto ¤tError : std::as_const(lastErrors)) { emit q->peerVerifyError(QTlsPrivate::X509CertificateOpenSSL::openSSLErrorToQSslError(currentError.code, peerCertificateChain.value(currentError.depth))); if (q->state() != QAbstractSocket::ConnectedState) @@ -708,7 +697,7 @@ bool TlsCryptographOpenSSL::startHandshake() // Translate errors from the error list into QSslErrors. errors.reserve(errors.size() + errorList.size()); - for (const auto &error : qAsConst(errorList)) + for (const auto &error : std::as_const(errorList)) errors << X509CertificateOpenSSL::openSSLErrorToQSslError(error.code, peerCertificateChain.value(error.depth)); if (!errors.isEmpty()) { @@ -760,7 +749,7 @@ void TlsCryptographOpenSSL::enableHandshakeContinuation() void TlsCryptographOpenSSL::cancelCAFetch() { fetchAuthorityInformation = false; - caToFetch = QSslCertificate{}; + caToFetch.reset(); } void TlsCryptographOpenSSL::continueHandshake() @@ -799,7 +788,7 @@ void TlsCryptographOpenSSL::continueHandshake() debugLineClientRandom.append(masterKey.toHex().toUpper()); debugLineClientRandom.append("\n"); - QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys"); + QString sslKeyFile = QDir::tempPath() + "/qt-ssl-keys"_L1; QFile file(sslKeyFile); if (!file.open(QIODevice::Append)) qCWarning(lcTlsBackend) << "could not open file" << sslKeyFile << "for appending"; @@ -815,7 +804,7 @@ void TlsCryptographOpenSSL::continueHandshake() // Cache this SSL session inside the QSslContext if (!(configuration.testSslOption(QSsl::SslOptionDisableSessionSharing))) { if (!sslContextPointer->cacheSession(ssl)) { - sslContextPointer.clear(); // we could not cache the session + sslContextPointer.reset(); // we could not cache the session } else { // Cache the session for permanent usage as well if (!(configuration.testSslOption(QSsl::SslOptionDisableSessionPersistence))) { @@ -1040,7 +1029,25 @@ void TlsCryptographOpenSSL::transmit() break; } // Don't use SSL_pending(). It's very unreliable. + inSslRead = true; readBytes = q_SSL_read(ssl, buffer.reserve(bytesToRead), bytesToRead); + inSslRead = false; + if (renegotiated) { + renegotiated = false; + X509 *x509 = q_SSL_get_peer_certificate(ssl); + const auto peerCertificate = + QTlsPrivate::X509CertificateOpenSSL::certificateFromX509(x509); + // Fail the renegotiate if the certificate has changed, else: continue. + if (peerCertificate != q->peerCertificate()) { + const ScopedBool bg(inSetAndEmitError, true); + setErrorAndEmit( + d, QAbstractSocket::RemoteHostClosedError, + QSslSocket::tr( + "TLS certificate unexpectedly changed during renegotiation!")); + q->abort(); + return; + } + } if (readBytes > 0) { #ifdef QSSLSOCKET_DEBUG qCDebug(lcTlsBackend) << "TlsCryptographOpenSSL::transmit: decrypted" << readBytes << "bytes"; @@ -1127,6 +1134,7 @@ void TlsCryptographOpenSSL::disconnected() Q_ASSERT(d); auto *plainSocket = d->plainTcpSocket(); Q_ASSERT(plainSocket); + d->setEncrypted(false); if (plainSocket->bytesAvailable() <= 0) { destroySslContext(); @@ -1158,10 +1166,13 @@ QSsl::SslProtocol TlsCryptographOpenSSL::sessionProtocol() const const int ver = q_SSL_version(ssl); switch (ver) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case 0x301: return QSsl::TlsV1_0; case 0x302: return QSsl::TlsV1_1; +QT_WARNING_POP case 0x303: return QSsl::TlsV1_2; case 0x304: @@ -1363,7 +1374,7 @@ bool TlsCryptographOpenSSL::initSslContext() if (sslContextPointer->error() != QSslError::NoError) { setErrorAndEmit(d, QAbstractSocket::SslInvalidUserDataError, sslContextPointer->errorString()); - sslContextPointer.clear(); // deletes the QSslContext + sslContextPointer.reset(); return false; } @@ -1491,7 +1502,7 @@ void TlsCryptographOpenSSL::destroySslContext() q_SSL_free(ssl); ssl = nullptr; } - sslContextPointer.clear(); + sslContextPointer.reset(); } void TlsCryptographOpenSSL::storePeerCertificates() @@ -1715,11 +1726,11 @@ unsigned TlsCryptographOpenSSL::pskClientTlsCallback(const char *hint, char *ide return 0; // Copy data back into OpenSSL - const int identityLength = qMin(authenticator.identity().length(), authenticator.maximumIdentityLength()); + const int identityLength = qMin(authenticator.identity().size(), authenticator.maximumIdentityLength()); std::memcpy(identity, authenticator.identity().constData(), identityLength); identity[identityLength] = 0; - const int pskLength = qMin(authenticator.preSharedKey().length(), authenticator.maximumPreSharedKeyLength()); + const int pskLength = qMin(authenticator.preSharedKey().size(), authenticator.maximumPreSharedKeyLength()); std::memcpy(psk, authenticator.preSharedKey().constData(), pskLength); return pskLength; } @@ -1741,11 +1752,21 @@ unsigned TlsCryptographOpenSSL::pskServerTlsCallback(const char *identity, unsig return 0; // Copy data back into OpenSSL - const int pskLength = qMin(authenticator.preSharedKey().length(), authenticator.maximumPreSharedKeyLength()); + const int pskLength = qMin(authenticator.preSharedKey().size(), authenticator.maximumPreSharedKeyLength()); std::memcpy(psk, authenticator.preSharedKey().constData(), pskLength); return pskLength; } +bool TlsCryptographOpenSSL::isInSslRead() const +{ + return inSslRead; +} + +void TlsCryptographOpenSSL::setRenegotiated(bool renegotiated) +{ + this->renegotiated = renegotiated; +} + #ifdef Q_OS_WIN void TlsCryptographOpenSSL::fetchCaRootForCert(const QSslCertificate &cert) @@ -1782,7 +1803,7 @@ void TlsCryptographOpenSSL::caRootLoaded(QSslCertificate cert, QSslCertificate t Q_ASSERT(q); //Done, fetched already: - caToFetch = QSslCertificate{}; + caToFetch.reset(); if (fetchAuthorityInformation) { if (!q->sslConfiguration().caCertificates().contains(trustedRoot)) diff --git a/src/plugins/tls/openssl/qtls_openssl_p.h b/src/plugins/tls/openssl/qtls_openssl_p.h index 48c9223f99..65d21a395b 100644 --- a/src/plugins/tls/openssl/qtls_openssl_p.h +++ b/src/plugins/tls/openssl/qtls_openssl_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLS_OPENSSL_P_H #define QTLS_OPENSSL_P_H @@ -80,8 +44,8 @@ public: ~TlsCryptographOpenSSL(); void init(QSslSocket *qObj, QSslSocketPrivate *dObj) override; - void checkSettingSslContext(QSharedPointer<QSslContext> tlsContext) override; - QSharedPointer<QSslContext> sslContext() const override; + void checkSettingSslContext(std::shared_ptr<QSslContext> tlsContext) override; + std::shared_ptr<QSslContext> sslContext() const override; QList<QSslError> tlsErrors() const override; @@ -121,6 +85,9 @@ public: unsigned pskServerTlsCallback(const char *identity, unsigned char *psk, unsigned max_psk_len); + bool isInSslRead() const; + void setRenegotiated(bool renegotiated); + #ifdef Q_OS_WIN void fetchCaRootForCert(const QSslCertificate &cert); void caRootLoaded(QSslCertificate certificate, QSslCertificate trustedRoot); @@ -133,7 +100,7 @@ private: bool initSslContext(); void destroySslContext(); - QSharedPointer<QSslContext> sslContextPointer; + std::shared_ptr<QSslContext> sslContextPointer; SSL *ssl = nullptr; // TLSTODO: RAII. QList<QSslErrorEntry> errorList; @@ -144,7 +111,7 @@ private: QList<QOcspResponse> ocspResponses; - // This decription will go to setErrorAndEmit(SslHandshakeError, ocspErrorDescription) + // This description will go to setErrorAndEmit(SslHandshakeError, ocspErrorDescription) QString ocspErrorDescription; // These will go to sslErrors() QList<QSslError> ocspErrors; @@ -153,13 +120,16 @@ private: bool handshakeInterrupted = false; bool fetchAuthorityInformation = false; - QSslCertificate caToFetch; + std::optional<QSslCertificate> caToFetch; bool inSetAndEmitError = false; bool pendingFatalAlert = false; bool errorsReportedFromCallback = false; bool shutdown = false; + + bool inSslRead = false; + bool renegotiated = false; }; } // namespace QTlsPrivate diff --git a/src/plugins/tls/openssl/qtlsbackend_openssl.cpp b/src/plugins/tls/openssl/qtlsbackend_openssl.cpp index 544ce1bcef..d73515724b 100644 --- a/src/plugins/tls/openssl/qtlsbackend_openssl.cpp +++ b/src/plugins/tls/openssl/qtlsbackend_openssl.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qsslsocket_openssl_symbols_p.h" #include "qtlsbackend_openssl_p.h" @@ -53,10 +17,11 @@ #include <QtNetwork/qssl.h> #include <QtCore/qdir.h> -#include <QtCore/qdiriterator.h> +#include <QtCore/qdirlisting.h> #include <QtCore/qlist.h> #include <QtCore/qmutex.h> #include <QtCore/qscopeguard.h> +#include <QtCore/qset.h> #include "qopenssl_p.h" @@ -64,9 +29,15 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(lcTlsBackend, "qt.tlsbackend.ossl"); +using namespace Qt::StringLiterals; -Q_GLOBAL_STATIC(QRecursiveMutex, qt_opensslInitMutex) +#if defined(Q_OS_WIN) || defined(Q_OS_MACOS) +constexpr auto DefaultWarningLevel = QtCriticalMsg; +#else +constexpr auto DefaultWarningLevel = QtDebugMsg; +#endif + +Q_LOGGING_CATEGORY(lcTlsBackend, "qt.tlsbackend.ossl", DefaultWarningLevel); static void q_loadCiphersForConnection(SSL *connection, QList<QSslCipher> &ciphers, QList<QSslCipher> &defaultCiphers) @@ -79,9 +50,9 @@ static void q_loadCiphersForConnection(SSL *connection, QList<QSslCipher> &ciphe const auto ciph = QTlsBackendOpenSSL::qt_OpenSSL_cipher_to_QSslCipher(cipher); if (!ciph.isNull()) { // Unconditionally exclude ADH and AECDH ciphers since they offer no MITM protection - if (!ciph.name().toLower().startsWith(QLatin1String("adh")) && - !ciph.name().toLower().startsWith(QLatin1String("exp-adh")) && - !ciph.name().toLower().startsWith(QLatin1String("aecdh"))) { + if (!ciph.name().toLower().startsWith("adh"_L1) && + !ciph.name().toLower().startsWith("exp-adh"_L1) && + !ciph.name().toLower().startsWith("aecdh"_L1)) { ciphers << ciph; if (ciph.usedBits() >= 128) @@ -92,8 +63,6 @@ static void q_loadCiphersForConnection(SSL *connection, QList<QSslCipher> &ciphe } } -bool QTlsBackendOpenSSL::s_libraryLoaded = false; -bool QTlsBackendOpenSSL::s_loadedCiphersAndCerts = false; int QTlsBackendOpenSSL::s_indexForSSLExtraData = -1; QString QTlsBackendOpenSSL::getErrorsFromOpenSsl() @@ -103,9 +72,9 @@ QString QTlsBackendOpenSSL::getErrorsFromOpenSsl() unsigned long errNum; while ((errNum = q_ERR_get_error())) { if (!errorString.isEmpty()) - errorString.append(QLatin1String(", ")); + errorString.append(", "_L1); q_ERR_error_string_n(errNum, buf, sizeof buf); - errorString.append(QString::fromLatin1(buf)); // error is ascii according to man ERR_error_string + errorString.append(QLatin1StringView(buf)); // error is ascii according to man ERR_error_string } return errorString; } @@ -119,18 +88,16 @@ void QTlsBackendOpenSSL::logAndClearErrorQueue() void QTlsBackendOpenSSL::clearErrorQueue() { - const auto errs = getErrorsFromOpenSsl(); - Q_UNUSED(errs); + while (q_ERR_get_error()) + ; } bool QTlsBackendOpenSSL::ensureLibraryLoaded() { - if (!q_resolveOpenSslSymbols()) - return false; - - const QMutexLocker locker(qt_opensslInitMutex()); + static bool libraryLoaded = []() { + if (!q_resolveOpenSslSymbols()) + return false; - if (!s_libraryLoaded) { // Initialize OpenSSL. if (q_OPENSSL_init_ssl(0, nullptr) != 1) return false; @@ -152,10 +119,10 @@ bool QTlsBackendOpenSSL::ensureLibraryLoaded() return false; } - s_libraryLoaded = true; - } + return true; + }(); - return true; + return libraryLoaded; } QString QTlsBackendOpenSSL::backendName() const @@ -208,11 +175,24 @@ void QTlsBackendOpenSSL::ensureInitialized() const void QTlsBackendOpenSSL::ensureCiphersAndCertsLoaded() const { - const QMutexLocker locker(qt_opensslInitMutex()); + Q_CONSTINIT static bool initializationStarted = false; + Q_CONSTINIT static QAtomicInt initialized = Q_BASIC_ATOMIC_INITIALIZER(0); + Q_CONSTINIT static QRecursiveMutex initMutex; + + if (initialized.loadAcquire()) + return; - if (s_loadedCiphersAndCerts) + const QMutexLocker locker(&initMutex); + + if (initializationStarted || initialized.loadAcquire()) return; - s_loadedCiphersAndCerts = true; + + // Indicate that the initialization has already started in the current + // thread in case of recursive calls. The atomic variable cannot be used + // for this because it is checked without holding the init mutex. + initializationStarted = true; + + auto guard = qScopeGuard([] { initialized.storeRelease(1); }); resetDefaultCiphers(); resetDefaultEllipticCurves(); @@ -223,12 +203,12 @@ void QTlsBackendOpenSSL::ensureCiphersAndCertsLoaded() const QSslSocketPrivate::setRootCertOnDemandLoadingSupported(true); #elif defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there) - QList<QByteArray> dirs = QSslSocketPrivate::unixRootCertDirectories(); - QStringList symLinkFilter; - symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]"); - for (int a = 0; a < dirs.count(); ++a) { - QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files); - if (iterator.hasNext()) { + const QList<QByteArray> dirs = QSslSocketPrivate::unixRootCertDirectories(); + const QStringList symLinkFilter{ + u"[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]"_s}; + for (const auto &dir : dirs) { + QDirListing dirList(QString::fromLatin1(dir), symLinkFilter, QDir::Files); + if (dirList.cbegin() != dirList.cend()) { // Not empty QSslSocketPrivate::setRootCertOnDemandLoadingSupported(true); break; } @@ -291,10 +271,13 @@ QList<QSsl::SslProtocol> QTlsBackendOpenSSL::supportedProtocols() const protocols << QSsl::AnyProtocol; protocols << QSsl::SecureProtocols; +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED protocols << QSsl::TlsV1_0; protocols << QSsl::TlsV1_0OrLater; protocols << QSsl::TlsV1_1; protocols << QSsl::TlsV1_1OrLater; +QT_WARNING_POP protocols << QSsl::TlsV1_2; protocols << QSsl::TlsV1_2OrLater; @@ -304,8 +287,11 @@ QList<QSsl::SslProtocol> QTlsBackendOpenSSL::supportedProtocols() const #endif // TLS1_3_VERSION #if QT_CONFIG(dtls) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED protocols << QSsl::DtlsV1_0; protocols << QSsl::DtlsV1_0OrLater; +QT_WARNING_POP protocols << QSsl::DtlsV1_2; protocols << QSsl::DtlsV1_2OrLater; #endif // dtls @@ -318,8 +304,12 @@ QList<QSsl::SupportedFeature> QTlsBackendOpenSSL::supportedFeatures() const QList<QSsl::SupportedFeature> features; features << QSsl::SupportedFeature::CertificateVerification; + +#if !defined(OPENSSL_NO_TLSEXT) features << QSsl::SupportedFeature::ClientSideAlpn; features << QSsl::SupportedFeature::ServerSideAlpn; +#endif // !OPENSSL_NO_TLSEXT + features << QSsl::SupportedFeature::Ocsp; features << QSsl::SupportedFeature::Psk; features << QSsl::SupportedFeature::SessionTicket; @@ -357,8 +347,7 @@ QTlsPrivate::X509Certificate *QTlsBackendOpenSSL::createCertificate() const namespace QTlsPrivate { -// TLSTODO: remove. -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) +#ifdef Q_OS_ANDROID QList<QByteArray> fetchSslCertificateData(); #endif @@ -374,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) { @@ -388,50 +379,30 @@ QList<QSslCertificate> systemCaCertificates() } CertCloseStore(hSystemStore, 0); } +#elif defined(Q_OS_ANDROID) + const QList<QByteArray> certData = fetchSslCertificateData(); + for (auto certDatum : certData) + systemCerts.append(QSslCertificate::fromData(certDatum, QSsl::Der)); #elif defined(Q_OS_UNIX) - QSet<QString> certFiles; - QDir currentDir; - QStringList nameFilters; - QList<QByteArray> directories; - QSsl::EncodingFormat platformEncodingFormat; -# ifndef Q_OS_ANDROID - directories = QSslSocketPrivate::unixRootCertDirectories(); - nameFilters << QLatin1String("*.pem") << QLatin1String("*.crt"); - platformEncodingFormat = QSsl::Pem; -# else - // Q_OS_ANDROID - QByteArray ministroPath = qgetenv("MINISTRO_SSL_CERTS_PATH"); // Set by Ministro - directories << ministroPath; - nameFilters << QLatin1String("*.der"); - platformEncodingFormat = QSsl::Der; -# ifndef Q_OS_ANDROID_EMBEDDED - if (ministroPath.isEmpty()) { - QList<QByteArray> certificateData = fetchSslCertificateData(); - for (int i = 0; i < certificateData.size(); ++i) { - systemCerts.append(QSslCertificate::fromData(certificateData.at(i), QSsl::Der)); - } - } else -# endif //Q_OS_ANDROID_EMBEDDED -# endif //Q_OS_ANDROID { - currentDir.setNameFilters(nameFilters); - for (int a = 0; a < directories.count(); a++) { - currentDir.setPath(QLatin1String(directories.at(a))); - QDirIterator it(currentDir); - while (it.hasNext()) { - it.next(); + const QList<QByteArray> directories = QSslSocketPrivate::unixRootCertDirectories(); + QSet<QString> certFiles = { + QStringLiteral("/etc/pki/tls/certs/ca-bundle.crt"), // Fedora, Mandriva + QStringLiteral("/usr/local/share/certs/ca-root-nss.crt") // FreeBSD's ca_root_nss + }; + QDir currentDir; + currentDir.setNameFilters(QStringList{QStringLiteral("*.pem"), QStringLiteral("*.crt")}); + for (const auto &directory : directories) { + currentDir.setPath(QLatin1StringView(directory)); + for (const auto &dirEntry : QDirListing(currentDir)) { // use canonical path here to not load the same certificate twice if symlinked - certFiles.insert(it.fileInfo().canonicalFilePath()); + certFiles.insert(dirEntry.canonicalFilePath()); } } - for (const QString& file : qAsConst(certFiles)) - systemCerts.append(QSslCertificate::fromPath(file, platformEncodingFormat)); -# ifndef Q_OS_ANDROID - systemCerts.append(QSslCertificate::fromPath(QLatin1String("/etc/pki/tls/certs/ca-bundle.crt"), QSsl::Pem)); // Fedora, Mandriva - systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/local/share/certs/ca-root-nss.crt"), QSsl::Pem)); // FreeBSD's ca_root_nss -# endif + for (const QString& file : std::as_const(certFiles)) + systemCerts.append(QSslCertificate::fromPath(file, QSsl::Pem)); } -#endif +#endif // platform #ifdef QSSLSOCKET_DEBUG qCDebug(lcTlsBackend) << "systemCaCertificates retrieval time " << timer.elapsed() << "ms"; qCDebug(lcTlsBackend) << "imported " << systemCerts.count() << " certificates"; @@ -636,3 +607,5 @@ void QTlsBackendOpenSSL::forceAutotestSecurityLevel() } QT_END_NAMESPACE + +#include "moc_qtlsbackend_openssl_p.cpp" diff --git a/src/plugins/tls/openssl/qtlsbackend_openssl_p.h b/src/plugins/tls/openssl/qtlsbackend_openssl_p.h index 93b6442a59..b9f1f95df0 100644 --- a/src/plugins/tls/openssl/qtlsbackend_openssl_p.h +++ b/src/plugins/tls/openssl/qtlsbackend_openssl_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLSBACKEND_OPENSSL_P_H #define QTLSBACKEND_OPENSSL_P_H @@ -77,16 +41,13 @@ public: static void logAndClearErrorQueue(); static void clearErrorQueue(); - static bool ensureLibraryLoaded(); // Index used in SSL_get_ex_data to get the matching TlsCryptographerOpenSSL: - static bool s_libraryLoaded; - static bool s_loadedCiphersAndCerts; static int s_indexForSSLExtraData; static QString msgErrorsDuringHandshake(); static QSslCipher qt_OpenSSL_cipher_to_QSslCipher(const SSL_CIPHER *cipher); private: - + static bool ensureLibraryLoaded(); QString backendName() const override; bool isValid() const override; long tlsLibraryVersionNumber() const override; @@ -134,6 +95,8 @@ private: void forceAutotestSecurityLevel() override; }; +Q_DECLARE_LOGGING_CATEGORY(lcTlsBackend) + QT_END_NAMESPACE #endif // QTLSBACKEND_OPENSSL_P_H diff --git a/src/plugins/tls/openssl/qtlskey_openssl.cpp b/src/plugins/tls/openssl/qtlskey_openssl.cpp index 5333623d70..294fc2ffcd 100644 --- a/src/plugins/tls/openssl/qtlskey_openssl.cpp +++ b/src/plugins/tls/openssl/qtlskey_openssl.cpp @@ -1,43 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qsslsocket_openssl_symbols_p.h" +#include "qtlsbackend_openssl_p.h" #include "qtlskey_openssl_p.h" #include <QtNetwork/private/qsslkey_p.h> @@ -84,6 +49,16 @@ void TlsKeyOpenSSL::decodePem(KeyType type, KeyAlgorithm algorithm, const QByteA void *phrase = const_cast<char *>(passPhrase.data()); +#ifdef OPENSSL_NO_DEPRECATED_3_0 + if (type == QSsl::PublicKey) + genericKey = q_PEM_read_bio_PUBKEY(bio, nullptr, nullptr, phrase); + else + genericKey = q_PEM_read_bio_PrivateKey(bio, nullptr, nullptr, phrase); + keyIsNull = !genericKey; + if (keyIsNull) + QTlsBackendOpenSSL::logAndClearErrorQueue(); +#else + if (algorithm == QSsl::Rsa) { RSA *result = (type == QSsl::PublicKey) ? q_PEM_read_bio_RSA_PUBKEY(bio, &rsa, nullptr, phrase) @@ -112,8 +87,10 @@ void TlsKeyOpenSSL::decodePem(KeyType type, KeyAlgorithm algorithm, const QByteA : q_PEM_read_bio_ECPrivateKey(bio, &ec, nullptr, phrase); if (ec && ec == result) keyIsNull = false; -#endif +#endif // OPENSSL_NO_EC } + +#endif // OPENSSL_NO_DEPRECATED_3_0 } QByteArray TlsKeyOpenSSL::derFromPem(const QByteArray &pem, QMap<QByteArray, QByteArray> *headers) const @@ -124,19 +101,19 @@ QByteArray TlsKeyOpenSSL::derFromPem(const QByteArray &pem, QMap<QByteArray, QBy QByteArray der(pem); int headerIndex = der.indexOf(header); - int footerIndex = der.indexOf(footer, headerIndex + header.length()); + int footerIndex = der.indexOf(footer, headerIndex + header.size()); if (type() != QSsl::PublicKey) { if (headerIndex == -1 || footerIndex == -1) { header = pkcs8Header(true); footer = pkcs8Footer(true); headerIndex = der.indexOf(header); - footerIndex = der.indexOf(footer, headerIndex + header.length()); + footerIndex = der.indexOf(footer, headerIndex + header.size()); } if (headerIndex == -1 || footerIndex == -1) { header = pkcs8Header(false); footer = pkcs8Footer(false); headerIndex = der.indexOf(header); - footerIndex = der.indexOf(footer, headerIndex + header.length()); + footerIndex = der.indexOf(footer, headerIndex + header.size()); } } if (headerIndex == -1 || footerIndex == -1) @@ -147,7 +124,7 @@ QByteArray TlsKeyOpenSSL::derFromPem(const QByteArray &pem, QMap<QByteArray, QBy if (der.contains("Proc-Type:")) { // taken from QHttpNetworkReplyPrivate::parseHeader int i = 0; - while (i < der.count()) { + while (i < der.size()) { int j = der.indexOf(':', i); // field-name if (j == -1) break; @@ -166,7 +143,7 @@ QByteArray TlsKeyOpenSSL::derFromPem(const QByteArray &pem, QMap<QByteArray, QBy int length = i -(hasCR ? 1: 0) - j; value += der.mid(j, length).trimmed(); j = ++i; - } while (i < der.count() && (der.at(i) == ' ' || der.at(i) == '\t')); + } while (i < der.size() && (der.at(i) == ' ' || der.at(i) == '\t')); if (i == -1) break; // something is wrong @@ -182,6 +159,7 @@ void TlsKeyOpenSSL::clear(bool deep) { keyIsNull = true; +#ifndef OPENSSL_NO_DEPRECATED_3_0 if (algorithm() == QSsl::Rsa && rsa) { if (deep) q_RSA_free(rsa); @@ -204,18 +182,30 @@ void TlsKeyOpenSSL::clear(bool deep) ec = nullptr; } #endif +#endif // OPENSSL_NO_DEPRECATED_3_0 + if (algorithm() == QSsl::Opaque && opaque) { if (deep) q_EVP_PKEY_free(opaque); opaque = nullptr; } + + if (genericKey) { + // None of the above cleared it. genericKey is either + // initialised by PEM read operation, or from X509, and + // we are the owners and not sharing. So we free it. + q_EVP_PKEY_free(genericKey); + genericKey = nullptr; + } } Qt::HANDLE TlsKeyOpenSSL::handle() const { - switch (keyAlgorithm) { - case QSsl::Opaque: + if (keyAlgorithm == QSsl::Opaque) return Qt::HANDLE(opaque); + +#ifndef OPENSSL_NO_DEPRECATED_3_0 + switch (keyAlgorithm) { case QSsl::Rsa: return Qt::HANDLE(rsa); case QSsl::Dsa: @@ -229,6 +219,11 @@ Qt::HANDLE TlsKeyOpenSSL::handle() const default: return Qt::HANDLE(nullptr); } +#else + qCWarning(lcTlsBackend, + "This version of OpenSSL disabled direct manipulation with RSA/DSA/DH/EC_KEY structures, consider using QSsl::Opaque instead."); + return Qt::HANDLE(genericKey); +#endif } int TlsKeyOpenSSL::length() const @@ -236,6 +231,7 @@ int TlsKeyOpenSSL::length() const if (isNull() || algorithm() == QSsl::Opaque) return -1; +#ifndef OPENSSL_NO_DEPRECATED_3_0 switch (algorithm()) { case QSsl::Rsa: return q_RSA_bits(rsa); @@ -250,6 +246,10 @@ int TlsKeyOpenSSL::length() const default: return -1; } +#else // OPENSSL_NO_DEPRECATED_3_0 + Q_ASSERT(genericKey); + return q_EVP_PKEY_get_bits(genericKey); +#endif // OPENSSL_NO_DEPRECATED_3_0 } QByteArray TlsKeyOpenSSL::toPem(const QByteArray &passPhrase) const @@ -272,54 +272,61 @@ QByteArray TlsKeyOpenSSL::toPem(const QByteArray &passPhrase) const const auto bioRaii = qScopeGuard([bio]{q_BIO_free(bio);}); - bool fail = false; +#ifndef OPENSSL_NO_DEPRECATED_3_0 + +#define write_pubkey(alg, key) q_PEM_write_bio_##alg##_PUBKEY(bio, key) +#define write_privatekey(alg, key) \ + q_PEM_write_bio_##alg##PrivateKey(bio, key, cipher, (uchar *)passPhrase.data(), \ + passPhrase.size(), nullptr, nullptr) + +#else + +#define write_pubkey(alg, key) q_PEM_write_bio_PUBKEY(bio, genericKey) +#define write_privatekey(alg, key) \ + q_PEM_write_bio_PrivateKey_traditional(bio, genericKey, cipher, (uchar *)passPhrase.data(), passPhrase.size(), nullptr, nullptr) + +#endif // OPENSSL_NO_DEPRECATED_3_0 + bool fail = false; if (algorithm() == QSsl::Rsa) { if (type() == QSsl::PublicKey) { - if (!q_PEM_write_bio_RSA_PUBKEY(bio, rsa)) - fail = true; - } else { - if (!q_PEM_write_bio_RSAPrivateKey( - bio, rsa, cipher, (uchar *)passPhrase.data(), - passPhrase.size(), nullptr, nullptr)) { + if (!write_pubkey(RSA, rsa)) fail = true; - } + } else if (!write_privatekey(RSA, rsa)) { + fail = true; } } else if (algorithm() == QSsl::Dsa) { if (type() == QSsl::PublicKey) { - if (!q_PEM_write_bio_DSA_PUBKEY(bio, dsa)) - fail = true; - } else { - if (!q_PEM_write_bio_DSAPrivateKey( - bio, dsa, cipher, (uchar *)passPhrase.data(), - passPhrase.size(), nullptr, nullptr)) { + if (!write_pubkey(DSA, dsa)) fail = true; - } + } else if (!write_privatekey(DSA, dsa)) { + fail = true; } } else if (algorithm() == QSsl::Dh) { +#ifdef OPENSSL_NO_DEPRECATED_3_0 + EVP_PKEY *result = genericKey; +#else EVP_PKEY *result = q_EVP_PKEY_new(); + const auto guard = qScopeGuard([result]{if (result) q_EVP_PKEY_free(result);}); if (!result || !q_EVP_PKEY_set1_DH(result, dh)) { fail = true; - } else if (type() == QSsl::PublicKey) { + } else +#endif + if (type() == QSsl::PublicKey) { if (!q_PEM_write_bio_PUBKEY(bio, result)) fail = true; - } else if (!q_PEM_write_bio_PrivateKey( - bio, result, cipher, (uchar *)passPhrase.data(), - passPhrase.size(), nullptr, nullptr)) { + } else if (!q_PEM_write_bio_PrivateKey(bio, result, cipher, (uchar *)passPhrase.data(), + passPhrase.size(), nullptr, nullptr)) { fail = true; } - q_EVP_PKEY_free(result); #ifndef OPENSSL_NO_EC } else if (algorithm() == QSsl::Ec) { if (type() == QSsl::PublicKey) { - if (!q_PEM_write_bio_EC_PUBKEY(bio, ec)) + if (!write_pubkey(EC, ec)) fail = true; } else { - if (!q_PEM_write_bio_ECPrivateKey( - bio, ec, cipher, (uchar *)passPhrase.data(), - passPhrase.size(), nullptr, nullptr)) { + if (!write_privatekey(EC, ec)) fail = true; - } } #endif } else { @@ -332,6 +339,8 @@ QByteArray TlsKeyOpenSSL::toPem(const QByteArray &passPhrase) const const long size = q_BIO_get_mem_data(bio, &data); if (size > 0 && data) pem = QByteArray(data, size); + } else { + QTlsBackendOpenSSL::logAndClearErrorQueue(); } return pem; @@ -356,34 +365,37 @@ bool TlsKeyOpenSSL::fromEVP_PKEY(EVP_PKEY *pkey) if (!pkey) return false; +#ifndef OPENSSL_NO_DEPRECATED_3_0 +#define get_key(key, alg) key = q_EVP_PKEY_get1_##alg(pkey) +#else +#define get_key(key, alg) q_EVP_PKEY_up_ref(pkey); genericKey = pkey; +#endif + switch (q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey))) { case EVP_PKEY_RSA: keyIsNull = false; keyAlgorithm = QSsl::Rsa; keyType = QSsl::PrivateKey; - rsa = q_EVP_PKEY_get1_RSA(pkey); - + get_key(rsa, RSA); return true; case EVP_PKEY_DSA: keyIsNull = false; keyAlgorithm = QSsl::Dsa; keyType = QSsl::PrivateKey; - dsa = q_EVP_PKEY_get1_DSA(pkey); - + get_key(dsa, DSA); return true; case EVP_PKEY_DH: keyIsNull = false; keyAlgorithm = QSsl::Dh; keyType = QSsl::PrivateKey; - dh = q_EVP_PKEY_get1_DH(pkey); + get_key(dh, DH); return true; #ifndef OPENSSL_NO_EC case EVP_PKEY_EC: keyIsNull = false; keyAlgorithm = QSsl::Ec; keyType = QSsl::PrivateKey; - ec = q_EVP_PKEY_get1_EC_KEY(pkey); - + get_key(ec, EC_KEY); return true; #endif default:; @@ -437,7 +449,12 @@ QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, EVP_CIPHER_CTX *ctx = q_EVP_CIPHER_CTX_new(); q_EVP_CIPHER_CTX_reset(ctx); - q_EVP_CipherInit(ctx, type, nullptr, nullptr, enc); + if (q_EVP_CipherInit(ctx, type, nullptr, nullptr, enc) != 1) { + q_EVP_CIPHER_CTX_free(ctx); + QTlsBackendOpenSSL::logAndClearErrorQueue(); + return {}; + } + q_EVP_CIPHER_CTX_set_key_length(ctx, key.size()); if (cipher == Cipher::Rc2Cbc) q_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), nullptr); @@ -478,21 +495,31 @@ TlsKeyOpenSSL *TlsKeyOpenSSL::publicKeyFromX509(X509 *x) tlsKey->keyType = QSsl::PublicKey; +#ifndef OPENSSL_NO_DEPRECATED_3_0 + +#define get_pubkey(keyName, alg) tlsKey->keyName = q_EVP_PKEY_get1_##alg(pkey) + +#else + +#define get_pubkey(a, b) tlsKey->genericKey = pkey + +#endif + EVP_PKEY *pkey = q_X509_get_pubkey(x); Q_ASSERT(pkey); const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey)); if (keyType == EVP_PKEY_RSA) { - tlsKey->rsa = q_EVP_PKEY_get1_RSA(pkey); + get_pubkey(rsa, RSA); tlsKey->keyAlgorithm = QSsl::Rsa; tlsKey->keyIsNull = false; } else if (keyType == EVP_PKEY_DSA) { - tlsKey->dsa = q_EVP_PKEY_get1_DSA(pkey); + get_pubkey(dsa, DSA); tlsKey->keyAlgorithm = QSsl::Dsa; tlsKey->keyIsNull = false; #ifndef OPENSSL_NO_EC } else if (keyType == EVP_PKEY_EC) { - tlsKey->ec = q_EVP_PKEY_get1_EC_KEY(pkey); + get_pubkey(ec, EC_KEY); tlsKey->keyAlgorithm = QSsl::Ec; tlsKey->keyIsNull = false; #endif @@ -502,7 +529,10 @@ TlsKeyOpenSSL *TlsKeyOpenSSL::publicKeyFromX509(X509 *x) // error? (key is null) } +#ifndef OPENSSL_NO_DEPRECATED_3_0 q_EVP_PKEY_free(pkey); +#endif + return keyRaii.release(); } diff --git a/src/plugins/tls/openssl/qtlskey_openssl_p.h b/src/plugins/tls/openssl/qtlskey_openssl_p.h index 815770112f..4ee16ffc29 100644 --- a/src/plugins/tls/openssl/qtlskey_openssl_p.h +++ b/src/plugins/tls/openssl/qtlskey_openssl_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLSKEY_OPENSSL_H #define QTLSKEY_OPENSSL_H @@ -67,6 +31,14 @@ #include <openssl/dsa.h> #include <openssl/dh.h> +#ifdef OPENSSL_NO_DEPRECATED_3_0 +typedef struct evp_pkey_st EVP_PKEY; +typedef struct dsa_st DSA; +typedef struct rsa_st RSA; +typedef struct dh_st DH; +typedef struct ec_key_st EC_KEY; +#endif // OPENSSL_NO_DEPRECATED_3_0 + QT_BEGIN_NAMESPACE QT_REQUIRE_CONFIG(ssl); @@ -115,6 +87,7 @@ public: #ifndef OPENSSL_NO_EC EC_KEY *ec; #endif + EVP_PKEY *genericKey; }; bool fromEVP_PKEY(EVP_PKEY *pkey); diff --git a/src/plugins/tls/openssl/qwindowscarootfetcher.cpp b/src/plugins/tls/openssl/qwindowscarootfetcher.cpp index 45ecbce258..a18aae0b71 100644 --- a/src/plugins/tls/openssl/qwindowscarootfetcher.cpp +++ b/src/plugins/tls/openssl/qwindowscarootfetcher.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qwindowscarootfetcher_p.h" #include "qx509_openssl_p.h" @@ -84,7 +48,7 @@ const QList<QSslCertificate> buildVerifiedChain(const QList<QSslCertificate> &ca // by setting custom CA certificates. We convert wincrypt's // structures in QSslCertificate and give OpenSSL the second // chance to verify the now (apparently) complete chain. - // In addition, wincrypt gives us a benifit of some checks + // In addition, wincrypt gives us a benefit of some checks // we don't have in OpenSSL back-end. Q_ASSERT(chainContext); @@ -281,3 +245,5 @@ QHCertStorePointer QWindowsCaRootFetcher::createAdditionalStore() const } QT_END_NAMESPACE + +#include "moc_qwindowscarootfetcher_p.cpp" diff --git a/src/plugins/tls/openssl/qwindowscarootfetcher_p.h b/src/plugins/tls/openssl/qwindowscarootfetcher_p.h index ed649b0936..715fd19945 100644 --- a/src/plugins/tls/openssl/qwindowscarootfetcher_p.h +++ b/src/plugins/tls/openssl/qwindowscarootfetcher_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QWINDOWSCAROOTFETCHER_P_H #define QWINDOWSCAROOTFETCHER_P_H diff --git a/src/plugins/tls/openssl/qx509_openssl.cpp b/src/plugins/tls/openssl/qx509_openssl.cpp index bf52c9345c..0cd3749f88 100644 --- a/src/plugins/tls/openssl/qx509_openssl.cpp +++ b/src/plugins/tls/openssl/qx509_openssl.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qsslsocket_openssl_symbols_p.h" #include "qtlsbackend_openssl_p.h" @@ -48,15 +12,18 @@ #include <QtNetwork/qsslsocket.h> #include <QtNetwork/qhostaddress.h> -#include <QtCore/qvarlengtharray.h> -#include <QtCore/qscopeguard.h> -#include <QtCore/qdatetime.h> -#include <QtCore/qiodevice.h> #include <QtCore/qendian.h> +#include <QtCore/qdatetime.h> #include <QtCore/qhash.h> +#include <QtCore/qiodevice.h> +#include <QtCore/qscopeguard.h> +#include <QtCore/qtimezone.h> +#include <QtCore/qvarlengtharray.h> QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + namespace QTlsPrivate { namespace { @@ -111,7 +78,7 @@ QDateTime dateTimeFromASN1(const ASN1_TIME *aTime) if (q_ASN1_TIME_to_tm(aTime, &lTime)) { QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday); QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec); - result = QDateTime(resDate, resTime, Qt::UTC); + result = QDateTime(resDate, resTime, QTimeZone::UTC); } return result; @@ -197,10 +164,27 @@ QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext) } void *ext_internal = q_X509V3_EXT_d2i(ext); + if (!ext_internal) + return {}; + + const auto extCleaner = qScopeGuard([meth, ext_internal]{ + Q_ASSERT(ext_internal && meth); + + if (meth->it) + q_ASN1_item_free(static_cast<ASN1_VALUE *>(ext_internal), ASN1_ITEM_ptr(meth->it)); + else if (meth->ext_free) + meth->ext_free(ext_internal); + else + qCWarning(lcTlsBackend, "No method to free an unknown extension, a potential memory leak?"); + }); // If this extension can be converted - if (meth->i2v && ext_internal) { + if (meth->i2v) { STACK_OF(CONF_VALUE) *val = meth->i2v(meth, ext_internal, nullptr); + const auto stackCleaner = qScopeGuard([val]{ + if (val) + q_OPENSSL_sk_pop_free((OPENSSL_STACK *)val, (void(*)(void*))q_X509V3_conf_free); + }); QVariantMap map; QVariantList list; @@ -222,10 +206,12 @@ QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext) return map; else return list; - } else if (meth->i2s && ext_internal) { - QVariant result(QString::fromUtf8(meth->i2s(meth, ext_internal))); + } else if (meth->i2s) { + const char *hexString = meth->i2s(meth, ext_internal); + QVariant result(hexString ? QString::fromUtf8(hexString) : QString{}); + q_OPENSSL_free((void *)hexString); return result; - } else if (meth->i2r && ext_internal) { + } else if (meth->i2r) { QByteArray result; BIO *bio = q_BIO_new(q_BIO_s_mem()); @@ -254,6 +240,31 @@ QVariant x509ExtensionToValue(X509_EXTENSION *ext) { ASN1_OBJECT *obj = q_X509_EXTENSION_get_object(ext); int nid = q_OBJ_obj2nid(obj); + + // We cast away the const-ness here because some versions of openssl + // don't use const for the parameters in the functions pointers stored + // in the object. + X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext)); + + void *ext_internal = nullptr; // The value, returned by X509V3_EXT_d2i. + const auto extCleaner = qScopeGuard([meth, &ext_internal]() { + if (!meth || !ext_internal) + return; + + if (meth->it) + q_ASN1_item_free(static_cast<ASN1_VALUE *>(ext_internal), ASN1_ITEM_ptr(meth->it)); + else if (meth->ext_free) + meth->ext_free(ext_internal); + else + qWarning(lcTlsBackend, "Cannot free an extension, a potential memory leak?"); + }); + + const char * hexString = nullptr; // The value returned by meth->i2s. + const auto hexStringCleaner = qScopeGuard([&hexString](){ + if (hexString) + q_OPENSSL_free((void*)hexString); + }); + switch (nid) { case NID_basic_constraints: { @@ -261,9 +272,9 @@ QVariant x509ExtensionToValue(X509_EXTENSION *ext) if (!basic) return {}; QVariantMap result; - result[QLatin1String("ca")] = basic->ca ? true : false; + result["ca"_L1] = basic->ca ? true : false; if (basic->pathlen) - result[QLatin1String("pathLenConstraint")] = (qlonglong)q_ASN1_INTEGER_get(basic->pathlen); + result["pathLenConstraint"_L1] = (qlonglong)q_ASN1_INTEGER_get(basic->pathlen); q_BASIC_CONSTRAINTS_free(basic); return result; @@ -295,21 +306,18 @@ QVariant x509ExtensionToValue(X509_EXTENSION *ext) } } - q_OPENSSL_sk_pop_free((OPENSSL_STACK*)info, reinterpret_cast<void(*)(void *)>(q_OPENSSL_sk_free)); + q_AUTHORITY_INFO_ACCESS_free(info); return result; } break; case NID_subject_key_identifier: { - void *ext_internal = q_X509V3_EXT_d2i(ext); + ext_internal = q_X509V3_EXT_d2i(ext); if (!ext_internal) return {}; - // we cast away the const-ness here because some versions of openssl - // don't use const for the parameters in the functions pointers stored - // in the object. - X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext)); - return QVariant(QString::fromUtf8(meth->i2s(meth, ext_internal))); + hexString = meth->i2s(meth, ext_internal); + return QVariant(QString::fromUtf8(hexString)); } break; case NID_authority_key_identifier: @@ -323,7 +331,7 @@ QVariant x509ExtensionToValue(X509_EXTENSION *ext) if (auth_key->keyid) { QByteArray keyid(reinterpret_cast<const char *>(auth_key->keyid->data), auth_key->keyid->length); - result[QLatin1String("keyid")] = keyid.toHex(); + result["keyid"_L1] = keyid.toHex(); } // issuer @@ -331,7 +339,7 @@ QVariant x509ExtensionToValue(X509_EXTENSION *ext) // serial if (auth_key->serial) - result[QLatin1String("serial")] = (qlonglong)q_ASN1_INTEGER_get(auth_key->serial); + result["serial"_L1] = (qlonglong)q_ASN1_INTEGER_get(auth_key->serial); q_AUTHORITY_KEYID_free(auth_key); return result; @@ -609,7 +617,7 @@ QList<QSslError> X509CertificateOpenSSL::verify(const QList<QSslCertificate> &ca const QString &hostName) { // This was previously QSslSocketPrivate::verify(). - if (certificateChain.count() <= 0) + if (certificateChain.size() <= 0) return {QSslError(QSslError::UnspecifiedError)}; QList<QSslError> errors; @@ -633,7 +641,7 @@ QList<QSslError> X509CertificateOpenSSL::verify(const QList<QSslCertificate> &ca // certificate will be searched. Make sure to not have expired // certificates mixed with valid ones. // - // See also: QSslContext::fromConfiguration() + // See also: QSslContext::sharedFromConfiguration() if (caCertificate.expiryDate() >= now) { q_X509_STORE_add_cert(certStore, reinterpret_cast<X509 *>(caCertificate.handle())); } @@ -651,7 +659,7 @@ QList<QSslError> X509CertificateOpenSSL::verify(const QList<QSslCertificate> &ca // Build the chain of intermediate certificates STACK_OF(X509) *intermediates = nullptr; - if (certificateChain.length() > 1) { + if (certificateChain.size() > 1) { intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null(); if (!intermediates) { @@ -703,7 +711,7 @@ QList<QSslError> X509CertificateOpenSSL::verify(const QList<QSslCertificate> &ca // Translate errors from the error list into QSslErrors. errors.reserve(errors.size() + lastErrors.size()); - for (const auto &error : qAsConst(lastErrors)) + for (const auto &error : std::as_const(lastErrors)) errors << openSSLErrorToQSslError(error.code, certificateChain.value(error.depth)); return errors; diff --git a/src/plugins/tls/openssl/qx509_openssl_p.h b/src/plugins/tls/openssl/qx509_openssl_p.h index 19f2f7614e..3b2e06f343 100644 --- a/src/plugins/tls/openssl/qx509_openssl_p.h +++ b/src/plugins/tls/openssl/qx509_openssl_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QX509_OPENSSL_P_H #define QX509_OPENSSL_P_H |