Move plugin code from QtNetwork to qtbase/plugins

All TLS (and non-TLS) backends that QSsl classes rely
on are now in plugins/tls (as openssl, securetransport,
schannel and certonly plugins).

For now, I have to disable some tests that were using OpenSSL
calls - this to be refactored/re-thought. These include:
qsslsocket auto-test (test-case where we work with private keys),
qsslkey auto-test (similar to qsslsocket - test-case working with
keys using OpenSSL calls).
qasn1element moved to plugins too, so its auto-test have to
be re-thought.
Since now we can have more than one working TLS-backend on a given
platform, the presence of OpenSSL also means I force this backend
as active before running tests, to make sure features implemented
only in OpenSSL-backend are tested.
OCSP auto test is disabled for now, since it heavily relies on
OpenSSL symbols (to be refactored).

[ChangeLog][QtNetwork][QSslSocket] QSslSocket by default prefers 'openssl' backend
if it is available.

[ChangeLog][QtNetwork][QSslSocket] TLS-backends are not mutually exclusive anymore,
depending on a platform, more than one TLS backend can be built. E.g., configuring
Qt with -openssl does not prevent SecureTransport or Schannel plugin from being
built.

Fixes: QTBUG-91928
Change-Id: I4c05e32f10179066bee3a518bdfdd6c4b15320c3
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Timur Pocheptsov 2021-03-25 12:41:08 +01:00
parent 6b1a7341fe
commit d385158d52
74 changed files with 916 additions and 827 deletions

View File

@ -5,7 +5,7 @@
#####################################################################
qt_internal_add_module(Network
PLUGIN_TYPES networkaccessbackends networkinformationbackends
PLUGIN_TYPES networkaccessbackends networkinformationbackends tls
SOURCES
access/qabstractnetworkcache.cpp access/qabstractnetworkcache.h access/qabstractnetworkcache_p.h
access/qhsts.cpp access/qhsts_p.h
@ -41,15 +41,11 @@ qt_internal_add_module(Network
socket/qtcpserver.cpp socket/qtcpserver.h socket/qtcpserver_p.h
socket/qtcpsocket.cpp socket/qtcpsocket.h socket/qtcpsocket_p.h
socket/qudpsocket.cpp socket/qudpsocket.h
ssl/qasn1element.cpp ssl/qasn1element_p.h
ssl/qpassworddigestor.cpp ssl/qpassworddigestor.h
ssl/qssl.cpp ssl/qssl.h ssl/qssl_p.h
ssl/qsslcertificate.cpp ssl/qsslcertificate.h ssl/qsslcertificate_p.h
ssl/qsslcertificateextension.cpp ssl/qsslcertificateextension.h ssl/qsslcertificateextension_p.h
ssl/qtlsbackend.cpp ssl/qtlsbackend_p.h
ssl/qtlsbackend_cert.cpp ssl/qtlsbackend_cert_p.h
ssl/qx509_base.cpp ssl/qx509_base_p.h
ssl/qx509_generic.cpp ssl/qx509_generic_p.h
DEFINES
QT_NO_FOREACH
QT_NO_USING_NAMESPACE
@ -324,59 +320,11 @@ qt_internal_extend_target(Network CONDITION QT_FEATURE_ssl
ssl/qsslkey.h ssl/qsslkey_p.cpp ssl/qsslkey_p.h
ssl/qsslpresharedkeyauthenticator.cpp ssl/qsslpresharedkeyauthenticator.h ssl/qsslpresharedkeyauthenticator_p.h
ssl/qsslsocket.cpp ssl/qsslsocket.h ssl/qsslsocket_p.h
ssl/qtlskey_base.cpp ssl/qtlskey_base_p.h
)
qt_internal_extend_target(Network CONDITION QT_FEATURE_schannel AND QT_FEATURE_ssl
SOURCES
ssl/qsslsocket_qt.cpp
ssl/qwincrypt_p.h
ssl/qtls_schannel.cpp ssl/qtls_schannel_p.h
ssl/qtlsbackend_schannel_p.h
ssl/qtlskey_generic.cpp ssl/qtlskey_generic_p.h
ssl/qtlskey_schannel.cpp ssl/qtlskey_schannel_p.h
ssl/qx509_schannel.cpp ssl/qx509_schannel_p.h
LIBRARIES
Crypt32
Secur32
bcrypt
ncrypt
)
qt_internal_extend_target(Network CONDITION QT_FEATURE_securetransport AND QT_FEATURE_ssl
SOURCES
ssl/qtls_st.cpp ssl/qtls_st_p.h
ssl/qsslsocket_mac_shared.cpp
ssl/qsslsocket_qt.cpp
ssl/qtlskey_generic.cpp ssl/qtlskey_generic_p.h
ssl/qtlskey_st.cpp ssl/qtlskey_st_p.h
ssl/qtlsbackend_st.cpp ssl/qtlsbackend_st_p.h
ssl/qx509_st.cpp ssl/qx509_st_p.h
)
qt_internal_extend_target(Network CONDITION QT_FEATURE_dtls AND QT_FEATURE_ssl
SOURCES
ssl/qdtls.cpp ssl/qdtls.h ssl/qdtls_p.h
ssl/qdtls_base.cpp ssl/qdtls_base_p.h
)
qt_internal_extend_target(Network CONDITION QT_FEATURE_openssl AND QT_FEATURE_ssl
SOURCES
ssl/qsslcontext_openssl.cpp ssl/qsslcontext_openssl_p.h
ssl/qssldiffiehellmanparameters_openssl.cpp
ssl/qopenssl.cpp ssl/qopenssl_p.h
ssl/qsslsocket_openssl_symbols.cpp ssl/qsslsocket_openssl_symbols_p.h
ssl/qtls_openssl.cpp ssl/qtls_openssl_p.h
ssl/qtlskey_openssl.cpp ssl/qtlskey_openssl_p.h
ssl/qtlsbackend_openssl.cpp ssl/qtlsbackend_openssl_p.h
ssl/qx509_openssl.cpp ssl/qx509_openssl_p.h
DEFINES
OPENSSL_API_COMPAT=0x10100000L
)
qt_internal_extend_target(Network CONDITION QT_FEATURE_dtls AND QT_FEATURE_openssl AND QT_FEATURE_ssl
SOURCES
ssl/qdtls_openssl.cpp ssl/qdtls_openssl_p.h
)
qt_internal_extend_target(Network CONDITION QT_FEATURE_ocsp AND QT_FEATURE_openssl AND QT_FEATURE_ssl
@ -384,16 +332,6 @@ qt_internal_extend_target(Network CONDITION QT_FEATURE_ocsp AND QT_FEATURE_opens
ssl/qocsp_p.h
)
qt_internal_extend_target(Network CONDITION APPLE AND QT_FEATURE_openssl AND QT_FEATURE_ssl
SOURCES
ssl/qsslsocket_mac_shared.cpp
)
qt_internal_extend_target(Network CONDITION ANDROID AND QT_FEATURE_openssl AND QT_FEATURE_ssl AND NOT ANDROID_EMBEDDED
SOURCES
ssl/qsslsocket_openssl_android.cpp
)
qt_internal_extend_target(Network CONDITION QT_FEATURE_openssl AND QT_FEATURE_openssl_linked AND QT_FEATURE_ssl
LIBRARIES
WrapOpenSSL::WrapOpenSSL
@ -408,13 +346,6 @@ qt_internal_extend_target(Network CONDITION QT_FEATURE_openssl AND QT_FEATURE_ss
WrapOpenSSLHeaders::WrapOpenSSLHeaders
)
qt_internal_extend_target(Network CONDITION QT_FEATURE_openssl AND QT_FEATURE_ssl AND WIN32
SOURCES
ssl/qwindowscarootfetcher.cpp ssl/qwindowscarootfetcher_p.h
LIBRARIES
crypt32
)
qt_internal_extend_target(Network CONDITION QT_FEATURE_dnslookup AND UNIX AND NOT ANDROID AND NOT INTEGRITY
SOURCES
kernel/qdnslookup_unix.cpp

View File

@ -263,27 +263,26 @@ qt_feature_definition("openssl" "QT_NO_OPENSSL" NEGATE)
qt_feature_config("openssl" QMAKE_PUBLIC_QT_CONFIG)
qt_feature("openssl-runtime"
AUTODETECT NOT WASM
CONDITION NOT QT_FEATURE_securetransport AND NOT QT_FEATURE_schannel AND TEST_openssl_headers
CONDITION TEST_openssl_headers
ENABLE INPUT_openssl STREQUAL 'yes' OR INPUT_openssl STREQUAL 'runtime'
DISABLE INPUT_openssl STREQUAL 'no' OR INPUT_openssl STREQUAL 'linked' OR INPUT_ssl STREQUAL 'no'
)
qt_feature("openssl-linked" PRIVATE
LABEL " Qt directly linked to OpenSSL"
AUTODETECT OFF
CONDITION NOT QT_FEATURE_securetransport AND NOT QT_FEATURE_schannel AND TEST_openssl
CONDITION TEST_openssl
ENABLE INPUT_openssl STREQUAL 'linked'
)
qt_feature_definition("openssl-linked" "QT_LINKED_OPENSSL")
qt_feature("securetransport" PUBLIC
LABEL "SecureTransport"
CONDITION APPLE AND ( INPUT_openssl STREQUAL '' OR INPUT_openssl STREQUAL 'no' )
CONDITION APPLE
DISABLE INPUT_ssl STREQUAL 'no'
)
qt_feature_definition("securetransport" "QT_SECURETRANSPORT")
qt_feature("schannel" PUBLIC
LABEL "Schannel"
AUTODETECT OFF
CONDITION WIN32 AND ( INPUT_openssl STREQUAL '' OR INPUT_openssl STREQUAL 'no' )
CONDITION WIN32
DISABLE INPUT_ssl STREQUAL 'no'
)
qt_feature_definition("schannel" "QT_SCHANNEL")

View File

@ -284,13 +284,13 @@
"autoDetect": "!config.wasm",
"enable": "input.openssl == 'yes' || input.openssl == 'runtime'",
"disable": "input.openssl == 'no' || input.openssl == 'linked' || input.ssl == 'no'",
"condition": "!features.securetransport && !features.schannel && libs.openssl_headers"
"condition": "libs.openssl_headers"
},
"openssl-linked": {
"label": " Qt directly linked to OpenSSL",
"autoDetect": false,
"enable": "input.openssl == 'linked'",
"condition": "!features.securetransport && !features.schannel && libs.openssl",
"condition": "libs.openssl",
"output": [
"privateFeature",
{ "type": "define", "name": "QT_LINKED_OPENSSL" }
@ -299,7 +299,7 @@
"securetransport": {
"label": "SecureTransport",
"disable": "input.ssl == 'no'",
"condition": "config.darwin && (input.openssl == '' || input.openssl == 'no')",
"condition": "config.darwin",
"output": [
"publicFeature",
{ "type": "define", "name": "QT_SECURETRANSPORT" }
@ -309,7 +309,7 @@
"label": "Schannel",
"autoDetect": false,
"disable": "input.ssl == 'no'",
"condition": "config.win32 && (input.openssl == '' || input.openssl == 'no')",
"condition": "config.win32",
"output": [
"publicFeature",
{ "type": "define", "name": "QT_SCHANNEL" }

View File

@ -1,71 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Copyright (C) 2014 Governikus GmbH & Co. KG
** 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$
**
****************************************************************************/
/****************************************************************************
**
** In addition, as a special exception, the copyright holders listed above give
** permission to link the code of its release of Qt with the OpenSSL project's
** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the
** same license as the original version), and distribute the linked executables.
**
** You must comply with the GNU General Public License version 2 in all
** respects for all of the code used other than the "OpenSSL" code. If you
** modify this file, you may extend this exception to your version of the file,
** but you are not obligated to do so. If you do not wish to do so, delete
** this exception statement from your version of this file.
**
****************************************************************************/
#include "qtlsbackend_openssl_p.h"
#include "qopenssl_p.h"
QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QTlsBackendOpenSSL, backendOpenSsl)
void QSslSocketPrivate::registerAdHocFactory()
{
// TLSTODO: this is a temporary solution, waiting for
// backends to move to ... plugins.
if (!backendOpenSsl())
qCWarning(lcSsl, "Failed to create backend factory");
}
QT_END_NAMESPACE

View File

@ -57,12 +57,8 @@
#include "qssl_p.h"
#include "qsslkey.h"
#include "qsslkey_p.h"
#ifndef QT_NO_OPENSSL
#include "qsslsocket_openssl_symbols_p.h"
#endif
#include "qsslsocket.h"
#include "qsslsocket_p.h"
#include "qasn1element_p.h"
#include "qtlsbackend_p.h"
#include <QtCore/qatomic.h>

View File

@ -73,8 +73,8 @@ public:
using Cipher = QTlsPrivate::Cipher;
Q_AUTOTEST_EXPORT static QByteArray decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv);
Q_AUTOTEST_EXPORT static QByteArray encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv);
Q_NETWORK_EXPORT static QByteArray decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv);
Q_NETWORK_EXPORT static QByteArray encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv);
std::unique_ptr<QTlsPrivate::TlsKey> backend;
QAtomicInt ref;

View File

@ -1573,7 +1573,7 @@ QList<QString> QSslSocket::availableBackends()
from the list of available backends.
\note When selecting a default backend implicitly, QSslSocket prefers
native backends, such as SecureTransport on Darwin, or Schannel on Windows.
the OpenSSL backend if available.
\sa setActiveBackend(), availableBackends()
*/

View File

@ -103,7 +103,7 @@ public:
static bool s_loadRootCertsOnDemand;
static bool supportsSsl();
static void ensureInitialized();
Q_NETWORK_EXPORT static void ensureInitialized();
static QList<QSslCipher> defaultCiphers();
static QList<QSslCipher> defaultDtlsCiphers();
@ -117,7 +117,7 @@ public:
static void resetDefaultEllipticCurves();
static QList<QSslCertificate> defaultCaCertificates();
static QList<QSslCertificate> systemCaCertificates();
Q_NETWORK_EXPORT static QList<QSslCertificate> systemCaCertificates();
static void setDefaultCaCertificates(const QList<QSslCertificate> &certs);
static void addDefaultCaCertificate(const QSslCertificate &cert);
static void addDefaultCaCertificates(const QList<QSslCertificate> &certs);
@ -168,7 +168,6 @@ public:
Q_NETWORK_PRIVATE_EXPORT static void setRootCertOnDemandLoadingSupported(bool supported);
static QTlsBackend *tlsBackendInUse();
static void registerAdHocFactory();
// Needed by TlsCryptograph:
Q_NETWORK_PRIVATE_EXPORT QSslSocket::SslMode tlsMode() const;

View File

@ -46,8 +46,6 @@
#include "qsslcipher_p.h"
#include "qsslkey_p.h"
#include "qsslkey.h"
#else
#include "qtlsbackend_cert_p.h"
#endif
#include "qssl_p.h"
@ -63,7 +61,7 @@
QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
(QTlsBackend_iid, QStringLiteral("/tlsbackends")))
(QTlsBackend_iid, QStringLiteral("/tls")))
namespace {
@ -104,14 +102,6 @@ public:
while (loader->instance(index))
++index;
// TLSTODO: obviously, these two below should
// disappear as soon as plugins are in place.
#if QT_CONFIG(ssl)
QSslSocketPrivate::registerAdHocFactory();
#else
static QTlsBackendCertOnly certGenerator;
#endif // QT_CONFIG(ssl)
return loaded = true;
}
@ -244,6 +234,13 @@ bool TlsCryptograph::isMatchingHostname(const QString &cn, const QString &hostna
return QSslSocketPrivate::isMatchingHostname(cn, hostname);
}
void TlsCryptograph::setErrorAndEmit(QSslSocketPrivate *d, QAbstractSocket::SocketError errorCode,
const QString &errorDescription) const
{
Q_ASSERT(d);
d->setErrorAndEmit(errorCode, errorDescription);
}
#endif // QT_CONFIG(ssl)
#if QT_CONFIG(dtls)
@ -255,7 +252,8 @@ DtlsBase::~DtlsBase() = default;
const QString QTlsBackend::builtinBackendNames[] = {
QStringLiteral("schannel"),
QStringLiteral("securetransport"),
QStringLiteral("openssl")
QStringLiteral("openssl"),
QStringLiteral("cert-only")
};
QTlsBackend::QTlsBackend()
@ -436,17 +434,24 @@ QList<QString> QTlsBackend::availableBackendNames()
QString QTlsBackend::defaultBackendName()
{
// We prefer native as default:
// We prefer OpenSSL as default:
const auto names = availableBackendNames();
auto name = builtinBackendNames[nameIndexSchannel];
auto name = builtinBackendNames[nameIndexOpenSSL];
if (names.contains(name))
return name;
name = builtinBackendNames[nameIndexSchannel];
if (names.contains(name))
return name;
name = builtinBackendNames[nameIndexSecureTransport];
if (names.contains(name))
return name;
name = builtinBackendNames[nameIndexOpenSSL];
if (names.contains(name))
return name;
const auto pos = std::find_if(names.begin(), names.end(), [](const auto &name) {
return name != builtinBackendNames[nameIndexCertOnly];
});
if (pos != names.end())
return *pos;
if (names.size())
return names[0];
@ -787,6 +792,16 @@ void QTlsBackend::setEphemeralKey(QSslSocketPrivate *d, const QSslKey &key)
d->configuration.ephemeralServerKey = key;
}
void QTlsBackend::forceAutotestSecurityLevel()
{
}
Q_NETWORK_EXPORT void qt_ForceTlsSecurityLevel()
{
if (auto *backend = QSslSocketPrivate::tlsBackendInUse())
backend->forceAutotestSecurityLevel();
}
#endif // QT_CONFIG(ssl)
QT_END_NAMESPACE

View File

@ -226,6 +226,9 @@ public:
static bool isMatchingHostname(const QSslCertificate &cert, const QString &peerName);
static bool isMatchingHostname(const QString &cn, const QString &hostname);
void setErrorAndEmit(QSslSocketPrivate *d, QAbstractSocket::SocketError errorCode,
const QString &errorDescription) const;
};
#else
class TlsCryptograph;
@ -371,6 +374,7 @@ public:
static constexpr const int nameIndexSchannel = 0;
static constexpr const int nameIndexSecureTransport = 1;
static constexpr const int nameIndexOpenSSL = 2;
static constexpr const int nameIndexCertOnly = 3;
static const QString builtinBackendNames[];
@ -428,6 +432,8 @@ public:
static void addTustedRoot(QSslSocketPrivate *d, const QSslCertificate &rootCert);
// The next one - is a "very important" feature! Kidding ...
static void setEphemeralKey(QSslSocketPrivate *d, const QSslKey &key);
virtual void forceAutotestSecurityLevel();
#endif // QT_CONFIG(ssl)
Q_DISABLE_COPY_MOVE(QTlsBackend)

View File

@ -22,4 +22,5 @@ if(TARGET Qt::PrintSupport)
endif()
if (TARGET Qt::Network)
add_subdirectory(networkinformationbackends)
add_subdirectory(tls)
endif()

View File

@ -0,0 +1,13 @@
if(QT_FEATURE_securetransport)
add_subdirectory(securetransport)
endif()
if (QT_FEATURE_openssl OR QT_FEATURE_openssl_linked)
add_subdirectory(openssl)
endif()
if (QT_FEATURE_schannel)
add_subdirectory(schannel)
endif()
add_subdirectory(certonly)

View File

@ -0,0 +1,16 @@
qt_internal_add_plugin(QTlsBackendCertOnly
OUTPUT_NAME certonlybackend
CLASS_NAME QTlsBackendCertOnly
TYPE tls
SOURCES
../shared/qx509_base_p.h
../shared/qx509_base.cpp
../shared/qx509_generic_p.h
../shared/qx509_generic.cpp
../shared/qasn1element_p.h
../shared/qasn1element.cpp
qtlsbackend_cert.cpp
qtlsbackend_cert_p.h
PUBLIC_LIBRARIES
Qt::NetworkPrivate
)

View File

@ -39,9 +39,7 @@
#include "qtlsbackend_cert_p.h"
#ifdef QT_NO_SSL
#include "qx509_generic_p.h"
#include "../shared/qx509_generic_p.h"
#include <qssl.h>
@ -53,7 +51,7 @@ Q_LOGGING_CATEGORY(lcTlsBackend, "qt.tlsbackend.cert-only");
QString QTlsBackendCertOnly::backendName() const
{
return QStringLiteral("cert-only");
return builtinBackendNames[nameIndexCertOnly];
}
@ -92,5 +90,3 @@ QTlsPrivate::X509DerReaderPtr QTlsBackendCertOnly::X509DerReader() const
QT_END_NAMESPACE
#endif // QT_NO_SSL

View File

@ -51,19 +51,19 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qtlsbackend_p.h"
#include <QtNetwork/private/qtlsbackend_p.h>
#include <QtCore/qglobal.h>
#ifdef QT_NO_SSL
QT_BEGIN_NAMESPACE
class QTlsBackendCertOnly final : public QTlsBackend
{
public:
Q_OBJECT
Q_PLUGIN_METADATA(IID QTlsBackend_iid)
Q_INTERFACES(QTlsBackend)
private:
QString backendName() const override;
@ -78,6 +78,4 @@ private:
QT_END_NAMESPACE
#endif // QT_NO_SSL
#endif // QTLSBACKEND_CERT_P_H

View File

@ -0,0 +1,51 @@
qt_internal_add_plugin(QTlsBackendOpenSSL
OUTPUT_NAME opensslbackend
CLASS_NAME QTlsBackendOpenSSL
TYPE tls
SOURCES
../shared/qx509_base.cpp ../shared/qx509_base_p.h
../shared/qtlskey_base.cpp ../shared/qtlskey_base_p.h
../shared/qasn1element.cpp ../shared/qasn1element_p.h
qtlsbackend_openssl.cpp qtlsbackend_openssl_p.h
qx509_openssl.cpp qx509_openssl_p.h
qtlskey_openssl.cpp qtlskey_openssl_p.h
qtls_openssl.cpp qtls_openssl_p.h
qssldiffiehellmanparameters_openssl.cpp
qsslcontext_openssl.cpp qsslcontext_openssl_p.h
qsslsocket_openssl_symbols.cpp qsslsocket_openssl_symbols_p.h
qopenssl_p.h
PUBLIC_LIBRARIES
Qt::NetworkPrivate
Qt::CorePrivate
DEFINES
OPENSSL_API_COMPAT=0x10100000L
)
qt_internal_extend_target(QTlsBackendOpenSSL CONDITION QT_FEATURE_dtls
SOURCES
qdtls_openssl.cpp qdtls_openssl_p.h
../shared/qdtls_base.cpp ../shared/qdtls_base_p.h
)
qt_internal_extend_target(QTlsBackendOpenSSL CONDITION APPLE
SOURCES
../shared/qsslsocket_mac_shared.cpp
LIBRARIES
${FWCoreFoundation}
${FWSecurity}
)
qt_internal_extend_target(QTlsBackendOpenSSL CONDITION ANDROID AND NOT ANDROID_EMBEDDED
SOURCES
qsslsocket_openssl_android.cpp
)
qt_internal_extend_target(QTlsBackendOpenSSL CONDITION QT_FEATURE_openssl
AND QT_FEATURE_ssl AND WIN32
SOURCES
qwindowscarootfetcher.cpp qwindowscarootfetcher_p.h
../shared/qwincrypt_p.h
LIBRARIES
crypt32
)

View File

@ -40,20 +40,23 @@
#ifndef NOMINMAX
#define NOMINMAX
#endif // NOMINMAX
#include "private/qnativesocketengine_p.h"
#include "qsslpresharedkeyauthenticator_p.h"
#include <QtNetwork/private/qnativesocketengine_p.h>
#include "qsslsocket_openssl_symbols_p.h"
#include "qsslcertificate_p.h"
#include "qdtls_openssl_p.h"
#include "qx509_openssl_p.h"
#include "qudpsocket.h"
#include "qssl_p.h"
#include "qmessageauthenticationcode.h"
#include "qcryptographichash.h"
#include <QtNetwork/private/qsslpresharedkeyauthenticator_p.h>
#include <QtNetwork/private/qsslcertificate_p.h>
#include <QtNetwork/private/qssl_p.h>
#include "qdebug.h"
#include <QtNetwork/qudpsocket.h>
#include <QtCore/qmessageauthenticationcode.h>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qdebug.h>
#include <cstring>
#include <cstddef>
@ -84,13 +87,13 @@ QByteArray cookie_for_peer(SSL *ssl)
// SSL_get_rbio does not increment the reference count
BIO *readBIO = q_SSL_get_rbio(ssl);
if (!readBIO) {
qCWarning(lcSsl, "No BIO (dgram) found in SSL object");
qCWarning(lcTlsBackend, "No BIO (dgram) found in SSL object");
return {};
}
auto listener = static_cast<dtlsopenssl::DtlsState *>(q_BIO_get_app_data(readBIO));
if (!listener) {
qCWarning(lcSsl, "BIO_get_app_data returned invalid (nullptr) value");
qCWarning(lcTlsBackend, "BIO_get_app_data returned invalid (nullptr) value");
return {};
}
@ -192,14 +195,14 @@ extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst,
unsigned *cookieLength)
{
if (!ssl || !dst || !cookieLength) {
qCWarning(lcSsl,
qCWarning(lcTlsBackend,
"Failed to generate cookie - invalid (nullptr) parameter(s)");
return 0;
}
void *generic = q_SSL_get_ex_data(ssl, QTlsBackendOpenSSL::s_indexForSSLExtraData);
if (!generic) {
qCWarning(lcSsl, "SSL_get_ex_data returned nullptr, cannot generate cookie");
qCWarning(lcTlsBackend, "SSL_get_ex_data returned nullptr, cannot generate cookie");
return 0;
}
@ -228,7 +231,7 @@ extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
unsigned cookieLength)
{
if (!ssl || !cookie || !cookieLength) {
qCWarning(lcSsl, "Could not verify cookie, invalid (nullptr or zero) parameters");
qCWarning(lcTlsBackend, "Could not verify cookie, invalid (nullptr or zero) parameters");
return 0;
}
@ -247,13 +250,13 @@ extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx)
// Store the error and at which depth the error was detected.
SSL *ssl = static_cast<SSL *>(q_X509_STORE_CTX_get_ex_data(ctx, q_SSL_get_ex_data_X509_STORE_CTX_idx()));
if (!ssl) {
qCWarning(lcSsl, "X509_STORE_CTX_get_ex_data returned nullptr, handshake failure");
qCWarning(lcTlsBackend, "X509_STORE_CTX_get_ex_data returned nullptr, handshake failure");
return 0;
}
void *generic = q_SSL_get_ex_data(ssl, QTlsBackendOpenSSL::s_indexForSSLExtraData);
if (!generic) {
qCWarning(lcSsl, "SSL_get_ex_data returned nullptr, handshake failure");
qCWarning(lcTlsBackend, "SSL_get_ex_data returned nullptr, handshake failure");
return 0;
}
@ -300,7 +303,7 @@ namespace dtlsbio
extern "C" int q_dgram_read(BIO *bio, char *dst, int bytesToRead)
{
if (!bio || !dst || bytesToRead <= 0) {
qCWarning(lcSsl, "invalid input parameter(s)");
qCWarning(lcTlsBackend, "invalid input parameter(s)");
return 0;
}
@ -330,7 +333,7 @@ extern "C" int q_dgram_read(BIO *bio, char *dst, int bytesToRead)
extern "C" int q_dgram_write(BIO *bio, const char *src, int bytesToWrite)
{
if (!bio || !src || bytesToWrite <= 0) {
qCWarning(lcSsl, "invalid input parameter(s)");
qCWarning(lcTlsBackend, "invalid input parameter(s)");
return 0;
}
@ -365,7 +368,7 @@ extern "C" int q_dgram_write(BIO *bio, const char *src, int bytesToWrite)
extern "C" int q_dgram_puts(BIO *bio, const char *src)
{
if (!bio || !src) {
qCWarning(lcSsl, "invalid input parameter(s)");
qCWarning(lcTlsBackend, "invalid input parameter(s)");
return 0;
}
@ -390,7 +393,7 @@ extern "C" long q_dgram_ctrl(BIO *bio, int cmd, long num, void *ptr)
// command.
if (!bio) {
qDebug(lcSsl, "invalid 'bio' parameter (nullptr)");
qDebug(lcTlsBackend, "invalid 'bio' parameter (nullptr)");
return -1;
}
@ -1425,7 +1428,7 @@ void QDtlsPrivateOpenSSL::fetchNegotiatedParameters()
sessionProtocol = QSsl::DtlsV1_2;
break;
default:
qCWarning(lcSsl, "unknown protocol version");
qCWarning(lcTlsBackend, "unknown protocol version");
sessionProtocol = QSsl::UnknownProtocol;
}
}

View File

@ -40,27 +40,26 @@
#ifndef QDTLS_OPENSSL_P_H
#define QDTLS_OPENSSL_P_H
#include <private/qtnetworkglobal_p.h>
#include <QtCore/qglobal.h>
#include <openssl/ossl_typ.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qsslcontext_openssl_p.h"
#include "qtlsbackend_openssl_p.h"
#include "qtls_openssl_p.h"
#include "qdtls_base_p.h"
#include "qdtls_p.h"
#include "qopenssl_p.h"
#include <private/qsslcontext_openssl_p.h>
#include <private/qopenssl_p.h>
#include "../shared/qdtls_base_p.h"
#include <QtNetwork/private/qdtls_p.h>
#include <QtNetwork/qsslpresharedkeyauthenticator.h>
#include <QtNetwork/qhostaddress.h>
#include <QtCore/qsharedpointer.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qglobal.h>
#include <QtCore/qlist.h>
#include <QtCore/qsharedpointer.h>
#include <openssl/ossl_typ.h>
//
// W A R N I N G

View File

@ -68,8 +68,9 @@
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qsslsocket_p.h"
#include "qsslcipher.h"
#include <QtNetwork/private/qsslsocket_p.h>
#include <QtNetwork/qsslcipher.h>
#ifdef Q_OS_WIN
#include <qt_windows.h>

View File

@ -43,13 +43,16 @@
#include <QtNetwork/qsslsocket.h>
#include <QtNetwork/qssldiffiehellmanparameters.h>
#include "private/qopenssl_p.h"
#include "private/qssl_p.h"
#include "private/qsslsocket_p.h"
#include "private/qsslcontext_openssl_p.h"
#include "private/qsslsocket_openssl_symbols_p.h"
#include "private/qssldiffiehellmanparameters_p.h"
#include "private/qtlsbackend_openssl_p.h"
#include "qsslsocket_openssl_symbols_p.h"
#include "qsslcontext_openssl_p.h"
#include "qtlsbackend_openssl_p.h"
#include "qopenssl_p.h"
#include <QtNetwork/private/qssl_p.h>
#include <QtNetwork/private/qsslsocket_p.h>
#include <QtNetwork/private/qtlsbackend_p.h>
#include <QtNetwork/private/qssldiffiehellmanparameters_p.h>
#include <vector>
@ -57,11 +60,6 @@ QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(bool, forceSecurityLevel)
Q_NETWORK_EXPORT void qt_ForceTlsSecurityLevel()
{
*forceSecurityLevel() = true;
}
namespace QTlsPrivate
{
// These callback functions are defined in qtls_openssl.cpp.
@ -218,7 +216,7 @@ static int next_proto_cb(SSL *, unsigned char **out, unsigned char *outlen,
ctx->status = QSslConfiguration::NextProtocolNegotiationUnsupported;
break;
default:
qCWarning(lcSsl, "OpenSSL sent unknown NPN status");
qCWarning(lcTlsBackend, "OpenSSL sent unknown NPN status");
}
return SSL_TLSEXT_ERR_OK;
@ -248,7 +246,7 @@ SSL* QSslContext::createSsl()
if (session) {
// Try to resume the last session we cached
if (!q_SSL_set_session(ssl, session)) {
qCWarning(lcSsl, "could not set SSL session");
qCWarning(lcTlsBackend, "could not set SSL session");
q_SSL_SESSION_free(session);
session = nullptr;
}
@ -260,7 +258,7 @@ SSL* QSslContext::createSsl()
m_supportedNPNVersions.clear();
for (int a = 0; a < protocols.count(); ++a) {
if (protocols.at(a).size() > 255) {
qCWarning(lcSsl) << "TLS NPN extension" << protocols.at(a)
qCWarning(lcTlsBackend) << "TLS NPN extension" << protocols.at(a)
<< "is too long and will be ignored.";
continue;
} else if (protocols.at(a).isEmpty()) {
@ -313,7 +311,7 @@ bool QSslContext::cacheSession(SSL* ssl)
m_sessionASN1.resize(sessionSize);
unsigned char *data = reinterpret_cast<unsigned char *>(m_sessionASN1.data());
if (!q_i2d_SSL_SESSION(session, &data))
qCWarning(lcSsl, "could not store persistent version of SSL session");
qCWarning(lcTlsBackend, "could not store persistent version of SSL session");
m_sessionTicketLifeTimeHint = q_SSL_SESSION_get_ticket_lifetime_hint(session);
}
}
@ -336,6 +334,11 @@ int QSslContext::sessionTicketLifeTimeHint() const
return m_sessionTicketLifeTimeHint;
}
void QSslContext::forceAutoTestSecurityLevel()
{
*forceSecurityLevel() = true;
}
QSslError::SslError QSslContext::error() const
{
return errorCode;
@ -370,13 +373,13 @@ init_context:
#else // dtls
sslContext->ctx = nullptr;
unsupportedProtocol = true;
qCWarning(lcSsl, "DTLS protocol requested, but feature 'dtls' is disabled");
qCWarning(lcTlsBackend, "DTLS protocol requested, but feature 'dtls' is disabled");
#endif // dtls
break;
case QSsl::TlsV1_3:
case QSsl::TlsV1_3OrLater:
#if !defined(TLS1_3_VERSION)
qCWarning(lcSsl, "TLS 1.3 is not supported");
qCWarning(lcTlsBackend, "TLS 1.3 is not supported");
sslContext->ctx = nullptr;
unsupportedProtocol = true;
break;
@ -591,7 +594,7 @@ init_context:
#endif // OPENSSL_VERSION_MAJOR
if (success != 1) {
const auto qtErrors = QTlsBackendOpenSSL::getErrorsFromOpenSsl();
qCWarning(lcSsl) << "An error encountered while to set root certificates location:"
qCWarning(lcTlsBackend) << "An error encountered while to set root certificates location:"
<< qtErrors;
}
}

View File

@ -87,6 +87,8 @@ public:
void setSessionASN1(const QByteArray &sessionASN1);
int sessionTicketLifeTimeHint() const;
static void forceAutoTestSecurityLevel();
#ifndef OPENSSL_NO_NEXTPROTONEG
// must be public because we want to use it from an OpenSSL callback
struct NPNContext {

View File

@ -40,7 +40,8 @@
#include "qsslsocket_openssl_symbols_p.h"
#include "qtlsbackend_openssl_p.h"
#include "qsslsocket_p.h"
#include <QtNetwork/private/qsslsocket_p.h>
#include <QtCore/qscopeguard.h>
#include <QtCore/qbytearray.h>

View File

@ -52,7 +52,6 @@
**
****************************************************************************/
#include "qsslsocket_p.h"
#include <QtCore/QJniEnvironment>
#include <QtCore/QJniObject>

View File

@ -54,11 +54,12 @@
**
****************************************************************************/
#include "qssl_p.h"
#include "qsslsocket_openssl_symbols_p.h"
#include <QtNetwork/private/qssl_p.h>
#ifdef Q_OS_WIN
# include <private/qsystemlibrary_p.h>
# include <QtCore/private/qsystemlibrary_p.h>
#elif QT_CONFIG(library)
# include <QtCore/qlibrary.h>
#endif
@ -72,7 +73,7 @@
#include <link.h>
#endif
#ifdef Q_OS_DARWIN
#include "private/qcore_mac_p.h"
#include <QtCore/private/qcore_mac_p.h>
#endif
#include <algorithm>
@ -123,13 +124,13 @@ QT_BEGIN_NAMESPACE
namespace {
void qsslSocketUnresolvedSymbolWarning(const char *functionName)
{
qCWarning(lcSsl, "QSslSocket: cannot call unresolved function %s", functionName);
qCWarning(lcTlsBackend, "QSslSocket: cannot call unresolved function %s", functionName);
}
#if QT_CONFIG(library)
void qsslSocketCannotResolveSymbolWarning(const char *functionName)
{
qCWarning(lcSsl, "QSslSocket: cannot resolve %s", functionName);
qCWarning(lcTlsBackend, "QSslSocket: cannot resolve %s", functionName);
}
#endif
@ -522,9 +523,9 @@ DEFINEFUNC(void, PKCS12_free, PKCS12 *pkcs12, pkcs12, return, DUMMYARG)
#if !QT_CONFIG(library)
bool q_resolveOpenSslSymbols()
{
qCWarning(lcSsl, "QSslSocket: unable to resolve symbols. Qt is configured without the "
qCWarning(lcTlsBackend, "QSslSocket: unable to resolve symbols. Qt is configured without the "
"'library' feature, which means runtime resolving of libraries won't work.");
qCWarning(lcSsl, "Either compile Qt statically or with support for runtime resolving "
qCWarning(lcTlsBackend, "Either compile Qt statically or with support for runtime resolving "
"of libraries.");
return false;
}
@ -904,7 +905,7 @@ bool q_resolveOpenSslSymbols()
if (!_q_OpenSSL_version) {
// Apparently, we were built with OpenSSL 1.1 enabled but are now using
// a wrong library.
qCWarning(lcSsl, "Incompatible version of OpenSSL");
qCWarning(lcTlsBackend, "Incompatible version of OpenSSL");
return false;
}
@ -1217,18 +1218,4 @@ bool q_resolveOpenSslSymbols()
}
#endif // !defined QT_LINKED_OPENSSL
QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime)
{
QDateTime result;
tm lTime;
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);
}
return result;
}
QT_END_NAMESPACE

View File

@ -69,11 +69,13 @@
//
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qopenssl_p.h"
#include <QtCore/qglobal.h>
#if QT_CONFIG(ocsp)
#include "qocsp_p.h"
#include <QtNetwork/private/qocsp_p.h>
#endif
QT_BEGIN_NAMESPACE
@ -227,23 +229,23 @@ QT_BEGIN_NAMESPACE
const unsigned char * q_ASN1_STRING_get0_data(const ASN1_STRING *x);
Q_AUTOTEST_EXPORT BIO *q_BIO_new(const BIO_METHOD *a);
Q_AUTOTEST_EXPORT const BIO_METHOD *q_BIO_s_mem();
BIO *q_BIO_new(const BIO_METHOD *a);
const BIO_METHOD *q_BIO_s_mem();
int q_DSA_bits(DSA *a);
int q_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c);
Q_AUTOTEST_EXPORT int q_EVP_PKEY_up_ref(EVP_PKEY *a);
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);
Q_AUTOTEST_EXPORT int q_OPENSSL_sk_num(OPENSSL_STACK *a);
Q_AUTOTEST_EXPORT void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *));
Q_AUTOTEST_EXPORT OPENSSL_STACK *q_OPENSSL_sk_new_null();
Q_AUTOTEST_EXPORT void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data);
Q_AUTOTEST_EXPORT void q_OPENSSL_sk_free(OPENSSL_STACK *a);
Q_AUTOTEST_EXPORT void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b);
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();
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);
int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
@ -256,7 +258,7 @@ const SSL_METHOD *q_TLS_server_method();
ASN1_TIME *q_X509_getm_notBefore(X509 *a);
ASN1_TIME *q_X509_getm_notAfter(X509 *a);
Q_AUTOTEST_EXPORT void q_X509_up_ref(X509 *a);
void q_X509_up_ref(X509 *a);
long q_X509_get_version(X509 *a);
EVP_PKEY *q_X509_get_pubkey(X509 *a);
void q_X509_STORE_set_verify_cb(X509_STORE *ctx, X509_STORE_CTX_verify_cb verify_cb);
@ -370,10 +372,10 @@ int q_ASN1_STRING_length(ASN1_STRING *a);
int q_ASN1_STRING_to_UTF8(unsigned char **a, ASN1_STRING *b);
int q_ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm);
long q_BIO_ctrl(BIO *a, int b, long c, void *d);
Q_AUTOTEST_EXPORT int q_BIO_free(BIO *a);
int q_BIO_free(BIO *a);
BIO *q_BIO_new_mem_buf(void *a, int b);
int q_BIO_read(BIO *a, void *b, int c);
Q_AUTOTEST_EXPORT int q_BIO_write(BIO *a, const void *b, int c);
int q_BIO_write(BIO *a, const void *b, int c);
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);
@ -414,18 +416,18 @@ const EVP_CIPHER *q_EVP_aes_192_cbc();
const EVP_CIPHER *q_EVP_aes_256_cbc();
#endif // OPENSSL_NO_AES
Q_AUTOTEST_EXPORT const EVP_MD *q_EVP_sha1();
const EVP_MD *q_EVP_sha1();
int q_EVP_PKEY_assign(EVP_PKEY *a, int b, void *r);
Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b);
Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b);
Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_DH(EVP_PKEY *a, DH *b);
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
Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b);
int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b);
#endif
Q_AUTOTEST_EXPORT int q_EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
Q_AUTOTEST_EXPORT void q_EVP_PKEY_free(EVP_PKEY *a);
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);
@ -433,7 +435,7 @@ DH *q_EVP_PKEY_get1_DH(EVP_PKEY *a);
EC_KEY *q_EVP_PKEY_get1_EC_KEY(EVP_PKEY *a);
#endif
int q_EVP_PKEY_type(int a);
Q_AUTOTEST_EXPORT EVP_PKEY *q_EVP_PKEY_new();
EVP_PKEY *q_EVP_PKEY_new();
int q_i2d_X509(X509 *a, unsigned char **b);
const char *q_OBJ_nid2sn(int a);
const char *q_OBJ_nid2ln(int a);
@ -443,7 +445,7 @@ int q_i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *obj);
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))
Q_AUTOTEST_EXPORT EVP_PKEY *q_PEM_read_bio_PrivateKey(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d);
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);
@ -462,7 +464,7 @@ int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned
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);
Q_AUTOTEST_EXPORT EVP_PKEY *q_PEM_read_bio_PUBKEY(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d);
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);
@ -541,9 +543,9 @@ X509 *q_X509_dup(X509 *a);
void q_X509_print(BIO *a, X509*b);
int q_X509_digest(const X509 *x509, const EVP_MD *type, unsigned char *md, unsigned int *len);
ASN1_OBJECT *q_X509_EXTENSION_get_object(X509_EXTENSION *a);
Q_AUTOTEST_EXPORT void q_X509_free(X509 *a);
Q_AUTOTEST_EXPORT ASN1_TIME *q_X509_gmtime_adj(ASN1_TIME *s, long adj);
Q_AUTOTEST_EXPORT void q_ASN1_TIME_free(ASN1_TIME *t);
void q_X509_free(X509 *a);
ASN1_TIME *q_X509_gmtime_adj(ASN1_TIME *s, long adj);
void q_ASN1_TIME_free(ASN1_TIME *t);
X509_EXTENSION *q_X509_get_ext(X509 *a, int b);
int q_X509_get_ext_count(X509 *a);
void *q_X509_get_ext_d2i(X509 *a, int b, int *c, int *d);
@ -698,28 +700,24 @@ int q_BIO_set_ex_data(BIO *b, int idx, void *data);
#define q_BIO_set_app_data(s,arg) q_BIO_set_ex_data(s,0,arg)
#define q_BIO_get_app_data(s) q_BIO_get_ex_data(s,0)
// Helper function
class QDateTime;
QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime);
#define q_SSL_set_tlsext_status_type(ssl, type) \
q_SSL_ctrl((ssl), SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE, (type), nullptr)
#if QT_CONFIG(ocsp)
OCSP_RESPONSE *q_d2i_OCSP_RESPONSE(OCSP_RESPONSE **a, const unsigned char **in, long len);
Q_AUTOTEST_EXPORT int q_i2d_OCSP_RESPONSE(OCSP_RESPONSE *r, unsigned char **ppout);
Q_AUTOTEST_EXPORT OCSP_RESPONSE *q_OCSP_response_create(int status, OCSP_BASICRESP *bs);
Q_AUTOTEST_EXPORT void q_OCSP_RESPONSE_free(OCSP_RESPONSE *rs);
int q_i2d_OCSP_RESPONSE(OCSP_RESPONSE *r, unsigned char **ppout);
OCSP_RESPONSE *q_OCSP_response_create(int status, OCSP_BASICRESP *bs);
void q_OCSP_RESPONSE_free(OCSP_RESPONSE *rs);
int q_OCSP_response_status(OCSP_RESPONSE *resp);
OCSP_BASICRESP *q_OCSP_response_get1_basic(OCSP_RESPONSE *resp);
Q_AUTOTEST_EXPORT OCSP_SINGLERESP *q_OCSP_basic_add1_status(OCSP_BASICRESP *rsp, OCSP_CERTID *cid,
OCSP_SINGLERESP *q_OCSP_basic_add1_status(OCSP_BASICRESP *rsp, OCSP_CERTID *cid,
int status, int reason, ASN1_TIME *revtime,
ASN1_TIME *thisupd, ASN1_TIME *nextupd);
Q_AUTOTEST_EXPORT int q_OCSP_basic_sign(OCSP_BASICRESP *brsp, X509 *signer, EVP_PKEY *key, const EVP_MD *dgst,
int q_OCSP_basic_sign(OCSP_BASICRESP *brsp, X509 *signer, EVP_PKEY *key, const EVP_MD *dgst,
STACK_OF(X509) *certs, unsigned long flags);
Q_AUTOTEST_EXPORT OCSP_BASICRESP *q_OCSP_BASICRESP_new();
Q_AUTOTEST_EXPORT void q_OCSP_BASICRESP_free(OCSP_BASICRESP *bs);
OCSP_BASICRESP *q_OCSP_BASICRESP_new();
void q_OCSP_BASICRESP_free(OCSP_BASICRESP *bs);
int q_OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags);
int q_OCSP_resp_count(OCSP_BASICRESP *bs);
OCSP_SINGLERESP *q_OCSP_resp_get0(OCSP_BASICRESP *bs, int idx);
@ -730,8 +728,8 @@ int q_OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd, ASN1_
ASN1_INTEGER **pserial, OCSP_CERTID *cid);
const STACK_OF(X509) *q_OCSP_resp_get0_certs(const OCSP_BASICRESP *bs);
Q_AUTOTEST_EXPORT OCSP_CERTID *q_OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer);
Q_AUTOTEST_EXPORT void q_OCSP_CERTID_free(OCSP_CERTID *cid);
OCSP_CERTID *q_OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer);
void q_OCSP_CERTID_free(OCSP_CERTID *cid);
int q_OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
#define q_SSL_get_tlsext_status_ocsp_resp(ssl, arg) \

View File

@ -37,19 +37,21 @@
**
****************************************************************************/
#include "qsslpresharedkeyauthenticator_p.h"
#include "qsslpresharedkeyauthenticator.h"
#include "qsslsocket_openssl_symbols_p.h"
#include "qsslcertificate_p.h"
#include "qx509_openssl_p.h"
#include "qocspresponse_p.h"
#include "qtls_openssl_p.h"
#include "qsslsocket_p.h"
#ifdef Q_OS_WIN
#include "qwindowscarootfetcher_p.h"
#endif
#include <QtNetwork/private/qsslpresharedkeyauthenticator_p.h>
#include <QtNetwork/private/qsslcertificate_p.h>
#include <QtNetwork/private/qocspresponse_p.h>
#include <QtNetwork/private/qsslsocket_p.h>
#include <QtNetwork/qsslpresharedkeyauthenticator.h>
#include <QtCore/qscopedvaluerollback.h>
#include <QtCore/qscopeguard.h>
@ -195,7 +197,7 @@ int q_X509CallbackDirect(int ok, X509_STORE_CTX *ctx)
// errors immediately and returning 0 or 1 depending on an application
// either ignoring or not ignoring verification errors as they come.
if (!ctx) {
qCWarning(lcSsl, "Invalid store context (nullptr)");
qCWarning(lcTlsBackend, "Invalid store context (nullptr)");
return 0;
}
@ -430,7 +432,7 @@ bool qt_OCSP_certificate_match(OCSP_SINGLERESP *singleResponse, X509 *peerCert,
const OCSP_CERTID *certId = q_OCSP_SINGLERESP_get0_id(singleResponse); // Does not increment refcount.
if (!certId) {
qCWarning(lcSsl, "A SingleResponse without CertID");
qCWarning(lcTlsBackend, "A SingleResponse without CertID");
return false;
}
@ -438,7 +440,7 @@ bool qt_OCSP_certificate_match(OCSP_SINGLERESP *singleResponse, X509 *peerCert,
ASN1_INTEGER *reportedSerialNumber = nullptr;
const int result = q_OCSP_id_get0_info(nullptr, &md, nullptr, &reportedSerialNumber, const_cast<OCSP_CERTID *>(certId));
if (result != 1 || !md || !reportedSerialNumber) {
qCWarning(lcSsl, "Failed to extract a hash and serial number from CertID structure");
qCWarning(lcTlsBackend, "Failed to extract a hash and serial number from CertID structure");
return false;
}
@ -446,31 +448,31 @@ bool qt_OCSP_certificate_match(OCSP_SINGLERESP *singleResponse, X509 *peerCert,
// Is this possible at all? But we have to check this,
// ASN1_INTEGER_cmp (called from OCSP_id_cmp) dereferences
// without any checks at all.
qCWarning(lcSsl, "No serial number in peer's ceritificate");
qCWarning(lcTlsBackend, "No serial number in peer's ceritificate");
return false;
}
const int nid = q_OBJ_obj2nid(md);
if (nid == NID_undef) {
qCWarning(lcSsl, "Unknown hash algorithm in CertID");
qCWarning(lcTlsBackend, "Unknown hash algorithm in CertID");
return false;
}
const EVP_MD *digest = q_EVP_get_digestbynid(nid); // Does not increment refcount.
if (!digest) {
qCWarning(lcSsl) << "No digest for nid" << nid;
qCWarning(lcTlsBackend) << "No digest for nid" << nid;
return false;
}
OCSP_CERTID *recreatedId = q_OCSP_cert_to_id(digest, peerCert, issuer);
if (!recreatedId) {
qCWarning(lcSsl, "Failed to re-create CertID");
qCWarning(lcTlsBackend, "Failed to re-create CertID");
return false;
}
const QSharedPointer<OCSP_CERTID> guard(recreatedId, q_OCSP_CERTID_free);
if (q_OCSP_id_cmp(const_cast<OCSP_CERTID *>(certId), recreatedId)) {
qDebug(lcSsl, "Certificate ID mismatch");
qDebug(lcTlsBackend, "Certificate ID mismatch");
return false;
}
// Bingo!
@ -522,8 +524,8 @@ void TlsCryptographOpenSSL::startClientEncryption()
{
if (!initSslContext()) {
Q_ASSERT(d);
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QSslSocket::tr("Unable to init SSL Context: %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QSslSocket::tr("Unable to init SSL Context: %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
return;
}
@ -537,8 +539,8 @@ void TlsCryptographOpenSSL::startServerEncryption()
{
if (!initSslContext()) {
Q_ASSERT(d);
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QSslSocket::tr("Unable to init SSL Context: %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QSslSocket::tr("Unable to init SSL Context: %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
return;
}
@ -614,7 +616,7 @@ bool TlsCryptographOpenSSL::startHandshake()
#endif
{
const ScopedBool bg(inSetAndEmitError, true);
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, errorString);
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError, errorString);
if (pendingFatalAlert) {
trySendFatalAlert();
pendingFatalAlert = false;
@ -657,7 +659,7 @@ bool TlsCryptographOpenSSL::startHandshake()
if (ocspErrors.isEmpty()) {
{
const ScopedBool bg(inSetAndEmitError, true);
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, ocspErrorDescription);
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError, ocspErrorDescription);
}
q->abort();
return false;
@ -800,9 +802,9 @@ void TlsCryptographOpenSSL::continueHandshake()
QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys");
QFile file(sslKeyFile);
if (!file.open(QIODevice::Append))
qCWarning(lcSsl) << "could not open file" << sslKeyFile << "for appending";
qCWarning(lcTlsBackend) << "could not open file" << sslKeyFile << "for appending";
if (!file.write(debugLineClientRandom))
qCWarning(lcSsl) << "could not write to file" << sslKeyFile;
qCWarning(lcTlsBackend) << "could not write to file" << sslKeyFile;
file.close();
} else {
qCWarning(lcTlsBackend, "could not decrypt SSL traffic");
@ -911,9 +913,9 @@ void TlsCryptographOpenSSL::transmit()
} else {
// ### Better error handling.
const ScopedBool bg(inSetAndEmitError, true);
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QSslSocket::tr("Unable to write data: %1").arg(
QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QSslSocket::tr("Unable to write data: %1").arg(
QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
return;
}
}
@ -959,7 +961,7 @@ void TlsCryptographOpenSSL::transmit()
if (actualWritten < 0) {
//plain socket write fails if it was in the pending close state.
const ScopedBool bg(inSetAndEmitError, true);
d->setErrorAndEmit(plainSocket->error(), plainSocket->errorString());
setErrorAndEmit(d, plainSocket->error(), plainSocket->errorString());
return;
}
transmitting = true;
@ -985,9 +987,9 @@ void TlsCryptographOpenSSL::transmit()
} else {
// ### Better error handling.
const ScopedBool bg(inSetAndEmitError, true);
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QSslSocket::tr("Unable to decrypt data: %1")
.arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QSslSocket::tr("Unable to decrypt data: %1")
.arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
return;
}
@ -1068,8 +1070,8 @@ void TlsCryptographOpenSSL::transmit()
shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves
{
const ScopedBool bg(inSetAndEmitError, true);
d->setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
QSslSocket::tr("The TLS/SSL connection has been closed"));
setErrorAndEmit(d, QAbstractSocket::RemoteHostClosedError,
QSslSocket::tr("The TLS/SSL connection has been closed"));
}
return;
case SSL_ERROR_SYSCALL: // some IO error
@ -1079,9 +1081,9 @@ void TlsCryptographOpenSSL::transmit()
systemOrSslErrorDetected = true;
{
const ScopedBool bg(inSetAndEmitError, true);
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QSslSocket::tr("Error while reading: %1")
.arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QSslSocket::tr("Error while reading: %1")
.arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
}
return;
default:
@ -1092,9 +1094,9 @@ void TlsCryptographOpenSSL::transmit()
// So this default case should never be triggered.
{
const ScopedBool bg(inSetAndEmitError, true);
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QSslSocket::tr("Error while reading: %1")
.arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QSslSocket::tr("Error while reading: %1")
.arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
}
break;
}
@ -1196,7 +1198,7 @@ bool TlsCryptographOpenSSL::checkSslErrors()
QSslSocketPrivate::pauseSocketNotifiers(q);
d->setPaused(true);
} else {
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.constFirst().errorString());
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError, sslErrors.constFirst().errorString());
auto *plainSocket = d->plainTcpSocket();
Q_ASSERT(plainSocket);
plainSocket->disconnectFromHost();
@ -1360,15 +1362,15 @@ bool TlsCryptographOpenSSL::initSslContext()
sslContextPointer = QSslContext::sharedFromConfiguration(mode, configuration, d->isRootsOnDemandAllowed());
if (sslContextPointer->error() != QSslError::NoError) {
d->setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError, sslContextPointer->errorString());
setErrorAndEmit(d, QAbstractSocket::SslInvalidUserDataError, sslContextPointer->errorString());
sslContextPointer.clear(); // deletes the QSslContext
return false;
}
// Create and initialize SSL session
if (!(ssl = sslContextPointer->createSsl())) {
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QSslSocket::tr("Error creating SSL session, %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QSslSocket::tr("Error creating SSL session, %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
return false;
}
@ -1399,8 +1401,8 @@ bool TlsCryptographOpenSSL::initSslContext()
readBio = q_BIO_new(q_BIO_s_mem());
writeBio = q_BIO_new(q_BIO_s_mem());
if (!readBio || !writeBio) {
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QSslSocket::tr("Error creating SSL session: %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QSslSocket::tr("Error creating SSL session: %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl()));
if (readBio)
q_BIO_free(readBio);
if (writeBio)
@ -1438,13 +1440,13 @@ bool TlsCryptographOpenSSL::initSslContext()
#if QT_CONFIG(ocsp)
if (configuration.ocspStaplingEnabled()) {
if (mode == QSslSocket::SslServerMode) {
d->setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
QSslSocket::tr("Server-side QSslSocket does not support OCSP stapling"));
setErrorAndEmit(d, QAbstractSocket::SslInvalidUserDataError,
QSslSocket::tr("Server-side QSslSocket does not support OCSP stapling"));
return false;
}
if (q_SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp) != 1) {
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QSslSocket::tr("Failed to enable OCSP stapling"));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QSslSocket::tr("Failed to enable OCSP stapling"));
return false;
}
}
@ -1463,8 +1465,8 @@ bool TlsCryptographOpenSSL::initSslContext()
if (ocspResponseDer.size()) {
if (mode != QSslSocket::SslServerMode) {
d->setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
QSslSocket::tr("Client-side sockets do not send OCSP responses"));
setErrorAndEmit(d, QAbstractSocket::SslInvalidUserDataError,
QSslSocket::tr("Client-side sockets do not send OCSP responses"));
return false;
}
}

View File

@ -51,14 +51,15 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qtlsbackend_openssl_p.h"
#include "qsslcontext_openssl_p.h"
#include "qsslcertificate.h"
#include "qocspresponse.h"
#include "qopenssl_p.h"
#include <QtNetwork/qsslcertificate.h>
#include <QtNetwork/qocspresponse.h>
#include <QtCore/qsharedpointer.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qglobal.h>

View File

@ -37,29 +37,29 @@
**
****************************************************************************/
#include "qsslsocket_openssl_symbols_p.h"
#include "qtlsbackend_openssl_p.h"
#include "qtlskey_openssl_p.h"
#include "qx509_openssl_p.h"
#include "qtls_openssl_p.h"
#include "qsslcipher_p.h"
//#include "qsslsocket_p.h"
#include "qsslcipher.h"
#if QT_CONFIG(dtls)
#include "qdtls_openssl_p.h"
#endif // QT_CONFIG(dtls)
#include "qsslsocket_openssl_symbols_p.h"
#include <QtNetwork/private/qsslcipher_p.h>
#include <QtNetwork/qsslcipher.h>
#include <QtNetwork/qssl.h>
#include <QtCore/qdir.h>
#include <QtCore/qdiriterator.h>
#include <QtCore/qlist.h>
#include <QtCore/qmutex.h>
#include <QtCore/qscopeguard.h>
#include "qopenssl_p.h"
#include <qssl.h>
#include <qdir.h>
#include <qdiriterator.h>
#include <qlist.h>
#include <qmutex.h>
#include <qscopeguard.h>
#include <algorithm>
QT_BEGIN_NAMESPACE
@ -335,7 +335,9 @@ QList<QSsl::ImplementedClass> QTlsBackendOpenSSL::implementedClasses() const
classes << QSsl::ImplementedClass::Key;
classes << QSsl::ImplementedClass::Certificate;
classes << QSsl::ImplementedClass::Socket;
#if QT_CONFIG(dtls)
classes << QSsl::ImplementedClass::Dtls;
#endif
classes << QSsl::ImplementedClass::EllipticCurve;
classes << QSsl::ImplementedClass::DiffieHellman;
@ -627,4 +629,9 @@ QSslCipher QTlsBackendOpenSSL::qt_OpenSSL_cipher_to_QSslCipher(const SSL_CIPHER
return createCiphersuite(desc, bits, supportedBits);
}
void QTlsBackendOpenSSL::forceAutotestSecurityLevel()
{
QSslContext::forceAutoTestSecurityLevel();
}
QT_END_NAMESPACE

View File

@ -51,11 +51,12 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qssldiffiehellmanparameters.h"
#include "qsslcertificate.h"
#include "qtlsbackend_p.h"
#include <QtNetwork/qssldiffiehellmanparameters.h>
#include <QtNetwork/qsslcertificate.h>
#include <QtNetwork/private/qtlsbackend_p.h>
#include <QtCore/qglobal.h>
#include <QtCore/qlist.h>
@ -66,6 +67,10 @@ QT_BEGIN_NAMESPACE
class QTlsBackendOpenSSL final : public QTlsBackend
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QTlsBackend_iid)
Q_INTERFACES(QTlsBackend)
public:
static QString getErrorsFromOpenSsl();
@ -125,6 +130,8 @@ private:
using DHParams = QSslDiffieHellmanParameters;
int dhParametersFromDer(const QByteArray &derData, QByteArray *data) const override;
int dhParametersFromPem(const QByteArray &pemData, QByteArray *data) const override;
void forceAutotestSecurityLevel() override;
};
QT_END_NAMESPACE

View File

@ -39,10 +39,12 @@
#include "qsslsocket_openssl_symbols_p.h"
#include "qtlskey_openssl_p.h"
#include "qsslsocket.h"
#include "qsslkey_p.h"
#include <qscopeguard.h>
#include <QtNetwork/private/qsslkey_p.h>
#include <QtNetwork/qsslsocket.h>
#include <QtCore/qscopeguard.h>
QT_BEGIN_NAMESPACE

View File

@ -51,11 +51,12 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qtlskey_base_p.h"
#include "qtlsbackend_p.h"
#include "qsslkey_p.h"
#include "../shared/qtlskey_base_p.h"
#include <QtNetwork/private/qtlsbackend_p.h>
#include <QtNetwork/private/qsslkey_p.h>
#include <QtNetwork/qssl.h>

View File

@ -38,6 +38,8 @@
****************************************************************************/
#include "qwindowscarootfetcher_p.h"
#include "qx509_openssl_p.h"
#include "qopenssl_p.h"
#include <QtCore/QThread>
#include <QtGlobal>
@ -45,17 +47,10 @@
#include <QtCore/qscopeguard.h>
#ifdef QSSLSOCKET_DEBUG
#include "qssl_p.h" // for debug categories
#include <QtNetwork/private/qtlsbackend_p.h> // for debug categories
#include <QtCore/QElapsedTimer>
#endif
#include "qsslsocket_p.h" // Transitively includes Wincrypt.h
#if QT_CONFIG(openssl)
#include "qopenssl_p.h"
#include "qx509_openssl_p.h"
#endif
QT_BEGIN_NAMESPACE
class QWindowsCaRootFetcherThread : public QThread
@ -76,11 +71,8 @@ public:
Q_GLOBAL_STATIC(QWindowsCaRootFetcherThread, windowsCaRootFetcherThread);
#if QT_CONFIG(openssl)
namespace {
// TLSTODO: we have to ask the currently active TLS backend about verification
// support and get a function pointer. QT_CONFIG(openssl) check is becoming useless
// as soon as we have several plugins.
const QList<QSslCertificate> buildVerifiedChain(const QList<QSslCertificate> &caCertificates,
PCCERT_CHAIN_CONTEXT chainContext,
const QString &peerVerifyName)
@ -134,7 +126,6 @@ const QList<QSslCertificate> buildVerifiedChain(const QList<QSslCertificate> &ca
}
} // unnamed namespace
#endif // QT_CONFIG(openssl)
QWindowsCaRootFetcher::QWindowsCaRootFetcher(const QSslCertificate &certificate, QSslSocket::SslMode sslMode,
const QList<QSslCertificate> &caCertificates, const QString &hostName)
@ -153,7 +144,7 @@ void QWindowsCaRootFetcher::start()
PCCERT_CONTEXT wincert = CertCreateCertificateContext(X509_ASN_ENCODING, (const BYTE *)der.constData(), der.length());
if (!wincert) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, "QWindowsCaRootFetcher failed to convert certificate to windows form");
qCDebug(lcTlsBackend, "QWindowsCaRootFetcher failed to convert certificate to windows form");
#endif
emit finished(cert, QSslCertificate());
deleteLater();

View File

@ -42,13 +42,13 @@
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <QtNetwork/qsslcertificate.h>
#include <QtNetwork/qsslsocket.h>
#include <QtCore/QtGlobal>
#include <QtCore/QObject>
#include "qsslcertificate.h"
#include "qsslsocket.h"
#include "qwincrypt_p.h"
#include "../shared/qwincrypt_p.h"
//
// W A R N I N G

View File

@ -37,16 +37,15 @@
**
****************************************************************************/
#include "qtlsbackend_openssl_p.h"
#include "qsslcertificate_p.h"
#include "qtlskey_openssl_p.h"
#include "qx509_openssl_p.h"
#include "qsslsocket_openssl_symbols_p.h"
#include "qtlsbackend_openssl_p.h"
#include "qtlskey_openssl_p.h"
#include "qx509_openssl_p.h"
#include "qtls_openssl_p.h"
#include "qsslsocket.h"
#include <QtNetwork/private/qsslcertificate_p.h>
#include <QtNetwork/qsslsocket.h>
#include <QtNetwork/qhostaddress.h>
#include <QtCore/qvarlengtharray.h>
@ -62,10 +61,6 @@ namespace QTlsPrivate {
namespace {
// TLSTODO: These helper functions below were static member-functions of
// QSslCertificatePrivate, if-defed with !QT_NO_OPENSSL, no need
// for them to be exposed this way anymore. Remove this comment when
// plugins are ready.
QByteArray asn1ObjectId(ASN1_OBJECT *object)
{
if (!object)
@ -108,6 +103,21 @@ QMultiMap<QByteArray, QString> mapFromX509Name(X509_NAME *name)
return info;
}
QDateTime dateTimeFromASN1(const ASN1_TIME *aTime)
{
QDateTime result;
tm lTime;
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);
}
return result;
}
#define BEGINCERTSTRING "-----BEGIN CERTIFICATE-----"
#define ENDCERTSTRING "-----END CERTIFICATE-----"
@ -528,11 +538,11 @@ QSslCertificate X509CertificateOpenSSL::certificateFromX509(X509 *x509)
ASN1_TIME *nbef = q_X509_getm_notBefore(x509);
if (nbef)
backend->notValidBefore = q_getTimeFromASN1(nbef);
backend->notValidBefore = dateTimeFromASN1(nbef);
ASN1_TIME *naft = q_X509_getm_notAfter(x509);
if (naft)
backend->notValidAfter = q_getTimeFromASN1(naft);
backend->notValidAfter = dateTimeFromASN1(naft);
backend->null = false;
backend->x509 = q_X509_dup(x509);
@ -685,7 +695,7 @@ QList<QSslError> X509CertificateOpenSSL::verify(const QList<QSslCertificate> &ca
errors << QSslError(QSslError::CertificateBlacklisted, certificateChain[0]);
// Check the certificate name against the hostname if one was specified
if (!hostName.isEmpty() && !QSslSocketPrivate::isMatchingHostname(certificateChain[0], hostName)) {
if (!hostName.isEmpty() && !TlsCryptograph::isMatchingHostname(certificateChain[0], hostName)) {
// No matches in common names or alternate names.
QSslError error(QSslError::HostNameMismatch, certificateChain[0]);
errors << error;

View File

@ -51,18 +51,17 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <private/qopenssl_p.h>
#include "../shared/qx509_base_p.h"
#include <private/qtlsbackend_p.h>
#include <private/qx509_base_p.h>
#include <QtNetwork/private/qtlsbackend_p.h>
#include <QtCore/qvariant.h>
#include <QtCore/qglobal.h>
#include <QtCore/qstring.h>
#include <openssl/x509.h>
#include "qopenssl_p.h"
#include <algorithm>
@ -70,9 +69,6 @@ QT_BEGIN_NAMESPACE
namespace QTlsPrivate {
// TLSTODO: This class is essentially what qsslcertificate_openssl.cpp
// contains - OpenSSL-based version of QSslCertificatePrivate. Remove
// this comment when plugins are ready.
class X509CertificateOpenSSL final : public X509CertificateBase
{
public:
@ -94,15 +90,10 @@ public:
size_t hash(size_t seed) const noexcept override;
// TLSTODO: these are needed by qsslsocket_openssl and later, by
// TLS code inside OpenSSL plugin. Remove this comment when
// plugins are ready.
static QSslCertificate certificateFromX509(X509 *x);
static QList<QSslCertificate> stackOfX509ToQSslCertificates(STACK_OF(X509) *x509);
static QSslErrorEntry errorEntryFromStoreContext(X509_STORE_CTX *ctx);
// TLSTODO: remove this comment when plugins are in place. This is what QSslSocketPrivate::verify()
// in qsslsocket_openssl.cpp is (was) doing (in the past).
static QList<QSslError> verify(const QList<QSslCertificate> &chain, const QString &hostName);
static QList<QSslError> verify(const QList<QSslCertificate> &caCertificates,
const QList<QSslCertificate> &certificateChain,

View File

@ -0,0 +1,30 @@
qt_internal_add_plugin(QSchannelBackend
OUTPUT_NAME schannelbackend
CLASS_NAME QSchannelBackend
TYPE tls
DEFAULT_IF WINDOWS
SOURCES
../shared/qtlskey_base_p.h
../shared/qtlskey_base.cpp
../shared/qtlskey_generic_p.h
../shared/qtlskey_generic.cpp
../shared/qx509_base_p.h
../shared/qx509_base.cpp
../shared/qx509_generic_p.h
../shared/qx509_generic.cpp
../shared/qsslsocket_qt.cpp
../shared/qwincrypt_p.h
../shared/qasn1element_p.h
../shared/qasn1element.cpp
qtls_schannel.cpp qtls_schannel_p.h
qtlsbackend_schannel_p.h
qtlskey_schannel.cpp qtlskey_schannel_p.h
qx509_schannel.cpp qx509_schannel_p.h
LIBRARIES
Crypt32
Secur32
bcrypt
ncrypt
PUBLIC_LIBRARIES
Qt::NetworkPrivate
)

View File

@ -39,16 +39,18 @@
// #define QSSLSOCKET_DEBUG
#include "qssl_p.h"
#include "qsslsocket.h"
#include "qtls_schannel_p.h"
#include "qsslcertificate.h"
#include "qsslcertificateextension.h"
#include "qsslcertificate_p.h"
#include "qsslcipher_p.h"
#include "qtlsbackend_schannel_p.h"
#include "qtlskey_schannel_p.h"
#include "qx509_schannel_p.h"
#include "qtls_schannel_p.h"
#include <QtNetwork/private/qsslcertificate_p.h>
#include <QtNetwork/private/qsslcipher_p.h>
#include <QtNetwork/private/qssl_p.h>
#include <QtNetwork/qsslcertificate.h>
#include <QtNetwork/qsslcertificateextension.h>
#include <QtNetwork/qsslsocket.h>
#include <QtCore/qscopeguard.h>
#include <QtCore/qoperatingsystemversion.h>
@ -347,8 +349,6 @@ QTlsPrivate::X509DerReaderPtr QSchannelBackend::X509DerReader() const
return QTlsPrivate::X509CertificateGeneric::certificatesFromDer;
}
Q_GLOBAL_STATIC(QSchannelBackend, backendSchannel)
namespace {
SecBuffer createSecBuffer(void *ptr, unsigned long length, unsigned long bufferType)
@ -573,7 +573,7 @@ bool matchesContextRequirements(DWORD attributes, DWORD requirements,
bool isClient)
{
#ifdef QSSLSOCKET_DEBUG
#define DEBUG_WARN(message) qCWarning(lcSsl, message)
#define DEBUG_WARN(message) qCWarning(lcTlsBackend, message)
#else
#define DEBUG_WARN(message)
#endif
@ -630,8 +630,8 @@ QByteArray createAlpnString(const QByteArrayList &nextAllowedProtocols)
QByteArray protocolString;
for (QByteArray proto : nextAllowedProtocols) {
if (proto.size() > 255) {
qCWarning(lcSsl) << "TLS ALPN extension" << proto
<< "is too long and will be ignored.";
qCWarning(lcTlsBackend) << "TLS ALPN extension" << proto
<< "is too long and will be ignored.";
continue;
} else if (proto.isEmpty()) {
continue;
@ -684,7 +684,7 @@ void retainExtraData(QByteArray &buffer, const SecBuffer &secBuffer)
return;
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, "We got SECBUFFER_EXTRA, will retain %lu bytes", secBuffer.cbBuffer);
qCDebug(lcTlsBackend, "We got SECBUFFER_EXTRA, will retain %lu bytes", secBuffer.cbBuffer);
#endif
std::move(buffer.end() - secBuffer.cbBuffer, buffer.end(), buffer.begin());
buffer.resize(secBuffer.cbBuffer);
@ -694,7 +694,7 @@ qint64 checkIncompleteData(const SecBuffer &secBuffer)
{
if (secBuffer.BufferType == SECBUFFER_MISSING) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, "Need %lu more bytes.", secBuffer.cbBuffer);
qCDebug(lcTlsBackend, "Need %lu more bytes.", secBuffer.cbBuffer);
#endif
return secBuffer.cbBuffer;
}
@ -745,7 +745,7 @@ bool TlsCryptographSchannel::sendToken(void *token, unsigned long tokenLength, b
if (written != qint64(tokenLength)) {
// Failed to write/buffer everything or an error occurred
if (emitError)
d->setErrorAndEmit(plainSocket->error(), plainSocket->errorString());
setErrorAndEmit(d, plainSocket->error(), plainSocket->errorString());
return false;
}
return true;
@ -804,8 +804,8 @@ bool TlsCryptographSchannel::acquireCredentialsHandle()
const bool isClient = d->tlsMode() == QSslSocket::SslClientMode;
const DWORD protocols = toSchannelProtocol(configuration.protocol());
if (protocols == DWORD(-1)) {
d->setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
QSslSocket::tr("Invalid protocol chosen"));
setErrorAndEmit(d, QAbstractSocket::SslInvalidUserDataError,
QSslSocket::tr("Invalid protocol chosen"));
return false;
}
@ -842,7 +842,7 @@ bool TlsCryptographSchannel::acquireCredentialsHandle()
const QString message = isClient
? QSslSocket::tr("The certificate provided cannot be used for a client.")
: QSslSocket::tr("The certificate provided cannot be used for a server.");
d->setErrorAndEmit(QAbstractSocket::SocketError::SslInvalidUserDataError, message);
setErrorAndEmit(d, QAbstractSocket::SocketError::SslInvalidUserDataError, message);
return false;
}
Q_ASSERT(chainContext->cChain == 1);
@ -931,7 +931,7 @@ bool TlsCryptographSchannel::acquireCredentialsHandle()
}
if (status != SEC_E_OK) {
d->setErrorAndEmit(QAbstractSocket::SslInternalError, schannelErrorToString(status));
setErrorAndEmit(d, QAbstractSocket::SslInternalError, schannelErrorToString(status));
return false;
}
return true;
@ -964,7 +964,6 @@ bool TlsCryptographSchannel::createContext()
{
Q_ASSERT(q);
Q_ASSERT(d);
const auto &configuration = q->sslConfiguration();
Q_ASSERT(SecIsValidHandle(&credentialHandle));
Q_ASSERT(schannelState == SchannelState::InitializeHandshake);
@ -993,7 +992,7 @@ bool TlsCryptographSchannel::createContext()
bool useAlpn = false;
#ifdef SUPPORTS_ALPN
QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNone);
QByteArray alpnString = createAlpnString(configuration.allowedNextProtocols());
QByteArray alpnString = createAlpnString(q->sslConfiguration().allowedNextProtocols());
useAlpn = !alpnString.isEmpty();
SecBuffer alpnBuffers[1];
alpnBuffers[0] = createSecBuffer(alpnString, SECBUFFER_APPLICATION_PROTOCOLS);
@ -1021,8 +1020,8 @@ bool TlsCryptographSchannel::createContext()
// This is the first call to InitializeSecurityContext, so theoretically "CONTINUE_NEEDED"
// should be the only non-error return-code here.
if (status != SEC_I_CONTINUE_NEEDED) {
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QSslSocket::tr("Error creating SSL context (%1)").arg(schannelErrorToString(status)));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QSslSocket::tr("Error creating SSL context (%1)").arg(schannelErrorToString(status)));
return false;
}
@ -1036,8 +1035,9 @@ bool TlsCryptographSchannel::acceptContext()
{
Q_ASSERT(d);
Q_ASSERT(q);
const auto &configuration = q->sslConfiguration();
auto *plainSocket = d->plainTcpSocket();
Q_ASSERT(plainSocket);
Q_ASSERT(SecIsValidHandle(&credentialHandle));
Q_ASSERT(schannelState == SchannelState::InitializeHandshake);
@ -1058,7 +1058,7 @@ bool TlsCryptographSchannel::acceptContext()
#ifdef SUPPORTS_ALPN
QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNone);
// The string must be alive when we call AcceptSecurityContext
QByteArray alpnString = createAlpnString(configuration.allowedNextProtocols());
QByteArray alpnString = createAlpnString(q->sslConfiguration().allowedNextProtocols());
if (!alpnString.isEmpty()) {
inBuffers[1] = createSecBuffer(alpnString, SECBUFFER_APPLICATION_PROTOCOLS);
} else
@ -1118,8 +1118,8 @@ bool TlsCryptographSchannel::acceptContext()
}
if (status != SEC_I_CONTINUE_NEEDED) {
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Error creating SSL context (%1)").arg(schannelErrorToString(status)));
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Error creating SSL context (%1)").arg(schannelErrorToString(status)));
return false;
}
if (!sendToken(outBuffers[0].pvBuffer, outBuffers[0].cbBuffer))
@ -1135,8 +1135,8 @@ bool TlsCryptographSchannel::performHandshake()
Q_ASSERT(plainSocket);
if (plainSocket->state() == QAbstractSocket::UnconnectedState) {
d->setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
QSslSocket::tr("The TLS/SSL connection has been closed"));
setErrorAndEmit(d, QAbstractSocket::RemoteHostClosedError,
QSslSocket::tr("The TLS/SSL connection has been closed"));
return false;
}
Q_ASSERT(SecIsValidHandle(&credentialHandle));
@ -1144,8 +1144,8 @@ bool TlsCryptographSchannel::performHandshake()
Q_ASSERT(schannelState == SchannelState::PerformHandshake);
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, "Bytes available from socket: %lld", plainSocket->bytesAvailable());
qCDebug(lcSsl, "intermediateBuffer size: %d", intermediateBuffer.size());
qCDebug(lcTlsBackend, "Bytes available from socket: %lld", plainSocket->bytesAvailable());
qCDebug(lcTlsBackend, "intermediateBuffer size: %d", intermediateBuffer.size());
#endif
if (missingData > plainSocket->bytesAvailable())
@ -1236,8 +1236,8 @@ bool TlsCryptographSchannel::performHandshake()
case SEC_I_INCOMPLETE_CREDENTIALS:
// Schannel takes care of picking certificate to send (other than the one we can specify),
// so if we get here then that means we don't have a certificate the server accepts.
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Server did not accept any certificate we could present."));
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Server did not accept any certificate we could present."));
return false;
case SEC_I_CONTEXT_EXPIRED:
// "The message sender has finished using the connection and has initiated a shutdown."
@ -1246,8 +1246,8 @@ bool TlsCryptographSchannel::performHandshake()
return false;
}
if (!shutdown) { // we did not initiate this
d->setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
QSslSocket::tr("The TLS/SSL connection has been closed"));
setErrorAndEmit(d, QAbstractSocket::RemoteHostClosedError,
QSslSocket::tr("The TLS/SSL connection has been closed"));
}
return true;
case SEC_E_INCOMPLETE_MESSAGE:
@ -1255,8 +1255,8 @@ bool TlsCryptographSchannel::performHandshake()
missingData = checkIncompleteData(outBuffers[0]);
return true;
case SEC_E_ALGORITHM_MISMATCH:
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Algorithm mismatch"));
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Algorithm mismatch"));
shutdown = true; // skip sending the "Shutdown" alert
return false;
}
@ -1264,8 +1264,8 @@ bool TlsCryptographSchannel::performHandshake()
// Note: We can get here if the connection is using TLS 1.2 and the server certificate uses
// MD5, which is not allowed in Schannel. This causes an "invalid token" error during handshake.
// (If you came here investigating an error: md5 is insecure, update your certificate)
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Handshake failed: %1").arg(schannelErrorToString(status)));
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Handshake failed: %1").arg(schannelErrorToString(status)));
return false;
}
@ -1280,7 +1280,7 @@ bool TlsCryptographSchannel::verifyHandshake()
const bool isClient = d->tlsMode() == QSslSocket::SslClientMode;
#define CHECK_STATUS(status) \
if (status != SEC_E_OK) { \
d->setErrorAndEmit(QAbstractSocket::SslInternalError, \
setErrorAndEmit(d, QAbstractSocket::SslInternalError, \
QSslSocket::tr("Failed to query the TLS context: %1") \
.arg(schannelErrorToString(status))); \
return false; \
@ -1289,8 +1289,8 @@ bool TlsCryptographSchannel::verifyHandshake()
// Everything is set up, now make sure there's nothing wrong and query some attributes...
if (!matchesContextRequirements(contextAttributes, getContextRequirements(),
configuration.peerVerifyMode(), isClient)) {
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Did not get the required attributes for the connection."));
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Did not get the required attributes for the connection."));
return false;
}
@ -1318,7 +1318,7 @@ bool TlsCryptographSchannel::verifyHandshake()
QByteArray negotiatedProto = QByteArray((const char *)alpn.ProtocolId,
alpn.ProtocolIdSize);
if (!allowedProtos.contains(negotiatedProto)) {
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Unwanted protocol was negotiated"));
return false;
}
@ -1353,8 +1353,8 @@ bool TlsCryptographSchannel::verifyHandshake()
&& configuration.peerVerifyMode() != QSslSocket::PeerVerifyMode::QueryPeer)) {
if (status != SEC_E_OK) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "Couldn't retrieve peer certificate, status:"
<< schannelErrorToString(status);
qCDebug(lcTlsBackend) << "Couldn't retrieve peer certificate, status:"
<< schannelErrorToString(status);
#endif
const QSslError error{ QSslError::NoPeerCertificate };
sslErrors += error;
@ -1370,7 +1370,7 @@ bool TlsCryptographSchannel::verifyHandshake()
if (!checkSslErrors() || q->state() != QAbstractSocket::ConnectedState) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << __func__ << "was unsuccessful. Paused:" << paused;
qCDebug(lcTlsBackend) << __func__ << "was unsuccessful. Paused:" << paused;
#endif
// If we're paused then checkSslErrors returned false, but it's not an error
return d->isPaused() && q->state() == QAbstractSocket::ConnectedState;
@ -1437,7 +1437,7 @@ bool TlsCryptographSchannel::renegotiate()
schannelState = SchannelState::PerformHandshake;
return true;
}
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
QSslSocket::tr("Renegotiation was unsuccessful: %1").arg(schannelErrorToString(status)));
return false;
}
@ -1541,7 +1541,7 @@ void TlsCryptographSchannel::transmit()
};
auto status = EncryptMessage(&contextHandle, 0, &message, 0);
if (status != SEC_E_OK) {
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QSslSocket::tr("Schannel failed to encrypt data: %1")
.arg(schannelErrorToString(status)));
return;
@ -1553,12 +1553,12 @@ void TlsCryptographSchannel::transmit()
fullMessage.resize(inputBuffers[0].cbBuffer + inputBuffers[1].cbBuffer + inputBuffers[2].cbBuffer);
const qint64 bytesWritten = plainSocket->write(fullMessage);
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, "Wrote %lld of total %d bytes", bytesWritten, fullMessage.length());
qCDebug(lcTlsBackend, "Wrote %lld of total %d bytes", bytesWritten, fullMessage.length());
#endif
if (bytesWritten >= 0) {
totalBytesWritten += bytesWritten;
} else {
d->setErrorAndEmit(plainSocket->error(), plainSocket->errorString());
setErrorAndEmit(d, plainSocket->error(), plainSocket->errorString());
return;
}
}
@ -1583,7 +1583,7 @@ void TlsCryptographSchannel::transmit()
if (missingData > plainSocket->bytesAvailable()
&& (!readBufferMaxSize || readBufferMaxSize >= missingData)) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, "We're still missing %lld bytes, will check later.", missingData);
qCDebug(lcTlsBackend, "We're still missing %lld bytes, will check later.", missingData);
#endif
break;
}
@ -1591,18 +1591,18 @@ void TlsCryptographSchannel::transmit()
missingData = 0;
const qint64 bytesRead = readToBuffer(intermediateBuffer, plainSocket);
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, "Read %lld encrypted bytes from the socket", bytesRead);
qCDebug(lcTlsBackend, "Read %lld encrypted bytes from the socket", bytesRead);
#endif
if (intermediateBuffer.length() == 0 || (hadIncompleteData && bytesRead == 0)) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, (hadIncompleteData ? "No new data received, leaving loop!"
: "Nothing to decrypt, leaving loop!"));
qCDebug(lcTlsBackend, (hadIncompleteData ? "No new data received, leaving loop!"
: "Nothing to decrypt, leaving loop!"));
#endif
break;
}
hadIncompleteData = false;
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, "Total amount of bytes to decrypt: %d", intermediateBuffer.length());
qCDebug(lcTlsBackend, "Total amount of bytes to decrypt: %d", intermediateBuffer.length());
#endif
SecBuffer dataBuffer[4]{
@ -1627,7 +1627,7 @@ void TlsCryptographSchannel::transmit()
dataBuffer[1].cbBuffer);
totalRead += dataBuffer[1].cbBuffer;
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, "Decrypted %lu bytes. New read buffer size: %d",
qCDebug(lcTlsBackend, "Decrypted %lu bytes. New read buffer size: %d",
dataBuffer[1].cbBuffer, buffer.size());
#endif
}
@ -1644,22 +1644,22 @@ void TlsCryptographSchannel::transmit()
if (status == SEC_E_INCOMPLETE_MESSAGE) {
missingData = checkIncompleteData(dataBuffer[0]);
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, "We didn't have enough data to decrypt anything, will try again!");
qCDebug(lcTlsBackend, "We didn't have enough data to decrypt anything, will try again!");
#endif
// We try again, but if we don't get any more data then we leave
hadIncompleteData = true;
} else if (status == SEC_E_INVALID_HANDLE) {
// I don't think this should happen, if it does we're done...
qCWarning(lcSsl, "The internal SSPI handle is invalid!");
qCWarning(lcTlsBackend, "The internal SSPI handle is invalid!");
Q_UNREACHABLE();
} else if (status == SEC_E_INVALID_TOKEN) {
qCWarning(lcSsl, "Got SEC_E_INVALID_TOKEN!");
qCWarning(lcTlsBackend, "Got SEC_E_INVALID_TOKEN!");
Q_UNREACHABLE(); // Happened once due to a bug, but shouldn't generally happen(?)
} else if (status == SEC_E_MESSAGE_ALTERED) {
// The message has been altered, disconnect now.
shutdown = true; // skips sending the shutdown alert
disconnectFromHost();
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
schannelErrorToString(status));
break;
} else if (status == SEC_E_OUT_OF_SEQUENCE) {
@ -1668,19 +1668,19 @@ void TlsCryptographSchannel::transmit()
// while SEC_E_MESSAGE_ALTERED is for stream-oriented ones (what we use).
shutdown = true; // skips sending the shutdown alert
disconnectFromHost();
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
schannelErrorToString(status));
break;
} else if (status == SEC_I_CONTEXT_EXPIRED) {
// 'remote' has initiated a shutdown
disconnectFromHost();
d->setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
setErrorAndEmit(d, QAbstractSocket::RemoteHostClosedError,
schannelErrorToString(status));
break;
} else if (status == SEC_I_RENEGOTIATE) {
// 'remote' wants to renegotiate
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, "The peer wants to renegotiate.");
qCDebug(lcTlsBackend, "The peer wants to renegotiate.");
#endif
schannelState = SchannelState::Renegotiate;
renegotiating = true;
@ -1716,7 +1716,7 @@ void TlsCryptographSchannel::sendShutdown()
if (status != SEC_E_OK) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "Failed to apply shutdown control token:" << schannelErrorToString(status);
qCDebug(lcTlsBackend) << "Failed to apply shutdown control token:" << schannelErrorToString(status);
#endif
return;
}
@ -1774,7 +1774,7 @@ void TlsCryptographSchannel::sendShutdown()
}
} else {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "Failed to initialize shutdown:" << schannelErrorToString(status);
qCDebug(lcTlsBackend) << "Failed to initialize shutdown:" << schannelErrorToString(status);
#endif
}
}
@ -1929,7 +1929,7 @@ bool TlsCryptographSchannel::checkSslErrors()
QSslSocketPrivate::pauseSocketNotifiers(q);
d->setPaused(true);
} else {
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
sslErrors.constFirst().errorString());
plainSocket->disconnectFromHost();
}
@ -1960,7 +1960,7 @@ void TlsCryptographSchannel::initializeCertificateStores()
if (!configuration.localCertificateChain().isEmpty()) {
if (configuration.privateKey().isNull()) {
d->setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError,
setErrorAndEmit(d, QAbstractSocket::SslInvalidUserDataError,
QSslSocket::tr("Cannot provide a certificate with no key"));
return;
}
@ -1968,7 +1968,7 @@ void TlsCryptographSchannel::initializeCertificateStores()
localCertificateStore = createStoreFromCertificateChain(configuration.localCertificateChain(),
configuration.privateKey());
if (localCertificateStore == nullptr)
qCWarning(lcSsl, "Failed to load certificate chain!");
qCWarning(lcTlsBackend, "Failed to load certificate chain!");
}
}
@ -1995,7 +1995,7 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext)
nullptr));
if (!tempCertCollection) {
#ifdef QSSLSOCKET_DEBUG
qCWarning(lcSsl, "Failed to create certificate store collection!");
qCWarning(lcTlsBackend, "Failed to create certificate store collection!");
#endif
return false;
}
@ -2008,12 +2008,12 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext)
auto rootStore = QHCertStorePointer(CertOpenSystemStore(0, L"ROOT"));
if (!rootStore) {
#ifdef QSSLSOCKET_DEBUG
qCWarning(lcSsl, "Failed to open the system root CA certificate store!");
qCWarning(lcTlsBackend, "Failed to open the system root CA certificate store!");
#endif
return false;
} else if (!CertAddStoreToCollection(tempCertCollection.get(), rootStore.get(), 0, 1)) {
#ifdef QSSLSOCKET_DEBUG
qCWarning(lcSsl, "Failed to add the system root CA certificate store to the certificate store collection!");
qCWarning(lcTlsBackend, "Failed to add the system root CA certificate store to the certificate store collection!");
#endif
return false;
}
@ -2021,7 +2021,7 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext)
if (caCertificateStore) {
if (!CertAddStoreToCollection(tempCertCollection.get(), caCertificateStore.get(), 0, 1)) {
#ifdef QSSLSOCKET_DEBUG
qCWarning(lcSsl, "Failed to add the user's CA certificate store to the certificate store collection!");
qCWarning(lcTlsBackend, "Failed to add the user's CA certificate store to the certificate store collection!");
#endif
return false;
}
@ -2029,7 +2029,7 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext)
if (!CertAddStoreToCollection(tempCertCollection.get(), certContext->hCertStore, 0, 0)) {
#ifdef QSSLSOCKET_DEBUG
qCWarning(lcSsl, "Failed to add certificate's origin store to the certificate store collection!");
qCWarning(lcTlsBackend, "Failed to add certificate's origin store to the certificate store collection!");
#endif
return false;
}
@ -2311,12 +2311,4 @@ bool TlsCryptographSchannel::rootCertOnDemandLoadingAllowed()
} // namespace QTlsPrivate
void QSslSocketPrivate::registerAdHocFactory()
{
// TLSTODO: this is a temporary solution, waiting for
// backends to move to ... plugins.
if (!backendSchannel())
qCWarning(lcTlsBackend, "Failed to create backend factory");
}
QT_END_NAMESPACE

View File

@ -55,12 +55,11 @@
QT_REQUIRE_CONFIG(schannel);
#include <QtCore/qt_windows.h>
#include "../shared/qwincrypt_p.h"
#include "qtlsbackend_schannel_p.h"
#include "qsslsocket_p.h"
#include "qwincrypt_p.h"
#include <QtNetwork/private/qsslsocket_p.h>
#define SECURITY_WIN32
#define SCHANNEL_USE_BLACKLISTS 1

View File

@ -53,7 +53,7 @@
#include <private/qtnetworkglobal_p.h>
#include "qtlsbackend_p.h"
#include <QtNetwork/private/qtlsbackend_p.h>
#include <QtCore/qglobal.h>
@ -62,6 +62,10 @@ QT_BEGIN_NAMESPACE
class QSchannelBackend : public QTlsBackend
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QTlsBackend_iid)
Q_INTERFACES(QTlsBackend)
public:
static void ensureInitializedImplementation();

View File

@ -37,18 +37,20 @@
**
****************************************************************************/
#include "qssl_p.h"
#include <QtNetwork/private/qssl_p.h>
#include "qtlskey_schannel_p.h"
#include "qtlsbackend_p.h"
#include "qsslkey_p.h"
#include "qsslkey.h"
#include "../shared/qwincrypt_p.h"
#include <QtNetwork/private/qtlsbackend_p.h>
#include <QtNetwork/private/qsslkey_p.h>
#include <QtNetwork/qsslkey.h>
#include <QtCore/qscopeguard.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qt_windows.h>
#include <wincrypt.h>
QT_BEGIN_NAMESPACE
namespace {

View File

@ -51,9 +51,9 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <private/qtlskey_generic_p.h>
#include "../shared/qtlskey_generic_p.h"
#include <QtCore/qglobal.h>

View File

@ -38,9 +38,10 @@
****************************************************************************/
#include "qtlskey_schannel_p.h"
#include "qsslcertificate_p.h"
#include "qx509_schannel_p.h"
#include <QtNetwork/private/qsslcertificate_p.h>
#include <memory>
QT_BEGIN_NAMESPACE

View File

@ -51,15 +51,13 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <private/qx509_generic_p.h>
#include "../shared/qx509_generic_p.h"
#include "../shared/qwincrypt_p.h"
#include <QtCore/qglobal.h>
#include <QtCore/qt_windows.h>
#include <wincrypt.h>
QT_BEGIN_NAMESPACE
namespace QTlsPrivate {

View File

@ -0,0 +1,33 @@
qt_internal_add_plugin(QSecureTransportBackend
OUTPUT_NAME securetransportbackend
CLASS_NAME QSecureTransportBackend
TYPE tls
DEFAULT_IF APPLE
SOURCES
../shared/qsslsocket_mac_shared.cpp
../shared/qtlskey_generic_p.h
../shared/qtlskey_generic.cpp
../shared/qx509_base_p.h
../shared/qx509_base.cpp
../shared/qx509_generic_p.h
../shared/qx509_generic.cpp
../shared/qtlskey_base_p.h
../shared/qtlskey_base.cpp
../shared/qsslsocket_qt.cpp
../shared/qasn1element_p.h
../shared/qasn1element.cpp
qtlsbackend_st.cpp
qtlsbackend_st_p.h
qx509_st.cpp
qtlskey_st.cpp
qtlskey_st_p.h
qx509_st_p.h
qtls_st.cpp
qtls_st_p.h
PUBLIC_LIBRARIES
Qt::NetworkPrivate
Qt::CorePrivate
LIBRARIES
${FWCoreFoundation}
${FWSecurity}
)

View File

@ -38,16 +38,17 @@
**
****************************************************************************/
#include "qsslsocket.h"
#include "qssl_p.h"
#include "qtls_st_p.h"
#include "qasn1element_p.h"
#include "qsslcertificate_p.h"
#include "qtlsbackend_st_p.h"
#include "qsslcipher_p.h"
#include "qtlskey_st_p.h"
#include "qsslkey_p.h"
#include <QtNetwork/private/qssl_p.h>
#include <QtNetwork/private/qsslcertificate_p.h>
#include <QtNetwork/private/qsslcipher_p.h>
#include <QtNetwork/private/qsslkey_p.h>
#include <QtNetwork/qsslsocket.h>
#include <QtCore/qmessageauthenticationcode.h>
#include <QtCore/qoperatingsystemversion.h>
@ -75,8 +76,6 @@
QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QSecureTransportBackend, backendSecureTransport)
// Defined in qsslsocket_qt.cpp.
QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key,
const QString &passPhrase);
@ -205,7 +204,7 @@ SSLContextRef qt_createSecureTransportContext(QSslSocket::SslMode mode)
// We never use kSSLDatagramType, so it's kSSLStreamType unconditionally.
SSLContextRef context = SSLCreateContext(nullptr, side, kSSLStreamType);
if (!context)
qCWarning(lcSsl) << "SSLCreateContext failed";
qCWarning(lcTlsBackend) << "SSLCreateContext failed";
return context;
}
@ -457,9 +456,9 @@ void TlsCryptographSecureTransport::startClientEncryption()
if (!initSslContext()) {
Q_ASSERT(d);
// Error description/code were set, 'error' emitted
// by initSslContext, but OpenSSL socket also sets error
// by initSslContext, but OpenSSL socket also sets error,
// emits a signal twice, so ...
d->setErrorAndEmit(QAbstractSocket::SslInternalError, QStringLiteral("Unable to init SSL Context"));
setErrorAndEmit(d, QAbstractSocket::SslInternalError, QStringLiteral("Unable to init SSL Context"));
return;
}
@ -472,7 +471,7 @@ void TlsCryptographSecureTransport::startServerEncryption()
// Error description/code were set, 'error' emitted
// by initSslContext, but OpenSSL socket also sets error
// emits a signal twice, so ...
d->setErrorAndEmit(QAbstractSocket::SslInternalError, QStringLiteral("Unable to init SSL Context"));
setErrorAndEmit(d, QAbstractSocket::SslInternalError, QStringLiteral("Unable to init SSL Context"));
return;
}
@ -503,8 +502,8 @@ void TlsCryptographSecureTransport::transmit()
qCDebug(lcTlsBackend) << d->plainTcpSocket() << "SSLWrite returned" << err;
#endif
if (err != errSecSuccess && err != errSSLWouldBlock) {
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QStringLiteral("SSLWrite failed: %1").arg(err));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QStringLiteral("SSLWrite failed: %1").arg(err));
break;
}
@ -542,12 +541,12 @@ void TlsCryptographSecureTransport::transmit()
#endif
if (err == errSSLClosedGraceful) {
shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves
d->setErrorAndEmit(QAbstractSocket::RemoteHostClosedError,
QSslSocket::tr("The TLS/SSL connection has been closed"));
setErrorAndEmit(d, QAbstractSocket::RemoteHostClosedError,
QSslSocket::tr("The TLS/SSL connection has been closed"));
break;
} else if (err != errSecSuccess && err != errSSLWouldBlock) {
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QStringLiteral("SSLRead failed: %1").arg(err));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QStringLiteral("SSLRead failed: %1").arg(err));
break;
}
@ -662,7 +661,7 @@ bool TlsCryptographSecureTransport::initSslContext()
context.reset(qt_createSecureTransportContext(mode));
if (!context) {
d->setErrorAndEmit(QAbstractSocket::SslInternalError, QStringLiteral("SSLCreateContext failed"));
setErrorAndEmit(d, QAbstractSocket::SslInternalError, QStringLiteral("SSLCreateContext failed"));
return false;
}
@ -671,8 +670,8 @@ bool TlsCryptographSecureTransport::initSslContext()
reinterpret_cast<SSLWriteFunc>(&TlsCryptographSecureTransport::WriteCallback));
if (err != errSecSuccess) {
destroySslContext();
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QStringLiteral("SSLSetIOFuncs failed: %1").arg(err));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QStringLiteral("SSLSetIOFuncs failed: %1").arg(err));
return false;
}
@ -685,14 +684,14 @@ bool TlsCryptographSecureTransport::initSslContext()
QAbstractSocket::SocketError errorCode = QAbstractSocket::UnknownSocketError;
if (!setSessionCertificate(errorDescription, errorCode)) {
destroySslContext();
d->setErrorAndEmit(errorCode, errorDescription);
setErrorAndEmit(d, errorCode, errorDescription);
return false;
}
}
if (!setSessionProtocol()) {
destroySslContext();
d->setErrorAndEmit(QAbstractSocket::SslInternalError, QStringLiteral("Failed to set protocol version"));
setErrorAndEmit(d, QAbstractSocket::SslInternalError, QStringLiteral("Failed to set protocol version"));
return false;
}
@ -742,8 +741,8 @@ bool TlsCryptographSecureTransport::initSslContext()
if (err != errSecSuccess) {
destroySslContext();
d->setErrorAndEmit(QSslSocket::SslInternalError,
QStringLiteral("SSLSetSessionOption failed: %1").arg(err));
setErrorAndEmit(d, QSslSocket::SslInternalError,
QStringLiteral("SSLSetSessionOption failed: %1").arg(err));
return false;
}
//
@ -759,8 +758,8 @@ bool TlsCryptographSecureTransport::initSslContext()
if (err != errSecSuccess) {
destroySslContext();
d->setErrorAndEmit(QAbstractSocket::SslInternalError,
QStringLiteral("failed to set SSL context option in server mode: %1").arg(err));
setErrorAndEmit(d, QAbstractSocket::SslInternalError,
QStringLiteral("failed to set SSL context option in server mode: %1").arg(err));
return false;
}
}
@ -1033,8 +1032,8 @@ bool TlsCryptographSecureTransport::verifyPeerTrust()
// !trust - SSLCopyPeerTrust can return errSecSuccess but null trust.
if (err != errSecSuccess || !trust) {
if (!canIgnoreVerify) {
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
QStringLiteral("Failed to obtain peer trust: %1").arg(err));
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
QStringLiteral("Failed to obtain peer trust: %1").arg(err));
plainSocket->disconnectFromHost();
return false;
} else {
@ -1055,8 +1054,8 @@ bool TlsCryptographSecureTransport::verifyPeerTrust()
if (err != errSecSuccess) {
// We can not ignore this, it's not even about trust verification
// probably ...
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
QStringLiteral("SecTrustEvaluate failed: %1").arg(err));
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
QStringLiteral("SecTrustEvaluate failed: %1").arg(err));
plainSocket->disconnectFromHost();
return false;
}
@ -1214,8 +1213,8 @@ bool TlsCryptographSecureTransport::checkSslErrors()
QSslSocketPrivate::pauseSocketNotifiers(q);
d->setPaused(true);
} else {
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
sslErrors.constFirst().errorString());
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
sslErrors.constFirst().errorString());
Q_ASSERT(d->plainTcpSocket());
d->plainTcpSocket()->disconnectFromHost();
}
@ -1258,7 +1257,7 @@ bool TlsCryptographSecureTransport::startHandshake()
// setSessionCertificate does not fail if we have no certificate.
// Failure means a real error (invalid certificate, no private key, etc).
if (!setSessionCertificate(errorDescription, errorCode)) {
d->setErrorAndEmit(errorCode, errorDescription);
setErrorAndEmit(d, errorCode, errorDescription);
renegotiating = false;
return false;
} else {
@ -1275,8 +1274,8 @@ bool TlsCryptographSecureTransport::startHandshake()
}
renegotiating = false;
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError,
QStringLiteral("SSLHandshake failed: %1").arg(err));
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
QStringLiteral("SSLHandshake failed: %1").arg(err));
plainSocket->disconnectFromHost();
return false;
}
@ -1291,7 +1290,7 @@ bool TlsCryptographSecureTransport::startHandshake()
// check protocol version ourselves, as Secure Transport does not enforce
// the requested min / max versions.
if (!verifySessionProtocol()) {
d->setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, QStringLiteral("Protocol version mismatch"));
setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError, QStringLiteral("Protocol version mismatch"));
plainSocket->disconnectFromHost();
renegotiating = false;
return false;
@ -1320,12 +1319,4 @@ QList<QSslError> TlsCryptographSecureTransport::tlsErrors() const
} // namespace QTlsPrivate
void QSslSocketPrivate::registerAdHocFactory()
{
// TLSTODO: this is a temporary solution, waiting for
// backends to move to ... plugins.
if (!backendSecureTransport())
qCWarning(lcTlsBackend, "Failed to create backend factory");
}
QT_END_NAMESPACE

View File

@ -60,8 +60,8 @@
#include <QtCore/qglobal.h>
#include <QtCore/qlist.h>
#include "qabstractsocket.h"
#include "qsslsocket_p.h"
#include <QtNetwork/qabstractsocket.h>
#include <QtNetwork/private/qsslsocket_p.h>
#include <Security/Security.h>
#include <Security/SecureTransport.h>

View File

@ -51,9 +51,9 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qtlsbackend_p.h"
#include <QtNetwork/private/qtlsbackend_p.h>
#include <QtCore/qglobal.h>
@ -62,6 +62,10 @@ QT_BEGIN_NAMESPACE
class QSecureTransportBackend : public QTlsBackend
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QTlsBackend_iid)
Q_INTERFACES(QTlsBackend)
private:
QString tlsLibraryVersionString() const override;

View File

@ -39,9 +39,10 @@
****************************************************************************/
#include "qtlskey_st_p.h"
#include "qsslkey_p.h"
#include <qbytearray.h>
#include <QtNetwork/private/qsslkey_p.h>
#include <QtCore/qbytearray.h>
#include <CommonCrypto/CommonCrypto.h>

View File

@ -51,9 +51,9 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <private/qtlskey_generic_p.h>
#include "../shared/qtlskey_generic_p.h"
#include <QtCore/qglobal.h>

View File

@ -51,9 +51,9 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <private/qx509_generic_p.h>
#include "../shared/qx509_generic_p.h"
#include <QtCore/qglobal.h>

View File

@ -115,7 +115,7 @@ QT_BEGIN_NAMESPACE
#define AES192_CBC_ENCRYPTION_OID QByteArrayLiteral(AES_OID "22") // Not (yet) implemented
#define AES256_CBC_ENCRYPTION_OID QByteArrayLiteral(AES_OID "42") // Not (yet) implemented
class Q_AUTOTEST_EXPORT QAsn1Element
class QAsn1Element
{
public:
enum ElementType {

View File

@ -51,15 +51,16 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
QT_REQUIRE_CONFIG(dtls);
#include "qsslconfiguration.h"
#include "qtlsbackend_p.h"
#include "qsslcipher.h"
#include "qsslsocket.h"
#include "qssl.h"
#include <QtNetwork/private/qtlsbackend_p.h>
#include <QtNetwork/qsslconfiguration.h>
#include <QtNetwork/qsslcipher.h>
#include <QtNetwork/qsslsocket.h>
#include <QtNetwork/qssl.h>
#include <QtNetwork/qhostaddress.h>

View File

@ -38,17 +38,17 @@
**
****************************************************************************/
#include "qsslcertificate.h"
#include <QtNetwork/private/qtlsbackend_p.h>
#include <QtNetwork/qsslcertificate.h>
#include <QtCore/qglobal.h>
#include <QtCore/qdebug.h>
#ifdef Q_OS_MACOS
#include "qtlsbackend_p.h"
#include <private/qcore_mac_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/private/qcore_mac_p.h>
#include <CoreFoundation/CFArray.h>
#include <Security/Security.h>
@ -57,6 +57,8 @@
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcTlsBackend)
#ifdef Q_OS_MACOS
namespace {
@ -132,7 +134,7 @@ QList<QSslCertificate> systemCaCertificates()
QCFType<CFDataRef> derData = SecCertificateCopyData(cfCert);
if (isCaCertificateTrusted(cfCert, dom)) {
if (derData == nullptr) {
qCWarning(lcSsl, "Error retrieving a CA certificate from the system store");
qCWarning(lcTlsBackend, "Error retrieving a CA certificate from the system store");
} else {
systemCerts << QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der);
}

View File

@ -36,14 +36,16 @@
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qasn1element_p.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qdatastream.h>
#include <QtCore/qmessageauthenticationcode.h>
#include <QtCore/qrandom.h>
#include "qsslsocket_p.h"
#include "qasn1element_p.h"
#include "qsslkey_p.h"
#include <QtNetwork/private/qsslsocket_p.h>
#include <QtNetwork/private/qsslkey_p.h>
QT_BEGIN_NAMESPACE

View File

@ -51,11 +51,11 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <private/qtlsbackend_p.h>
#include <QtNetwork/private/qtlsbackend_p.h>
#include <qssl.h>
#include <QtNetwork/qssl.h>
#include <QtCore/qglobal.h>
@ -63,8 +63,6 @@ QT_BEGIN_NAMESPACE
namespace QTlsPrivate {
// TLSTODO: Note, 'base' is supposed to move to plugins together with
// 'generic' and 'backendXXX'.
class TlsKeyBase : public TlsKey
{
public:
@ -97,9 +95,7 @@ protected:
static QByteArray pkcs8Header(bool encrypted);
static QByteArray pkcs8Footer(bool encrypted);
static bool isEncryptedPkcs8(const QByteArray &der);
public:
// TLSTODO: this public is quick fix needed by old _openssl classes
// will become non-public as soon as those classes fixed.
bool keyIsNull = true;
KeyType keyType = QSsl::PublicKey;
KeyAlgorithm keyAlgorithm = QSsl::Opaque;

View File

@ -40,7 +40,8 @@
#include "qtlskey_generic_p.h"
#include "qasn1element_p.h"
#include "qsslkey_p.h"
#include <QtNetwork/private/qsslkey_p.h>
#include <QtNetwork/qpassworddigestor.h>

View File

@ -51,10 +51,12 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtlsbackend_p.h>
#include "qtlskey_base_p.h"
#include <private/qtlskey_base_p.h>
#include <private/qtlsbackend_p.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qglobal.h>

View File

@ -51,11 +51,11 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <private/qtlsbackend_p.h>
#include <QtNetwork/private/qtlsbackend_p.h>
#include <qssl.h>
#include <QtNetwork/qssl.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qstring.h>

View File

@ -37,15 +37,16 @@
**
****************************************************************************/
#include "qsslcertificate_p.h"
#include "qx509_generic_p.h"
#include <QtNetwork/private/qsslcertificate_p.h>
#include <QtNetwork/private/qssl_p.h>
#include "qasn1element_p.h"
#include "qx509_generic_p.h"
#include "qssl_p.h"
#include <QtNetwork/qhostaddress.h>
#include <qhostaddress.h>
#include <qendian.h>
#include <qhash.h>
#include <QtCore/qendian.h>
#include <QtCore/qhash.h>
#include <memory>

View File

@ -50,10 +50,11 @@
// We mean it.
//
#include <private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <private/qtlsbackend_p.h>
#include <private/qx509_base_p.h>
#include <QtNetwork/private/qtlsbackend_p.h>
#include "qx509_base_p.h"
#include <QtCore/qbytearray.h>
#include <QtCore/qglobal.h>
@ -62,7 +63,6 @@ QT_BEGIN_NAMESPACE
namespace QTlsPrivate {
// TLSTODO: This class is what previously was known as qsslcertificate_qt.
// A part of SecureTransport and Schannel plugin.
class X509CertificateGeneric : public X509CertificateBase
{

View File

@ -45,12 +45,6 @@
#include <QtCore/qthread.h>
#include <QtCore/qurl.h>
#ifndef QT_NO_SSL
#ifndef QT_NO_OPENSSL
#include <QtNetwork/private/qsslsocket_openssl_symbols_p.h>
#endif // NO_OPENSSL
#endif // NO_SSL
#include <cstdlib>
#include <memory>
#include <string>

View File

@ -26,6 +26,7 @@
**
****************************************************************************/
#include <QtNetwork/qtnetworkglobal.h>
#include <QTest>
#include <QSemaphore>
@ -71,6 +72,7 @@
#ifndef QT_NO_SSL
#include <QtNetwork/qsslerror.h>
#include <QtNetwork/qsslconfiguration.h>
#include <QtNetwork/qsslsocket.h>
#ifdef QT_BUILD_INTERNAL
#include <QtNetwork/private/qsslconfiguration_p.h>
#endif
@ -105,11 +107,10 @@ Q_DECLARE_METATYPE(QNetworkProxyQuery)
typedef QSharedPointer<QNetworkReply> QNetworkReplyPtr;
#ifndef QT_NO_OPENSSL
QT_BEGIN_NAMESPACE
// Technically, a workaround, and only needed for OpenSSL:
void qt_ForceTlsSecurityLevel();
QT_END_NAMESPACE
#endif
class MyCookieJar;
class tst_QNetworkReply: public QObject
@ -163,11 +164,14 @@ class tst_QNetworkReply: public QObject
#endif
QNetworkAccessManager manager;
MyCookieJar *cookieJar;
#ifndef QT_NO_SSL
#if QT_CONFIG(ssl)
QSslConfiguration storedSslConfiguration;
QList<QSslError> storedExpectedSslErrors;
static const QString certsFilePath;
#endif
#endif // QT_CONFIG(ssl)
bool isSecureTransport = false;
bool isSchannel = false;
using QObject::connect;
static bool connect(const QNetworkReplyPtr &ptr, const char *signal, const QObject *receiver, const char *slot, Qt::ConnectionType ct = Qt::AutoConnection)
@ -1289,9 +1293,14 @@ tst_QNetworkReply::tst_QNetworkReply()
#ifndef QT_NO_NETWORKPROXY
qRegisterMetaType<QNetworkProxy>();
#endif
#ifndef QT_NO_SSL
#if QT_CONFIG(ssl)
qRegisterMetaType<QList<QSslError> >();
isSecureTransport = QSslSocket::activeBackend() == QStringLiteral("securetransport");
if (!isSecureTransport)
isSchannel = QSslSocket::activeBackend() == QStringLiteral("schannel");
#endif
qRegisterMetaType<QNetworkReply::NetworkError>();
uniqueExtension = createUniqueExtension();
@ -1577,10 +1586,8 @@ void tst_QNetworkReply::initTestCase()
QString::fromLatin1("Couldn't find echo dir starting from %1.").arg(QDir::currentPath())));
cleanupTestData();
#ifndef QT_NO_OPENSSL
QT_PREPEND_NAMESPACE(qt_ForceTlsSecurityLevel)();
#endif // QT_NO_OPENSSL
QT_PREPEND_NAMESPACE(qt_ForceTlsSecurityLevel)();
}
void tst_QNetworkReply::cleanupTestCase()
@ -2781,9 +2788,9 @@ void tst_QNetworkReply::putToHttpMultipart()
#ifndef QT_NO_SSL
void tst_QNetworkReply::putToHttps_data()
{
#if QT_CONFIG(securetransport)
QSKIP("SecTrustEvaluate() returns recoverable error, update the certificate on server");
#endif
if (isSecureTransport)
QSKIP("SecTrustEvaluate() returns recoverable error, update the certificate on server");
uniqueExtension = createUniqueExtension();
putToFile_data();
}
@ -2825,9 +2832,9 @@ void tst_QNetworkReply::putToHttps()
void tst_QNetworkReply::putToHttpsSynchronous_data()
{
#if QT_CONFIG(securetransport)
QSKIP("SecTrustEvalueate() retruns recoverable error, update the server's certificate");
#endif
if (isSecureTransport)
QSKIP("SecTrustEvalueate() retruns recoverable error, update the server's certificate");
uniqueExtension = createUniqueExtension();
putToFile_data();
}
@ -2873,9 +2880,9 @@ void tst_QNetworkReply::putToHttpsSynchronous()
void tst_QNetworkReply::postToHttps_data()
{
#if QT_CONFIG(securetransport)
QSKIP("SecTrustEvaluate() returns recoverable error, update the certificate on server");
#endif
if (isSecureTransport)
QSKIP("SecTrustEvaluate() returns recoverable error, update the certificate on server");
putToFile_data();
}
@ -2907,9 +2914,9 @@ void tst_QNetworkReply::postToHttps()
void tst_QNetworkReply::postToHttpsSynchronous_data()
{
#if QT_CONFIG(securetransport)
QSKIP("SecTrustEvaluate() returns recoverable error, update the certificate on server");
#endif
if (isSecureTransport)
QSKIP("SecTrustEvaluate() returns recoverable error, update the certificate on server");
putToFile_data();
}
@ -2946,9 +2953,9 @@ void tst_QNetworkReply::postToHttpsSynchronous()
void tst_QNetworkReply::postToHttpsMultipart_data()
{
#if QT_CONFIG(securetransport)
QSKIP("SecTrustEvaluate() returns recoverable error, update the certificate on server");
#endif
if (isSecureTransport)
QSKIP("SecTrustEvaluate() returns recoverable error, update the certificate on server");
postToHttpMultipart_data();
}
@ -6467,23 +6474,23 @@ void tst_QNetworkReply::sslConfiguration_data()
QTest::newRow("empty") << QSslConfiguration() << false;
QSslConfiguration conf = QSslConfiguration::defaultConfiguration();
QTest::newRow("default") << conf << false; // does not contain test server cert
#if QT_CONFIG(securetransport)
qWarning("SecTrustEvaluate() will fail, update the certificate on server");
#else
QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(testDataDir + certsFilePath);
conf.setCaCertificates(testServerCert);
if (isSecureTransport) {
qWarning("SecTrustEvaluate() will fail, update the certificate on server");
} else {
QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(testDataDir + certsFilePath);
conf.setCaCertificates(testServerCert);
QTest::newRow("set-root-cert") << conf << true;
conf.setProtocol(QSsl::SecureProtocols);
QTest::newRow("secure") << conf << true;
#endif
QTest::newRow("set-root-cert") << conf << true;
conf.setProtocol(QSsl::SecureProtocols);
QTest::newRow("secure") << conf << true;
}
}
void tst_QNetworkReply::encrypted()
{
#if QT_CONFIG(securetransport)
QSKIP("SecTrustEvalute() fails with old server certificate");
#endif
if (isSecureTransport)
QSKIP("SecTrustEvalute() fails with old server certificate");
QUrl url("https://" + QtNetworkSettings::httpServerName());
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
@ -6556,9 +6563,8 @@ void tst_QNetworkReply::sslSessionSharing_data()
void tst_QNetworkReply::sslSessionSharing()
{
#if QT_CONFIG(schannel) || defined(QT_SECURETRANSPORT)
QSKIP("Not implemented with SecureTransport/Schannel");
#endif
if (isSchannel || isSecureTransport)
QSKIP("Not implemented with SecureTransport/Schannel");
QString urlString("https://" + QtNetworkSettings::httpServerName());
QList<QNetworkReplyPtr> replies;
@ -6627,9 +6633,8 @@ void tst_QNetworkReply::sslSessionSharingFromPersistentSession_data()
void tst_QNetworkReply::sslSessionSharingFromPersistentSession()
{
#if QT_CONFIG(schannel) || defined(QT_SECURETRANSPORT)
QSKIP("Not implemented with SecureTransport/Schannel");
#endif
if (isSchannel || isSecureTransport)
QSKIP("Not implemented with SecureTransport/Schannel");
QString urlString("https://" + QtNetworkSettings::httpServerName());
@ -7752,17 +7757,17 @@ void tst_QNetworkReply::synchronousRequest_data()
// ### we would need to enflate (un-deflate) the file content and compare the sizes
<< QString("text/plain");
#ifndef QT_NO_SSL
#if QT_CONFIG(securetransport)
qWarning("Skipping https scheme, SecTrustEvalue() fails, update the certificate on server");
#else
QTest::newRow("https")
<< QUrl("https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt")
<< QString("file:" + testDataDir + "/rfc3252.txt")
<< true
<< QString("text/plain");
#endif
#endif
#if QT_CONFIG(ssl)
if (isSecureTransport) {
qWarning("Skipping https scheme, SecTrustEvalue() fails, update the certificate on server");
} else {
QTest::newRow("https")
<< QUrl("https://" + QtNetworkSettings::httpServerName() + "/qtest/rfc3252.txt")
<< QString("file:" + testDataDir + "/rfc3252.txt")
<< true
<< QString("text/plain");
}
#endif // QT_CONFIG(ssl)
QTest::newRow("data")
<< QUrl(QString::fromLatin1("data:text/plain,hello world"))

View File

@ -12,7 +12,7 @@ if(QT_FEATURE_private_tests AND QT_FEATURE_ssl)
add_subdirectory(qsslsocket)
add_subdirectory(qsslsocket_onDemandCertificates_member)
add_subdirectory(qsslsocket_onDemandCertificates_static)
add_subdirectory(qasn1element)
# add_subdirectory(qasn1element)
add_subdirectory(qssldiffiehellmanparameters)
endif()
if(QT_FEATURE_dtls AND QT_FEATURE_private_tests AND QT_FEATURE_ssl)

View File

@ -31,8 +31,6 @@
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include <QtNetwork/private/qsslsocket_openssl_symbols_p.h>
#include <QtNetwork/qsslcertificate.h>
#include <QtNetwork/qtcpserver.h>
#include <QtNetwork/qsslerror.h>
@ -66,6 +64,9 @@ QT_BEGIN_NAMESPACE
namespace {
// TLSTODO: the test is temporarily disabled due to openssl code
// moved into plugin and not in QtNetwork anymore.
#if 0
using OcspResponse = QSharedPointer<OCSP_RESPONSE>;
using BasicResponse = QSharedPointer<OCSP_BASICRESP>;
using SingleResponse = QSharedPointer<OCSP_SINGLERESP>;
@ -74,6 +75,9 @@ using EvpKey = QSharedPointer<EVP_PKEY>;
using Asn1Time = QSharedPointer<ASN1_TIME>;
using CertificateChain = QList<QSslCertificate>;
// TLSTODO: test temporarily disabled due to openssl code moved
// into plugin and not in QtNetwork anymore.
using NativeX509Ptr = X509 *;
class X509Stack {
@ -372,12 +376,16 @@ void OcspServer::incomingConnection(qintptr socketDescriptor)
serverSocket.startServerEncryption();
}
#endif // if 0
} // unnamed namespace
class tst_QOcsp : public QObject
{
Q_OBJECT
// TLSTODO: test temporarily disabled due to openssl code moved
// into plugin and not in QtNetwork anymore.
#if 0
public slots:
void initTestCase();
@ -426,6 +434,7 @@ private:
QSslError::OcspResponseCertIdUnknown,
QSslError::OcspResponseExpired,
QSslError::OcspStatusUnknown};
#endif // if 0
};
#define QCOMPARE_SINGLE_ERROR(sslSocket, expectedError) \
@ -446,6 +455,9 @@ private:
QSslKey key; \
QVERIFY(loadPrivateKey(QLatin1String(keyFileName), key))
// TLSTODO: test temporarily disabled due to openssl code moved
// into plugin and not in QtNetwork anymore.
#if 0
QString tst_QOcsp::certDirPath;
void tst_QOcsp::initTestCase()
@ -827,6 +839,8 @@ CertificateChain tst_QOcsp::subjectToChain(const CertificateChain &chain)
return CertificateChain() << chain[0];
}
#endif // if 0
QT_END_NAMESPACE
QTEST_MAIN(tst_QOcsp)

View File

@ -28,6 +28,7 @@
#include <QTest>
#include <qsslcertificate.h>
#include <qsslkey.h>
#include <qsslsocket.h>
@ -120,6 +121,7 @@ private slots:
#endif
private:
QString testDataDir;
bool isNonOpenSslTls = false;
};
void tst_QSslCertificate::initTestCase()
@ -129,6 +131,13 @@ void tst_QSslCertificate::initTestCase()
testDataDir = QCoreApplication::applicationDirPath();
if (!testDataDir.endsWith(QLatin1String("/")))
testDataDir += QLatin1String("/");
#if QT_CONFIG(opensslv11)
// In the presence of 'openssl' backend, QSslSocket will
// select 'openssl' as the default one.
isNonOpenSslTls = false;
#else
isNonOpenSslTls = true;
#endif // QT_CONFIG(ssl)
QDir dir(testDataDir + "certificates");
QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable);
@ -889,9 +898,9 @@ void tst_QSslCertificate::task256066toPem()
void tst_QSslCertificate::nulInCN()
{
#if QT_CONFIG(securetransport) || QT_CONFIG(schannel)
QSKIP("Generic QSslCertificatePrivate fails this test");
#endif
if (isNonOpenSslTls)
QSKIP("Generic QSslCertificatePrivate fails this test");
QList<QSslCertificate> certList =
QSslCertificate::fromPath(testDataDir + "more-certificates/badguy-nul-cn.crt", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString);
QCOMPARE(certList.size(), 1);
@ -908,9 +917,10 @@ void tst_QSslCertificate::nulInCN()
void tst_QSslCertificate::nulInSan()
{
#if QT_CONFIG(securetransport) || QT_CONFIG(schannel)
QSKIP("Generic QSslCertificatePrivate fails this test");
#endif
if (isNonOpenSslTls)
QSKIP("Generic QSslCertificatePrivate fails this test");
QList<QSslCertificate> certList =
QSslCertificate::fromPath(testDataDir + "more-certificates/badguy-nul-san.crt", QSsl::Pem, QSslCertificate::PatternSyntax::FixedString);
QCOMPARE(certList.size(), 1);
@ -1047,9 +1057,9 @@ void tst_QSslCertificate::subjectAndIssuerAttributes()
void tst_QSslCertificate::verify()
{
#if QT_CONFIG(securetransport)
QSKIP("Not implemented in SecureTransport");
#endif
if (isNonOpenSslTls)
QSKIP("Not implemented in SecureTransport or Schannel");
QList<QSslError> errors;
QList<QSslCertificate> toVerify;
@ -1059,9 +1069,6 @@ void tst_QSslCertificate::verify()
qPrintable(QString("errors: %1").arg(toString(errors))) \
)
#ifdef QT_NO_OPENSSL
QEXPECT_FAIL("", "Verifying a chain is not supported without openssl", Abort); // TODO?
#endif
// Empty chain is unspecified error
errors = QSslCertificate::verify(toVerify);
VERIFY_VERBOSE(errors.count() == 1);

View File

@ -26,7 +26,6 @@
**
****************************************************************************/
#include <QTest>
#include <qsslkey.h>
#include <qsslsocket.h>
@ -46,11 +45,18 @@
#include "private/qsslkey_p.h"
#define TEST_CRYPTO
#endif
#ifndef QT_NO_OPENSSL
#include "private/qsslsocket_openssl_symbols_p.h"
#endif
// TLSTODO: find another solution, for now this code
// (OpenSSL specific) is a part of plugin, not in
// QtNetwork anymore.
//#ifndef QT_NO_OPENSSL
// #include "private/qsslsocket_openssl_symbols_p.h"
//#endif
#endif
#if QT_CONFIG(ssl)
#include <QtNetwork/qsslsocket.h>
#endif // QT_CONFIG(ssl)
#include <algorithm>
class tst_QSslKey : public QObject
@ -113,11 +119,15 @@ private:
bool fileContainsUnsupportedEllipticCurve(const QString &fileName) const;
QVector<QString> unsupportedCurves;
bool isOpenSsl = false;
bool isSecureTransport = false;
bool isSchannel = false;
};
tst_QSslKey::tst_QSslKey()
{
#ifndef QT_NO_SSL
#if QT_CONFIG(ssl)
const QString expectedCurves[] = {
// See how we generate them in keys/genkey.sh.
QStringLiteral("secp224r1"),
@ -140,6 +150,13 @@ tst_QSslKey::tst_QSslKey()
unsupportedCurves.push_back(requestedEc);
}
}
// Alas, we don't use network-private (and why?).
const auto backendName = QSslSocket::activeBackend();
isOpenSsl = backendName == QStringLiteral("openssl");
if (!isOpenSsl)
isSecureTransport = backendName == QStringLiteral("securetransport");
if (!isOpenSsl && !isSecureTransport)
isSchannel = backendName == QStringLiteral("schannel");
#else
unsupportedCurves = {}; // not unsued anymore.
#endif
@ -221,10 +238,12 @@ void tst_QSslKey::createPlainTestRows(bool pemOnly)
foreach (KeyInfo keyInfo, keyInfoList) {
if (pemOnly && keyInfo.format != QSsl::EncodingFormat::Pem)
continue;
#if QT_CONFIG(schannel)
if (keyInfo.fileInfo.fileName().contains("RC2-64"))
continue; // Schannel treats RC2 as 128 bit
#endif
if (isSchannel) {
if (keyInfo.fileInfo.fileName().contains("RC2-64"))
continue; // Schannel treats RC2 as 128 bit
}
#if QT_CONFIG(ssl) && defined(QT_NO_OPENSSL) // generic backend
if (keyInfo.fileInfo.fileName().contains(QRegularExpression("-aes\\d\\d\\d-")))
continue; // No AES support in the generic back-end
@ -272,7 +291,12 @@ void tst_QSslKey::constructorHandle()
{
#ifndef QT_BUILD_INTERNAL
QSKIP("This test requires -developer-build.");
#else
#endif // previously, else, see if 0 below.
// TLSTODO: OpenSSL-specific code and symbols are now
// part of 'openssl' plugin, not in QtNetwork anymore.
// For now - disabling.
#if 0
if (!QSslSocket::supportsSsl())
return;
@ -328,7 +352,8 @@ void tst_QSslKey::constructorHandle()
QCOMPARE(key.type(), type);
QCOMPARE(key.length(), length);
QCOMPARE(q_EVP_PKEY_cmp(origin, handle), 1);
#endif
#endif // if 0
}
#endif // !QT_NO_OPENSSL
@ -419,13 +444,13 @@ void tst_QSslKey::toPemOrDer()
QByteArray dataTag = QByteArray(QTest::currentDataTag());
if (dataTag.contains("-pkcs8-")) // these are encrypted
QSKIP("Encrypted PKCS#8 keys gets decrypted when loaded. So we can't compare it to the encrypted version.");
#ifndef QT_NO_OPENSSL
if (dataTag.contains("pkcs8"))
QSKIP("OpenSSL converts PKCS#8 keys to other formats, invalidating comparisons.");
#else // !openssl
if (dataTag.contains("pkcs8") && dataTag.contains("rsa"))
QSKIP("PKCS#8 RSA keys are changed into a different format in the generic back-end, meaning the comparison fails.");
#endif // openssl
if (dataTag.contains("pkcs8")) {
if (isOpenSsl)
QSKIP("OpenSSL converts PKCS#8 keys to other formats, invalidating comparisons.");
else if (dataTag.contains("rsa"))
QSKIP("PKCS#8 RSA keys are changed into a different format in the generic back-end, meaning the comparison fails.");
}
QByteArray encoded = readFile(absFilePath);
QSslKey key(encoded, algorithm, format, type);
@ -759,12 +784,13 @@ void tst_QSslKey::encrypt()
QFETCH(QByteArray, cipherText);
QFETCH(QByteArray, iv);
#if QT_CONFIG(schannel)
QEXPECT_FAIL("RC2-40-CBC, length 0", "Schannel treats RC2 as 128-bit", Abort);
QEXPECT_FAIL("RC2-40-CBC, length 8", "Schannel treats RC2 as 128-bit", Abort);
QEXPECT_FAIL("RC2-64-CBC, length 0", "Schannel treats RC2 as 128-bit", Abort);
QEXPECT_FAIL("RC2-64-CBC, length 8", "Schannel treats RC2 as 128-bit", Abort);
#endif
if (isSchannel) {
QEXPECT_FAIL("RC2-40-CBC, length 0", "Schannel treats RC2 as 128-bit", Abort);
QEXPECT_FAIL("RC2-40-CBC, length 8", "Schannel treats RC2 as 128-bit", Abort);
QEXPECT_FAIL("RC2-64-CBC, length 0", "Schannel treats RC2 as 128-bit", Abort);
QEXPECT_FAIL("RC2-64-CBC, length 8", "Schannel treats RC2 as 128-bit", Abort);
}
QByteArray encrypted = QSslKeyPrivate::encrypt(cipher, plainText, key, iv);
QCOMPARE(encrypted, cipherText);

View File

@ -59,7 +59,10 @@
#include "private/qtlsbackend_p.h"
#ifndef QT_NO_OPENSSL
#include "private/qsslsocket_openssl_symbols_p.h"
// TLSTODO:
// Disabling tests requiring this - moving OpenSSL code into plugins,
// find a workaround if needed.
//#include "private/qsslsocket_openssl_symbols_p.h"
#endif // QT_NO_OPENSSL
#include "private/qsslsocket_p.h"
@ -110,12 +113,12 @@ static const QByteArray PSK_CLIENT_PRESHAREDKEY = QByteArrayLiteral("\x1a\x2b\x3
static const QByteArray PSK_SERVER_IDENTITY_HINT = QByteArrayLiteral("QtTestServerHint");
static const QByteArray PSK_CLIENT_IDENTITY = QByteArrayLiteral("Client_identity");
#endif // !QT_NO_OPENSSL
QT_BEGIN_NAMESPACE
void qt_ForceTlsSecurityLevel();
QT_END_NAMESPACE
#endif // !QT_NO_OPENSSL
class tst_QSslSocket : public QObject
{
Q_OBJECT
@ -319,11 +322,36 @@ protected slots:
private:
QSslSocket *socket;
QList<QSslError> storedExpectedSslErrors;
bool isTestingOpenSsl = false;
bool isTestingSecureTransport = false;
bool isTestingSchannel = false;
#endif // QT_NO_SSL
private:
static int loopLevel;
public:
static QString testDataDir;
bool supportsTls13() const
{
if (isTestingOpenSsl) {
#ifdef TLS1_3_VERSION
return true;
#endif
}
if (isTestingSchannel) {
// Copied from qtls_schannel.cpp #supportsTls13()
static bool supported = []() {
const auto current = QOperatingSystemVersion::current();
const auto minimum =
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 20221);
return current >= minimum;
}();
return supported;
}
return false;
}
};
QString tst_QSslSocket::testDataDir;
@ -348,24 +376,6 @@ QString httpServerCertChainPath()
#endif // QT_TEST_SERVER
}
bool supportsTls13()
{
#ifdef TLS1_3_VERSION
return true;
#elif QT_CONFIG(schannel)
// Copied from qsslsocket_schannel.cpp #supportsTls13()
static bool supported = []() {
const auto current = QOperatingSystemVersion::current();
const auto minimum =
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 20221);
return current >= minimum;
}();
return supported;
#else
return false;
#endif
}
} // unnamed namespace
tst_QSslSocket::tst_QSslSocket()
@ -417,6 +427,20 @@ void tst_QSslSocket::initTestCase()
testDataDir = QCoreApplication::applicationDirPath();
if (!testDataDir.endsWith(QLatin1String("/")))
testDataDir += QLatin1String("/");
// Several plugins (TLS-backends) can co-exist. QSslSocket would implicitly
// select 'openssl' if available, and if not: 'securetransport' (Darwin) or
// 'schannel' (Windows). Check what we actually have:
const auto &tlsBackends = QSslSocket::availableBackends();
if (tlsBackends.contains(QTlsBackend::builtinBackendNames[QTlsBackend::nameIndexOpenSSL])) {
isTestingOpenSsl = true;
} else if (tlsBackends.contains(QTlsBackend::builtinBackendNames[QTlsBackend::nameIndexSchannel])) {
isTestingSchannel = true;
} else {
QVERIFY(tlsBackends.contains(QTlsBackend::builtinBackendNames[QTlsBackend::nameIndexSecureTransport]));
isTestingSecureTransport = true;
}
#ifndef QT_NO_SSL
qDebug("Using SSL library %s (%ld)",
qPrintable(QSslSocket::sslLibraryVersionString()),
@ -474,9 +498,7 @@ void tst_QSslSocket::init()
#endif // QT_NO_NETWORKPROXY
}
#ifndef QT_NO_OPENSSL
QT_PREPEND_NAMESPACE(qt_ForceTlsSecurityLevel)();
#endif // QT_NO_OPENSSL
qt_qhostinfo_clear_cache();
}
@ -519,8 +541,6 @@ void tst_QSslSocket::activeBackend()
if (setProxy) // Not interesting for backend test.
return;
QCOMPARE(QSslSocket::activeBackend(), QTlsBackend::defaultBackendName());
// We cannot set non-existing as active:
const QString nonExistingBackend = QStringLiteral("TheQtTLS");
QCOMPARE(QSslSocket::setActiveBackend(nonExistingBackend), false);
@ -609,17 +629,21 @@ void tst_QSslSocket::backends()
const auto sizeBefore = backendNames.size();
QVERIFY(sizeBefore > 0);
const auto builtinBackend = backendNames.first();
const auto builtinProtocols = QSslSocket::supportedProtocols(builtinBackend);
const QString tlsBackend = QSslSocket::activeBackend();
QVERIFY(tlsBackend == QTlsBackend::builtinBackendNames[QTlsBackend::nameIndexOpenSSL]
|| tlsBackend == QTlsBackend::builtinBackendNames[QTlsBackend::nameIndexSchannel]
|| tlsBackend == QTlsBackend::builtinBackendNames[QTlsBackend::nameIndexSecureTransport]);
const auto builtinProtocols = QSslSocket::supportedProtocols(tlsBackend);
QVERIFY(builtinProtocols.contains(QSsl::SecureProtocols));
// Socket and ALPN are supported by all our backends:
const auto builtinClasses = QSslSocket::implementedClasses(builtinBackend);
const auto builtinClasses = QSslSocket::implementedClasses(tlsBackend);
QVERIFY(builtinClasses.contains(QSsl::ImplementedClass::Socket));
const auto builtinFeatures = QSslSocket::supportedFeatures(builtinBackend);
const auto builtinFeatures = QSslSocket::supportedFeatures(tlsBackend);
QVERIFY(builtinFeatures.contains(QSsl::SupportedFeature::ClientSideAlpn));
// Verify that non-dummy backend can be created (and delete it):
auto *systemBackend = QTlsBackend::findBackend(builtinBackend);
// Verify that non-dummy backend can be found:
auto *systemBackend = QTlsBackend::findBackend(tlsBackend);
QVERIFY(systemBackend);
const auto protocols = QList<QSsl::SslProtocol>{QSsl::SecureProtocols};
@ -913,10 +937,11 @@ void tst_QSslSocket::sslErrors()
QFETCH(int, port);
QSslSocketPtr socket = newSocket();
#if QT_CONFIG(schannel)
// Needs to be < 1.2 because of the old certificate and <= 1.0 because of the mail server
socket->setProtocol(QSsl::SslProtocol::TlsV1_0);
#endif
if (isTestingSchannel) {
// Needs to be < 1.2 because of the old certificate and <= 1.0 because of the mail server
socket->setProtocol(QSsl::SslProtocol::TlsV1_0);
}
QSignalSpy sslErrorsSpy(socket.data(), SIGNAL(sslErrors(QList<QSslError>)));
QSignalSpy peerVerifyErrorSpy(socket.data(), SIGNAL(peerVerifyError(QSslError)));
@ -1013,26 +1038,28 @@ void tst_QSslSocket::ciphers()
if (!ciphers.size())
QSKIP("No proper ciphersuite was found to test 'setCiphers'");
#if QT_CONFIG(schannel)
qWarning("Schannel doesn't support setting ciphers from a cipher-string.");
#else
sslConfig.setCiphers(ciphersAsString);
socket.setSslConfiguration(sslConfig);
QCOMPARE(ciphers, socket.sslConfiguration().ciphers());
#endif
if (isTestingSchannel) {
qWarning("Schannel doesn't support setting ciphers from a cipher-string.");
} else {
sslConfig.setCiphers(ciphersAsString);
socket.setSslConfiguration(sslConfig);
QCOMPARE(ciphers, socket.sslConfiguration().ciphers());
}
sslConfig.setCiphers(ciphers);
socket.setSslConfiguration(sslConfig);
QCOMPARE(ciphers, socket.sslConfiguration().ciphers());
#ifndef QT_NO_OPENSSL
for (const auto &cipher : ciphers) {
if (cipher.name().size() && cipher.protocol() != QSsl::UnknownProtocol) {
const QSslCipher aCopy(cipher.name(), cipher.protocol());
QCOMPARE(aCopy, cipher);
break;
if (isTestingOpenSsl) {
for (const auto &cipher : ciphers) {
if (cipher.name().size() && cipher.protocol() != QSsl::UnknownProtocol) {
const QSslCipher aCopy(cipher.name(), cipher.protocol());
QCOMPARE(aCopy, cipher);
break;
}
}
}
#endif // QT_NO_OPENSSL
}
void tst_QSslSocket::connectToHostEncrypted()
@ -1041,9 +1068,9 @@ void tst_QSslSocket::connectToHostEncrypted()
return;
QSslSocketPtr socket = newSocket();
#if QT_CONFIG(schannel) // old certificate not supported with TLS 1.2
socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
#endif
if (isTestingSchannel) // old certificate not supported with TLS 1.2
socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
this->socket = socket.data();
auto config = socket->sslConfiguration();
QVERIFY(config.addCaCertificates(httpServerCertChainPath()));
@ -1079,9 +1106,9 @@ void tst_QSslSocket::connectToHostEncryptedWithVerificationPeerName()
return;
QSslSocketPtr socket = newSocket();
#if QT_CONFIG(schannel) // old certificate not supported with TLS 1.2
socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
#endif
if (isTestingSchannel) // old certificate not supported with TLS 1.2
socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
this->socket = socket.data();
auto config = socket->sslConfiguration();
@ -1250,7 +1277,9 @@ void tst_QSslSocket::privateKeyOpaque()
{
if (!QSslSocket::supportsSsl())
return;
// TLSTODO: OpenSSL symbols are now a part of 'openssl' plugin,
// not QtNetwork anymore.
#if 0
QFile file(testDataDir + "certs/fluke.key");
QVERIFY(file.open(QIODevice::ReadOnly));
QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
@ -1278,6 +1307,7 @@ void tst_QSslSocket::privateKeyOpaque()
QFETCH_GLOBAL(bool, setProxy);
if (setProxy && !socket->waitForEncrypted(10000))
QSKIP("Skipping flaky test - See QTBUG-29941");
#endif // if 0
}
#endif
@ -1745,11 +1775,12 @@ void tst_QSslSocket::setLocalCertificateChain()
loop.exec();
QList<QSslCertificate> chain = socket->peerCertificateChain();
#if QT_CONFIG(schannel)
QEXPECT_FAIL("", "Schannel cannot send intermediate certificates not "
"located in a system certificate store",
Abort);
#endif
if (isTestingSchannel) {
QEXPECT_FAIL("", "Schannel cannot send intermediate certificates not "
"located in a system certificate store",
Abort);
}
QCOMPARE(chain.size(), 2);
QCOMPARE(chain[0].serialNumber(), QByteArray("10:a0:ad:77:58:f6:6e:ae:46:93:a3:43:f9:59:8a:9e"));
QCOMPARE(chain[1].serialNumber(), QByteArray("3b:eb:99:c5:ea:d8:0b:5d:0b:97:5d:4f:06:75:4b:e1"));
@ -1824,15 +1855,16 @@ void tst_QSslSocket::setSslConfiguration_data()
QTest::newRow("empty") << QSslConfiguration() << false;
QSslConfiguration conf = QSslConfiguration::defaultConfiguration();
QTest::newRow("default") << conf << false; // does not contain test server cert
#if !QT_CONFIG(securetransport)
QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(httpServerCertChainPath());
conf.setCaCertificates(testServerCert);
QTest::newRow("set-root-cert") << conf << true;
conf.setProtocol(QSsl::SecureProtocols);
QTest::newRow("secure") << conf << true;
#else
qWarning("Skipping the cases with certificate, SecureTransport does not like old certificate on the test server");
#endif
if (!isTestingSecureTransport) {
QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(httpServerCertChainPath());
conf.setCaCertificates(testServerCert);
QTest::newRow("set-root-cert") << conf << true;
conf.setProtocol(QSsl::SecureProtocols);
QTest::newRow("secure") << conf << true;
} else {
qWarning("Skipping the cases with certificate, SecureTransport does not like old certificate on the test server");
}
}
void tst_QSslSocket::setSslConfiguration()
@ -1843,9 +1875,9 @@ void tst_QSslSocket::setSslConfiguration()
QSslSocketPtr socket = newSocket();
QFETCH(QSslConfiguration, configuration);
socket->setSslConfiguration(configuration);
#if QT_CONFIG(schannel) // old certificate not supported with TLS 1.2
socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
#endif
if (isTestingSchannel) // old certificate not supported with TLS 1.2
socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
this->socket = socket.data();
socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
QFETCH(bool, works);
@ -2545,9 +2577,9 @@ void tst_QSslSocket::verifyMode()
return;
QSslSocket socket;
#if QT_CONFIG(schannel) // old certificate not supported with TLS 1.2
socket.setProtocol(QSsl::SslProtocol::TlsV1_1);
#endif
if (isTestingSchannel) // old certificate not supported with TLS 1.2
socket.setProtocol(QSsl::SslProtocol::TlsV1_1);
QCOMPARE(socket.peerVerifyMode(), QSslSocket::AutoVerifyPeer);
socket.setPeerVerifyMode(QSslSocket::VerifyNone);
QCOMPARE(socket.peerVerifyMode(), QSslSocket::VerifyNone);
@ -2884,9 +2916,9 @@ void tst_QSslSocket::abortOnSslErrors()
void tst_QSslSocket::readFromClosedSocket()
{
QSslSocketPtr socket = newSocket();
#if QT_CONFIG(schannel) // old certificate not supported with TLS 1.2
socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
#endif
if (isTestingSchannel) // old certificate not supported with TLS 1.2
socket->setProtocol(QSsl::SslProtocol::TlsV1_1);
socket->ignoreSslErrors();
socket->connectToHostEncrypted(QtNetworkSettings::httpServerName(), 443);
socket->ignoreSslErrors();
@ -3547,14 +3579,15 @@ void tst_QSslSocket::verifyClientCertificate_data()
void tst_QSslSocket::verifyClientCertificate()
{
#if QT_CONFIG(securetransport)
// We run both client and server on the same machine,
// this means, client can update keychain with client's certificates,
// and server later will use the same certificates from the same
// keychain thus making tests fail (wrong number of certificates,
// success instead of failure etc.).
QSKIP("This test can not work with Secure Transport");
#endif // QT_CONFIG(securetransport)
if (isTestingSecureTransport) {
// We run both client and server on the same machine,
// this means, client can update keychain with client's certificates,
// and server later will use the same certificates from the same
// keychain thus making tests fail (wrong number of certificates,
// success instead of failure etc.).
QSKIP("This test can not work with Secure Transport");
}
if (!QSslSocket::supportsSsl()) {
qWarning("SSL not supported, skipping test");
return;
@ -3565,10 +3598,10 @@ void tst_QSslSocket::verifyClientCertificate()
return;
QFETCH(QSslSocket::PeerVerifyMode, peerVerifyMode);
#if QT_CONFIG(schannel)
if (peerVerifyMode == QSslSocket::QueryPeer || peerVerifyMode == QSslSocket::AutoVerifyPeer)
QSKIP("Schannel doesn't tackle requesting a certificate and not receiving one.");
#endif
if (isTestingSchannel) {
if (peerVerifyMode == QSslSocket::QueryPeer || peerVerifyMode == QSslSocket::AutoVerifyPeer)
QSKIP("Schannel doesn't tackle requesting a certificate and not receiving one.");
}
SslServer server;
server.addCaCertificates = testDataDir + "certs/bogus-ca.crt";
@ -3608,13 +3641,13 @@ void tst_QSslSocket::verifyClientCertificate()
QVERIFY(server.socket->peerCertificateChain().isEmpty());
} else {
QCOMPARE(server.socket->peerCertificate(), clientCerts.first());
#if QT_CONFIG(schannel)
if (clientCerts.count() == 1 && server.socket->peerCertificateChain().count() == 2) {
QEXPECT_FAIL("",
"Schannel includes the entire chain, not just the leaf and intermediates",
Continue);
if (isTestingSchannel) {
if (clientCerts.count() == 1 && server.socket->peerCertificateChain().count() == 2) {
QEXPECT_FAIL("",
"Schannel includes the entire chain, not just the leaf and intermediates",
Continue);
}
}
#endif
QCOMPARE(server.socket->peerCertificateChain(), clientCerts);
}
@ -3625,7 +3658,6 @@ void tst_QSslSocket::verifyClientCertificate()
void tst_QSslSocket::readBufferMaxSize()
{
#if QT_CONFIG(securetransport) || QT_CONFIG(schannel)
// QTBUG-55170:
// SecureTransport back-end was ignoring read-buffer
// size limit, resulting (potentially) in a constantly
@ -3680,9 +3712,6 @@ void tst_QSslSocket::readBufferMaxSize()
loop.exec();
QCOMPARE(client->bytesAvailable() + readSoFar, message.size());
#else
// Not needed, QSslSocket works correctly with other back-ends.
#endif // QT_CONFIG(securetransport) || QT_CONFIG(schannel)
}
void tst_QSslSocket::setEmptyDefaultConfiguration() // this test should be last, as it has some side effects
@ -3711,16 +3740,15 @@ void tst_QSslSocket::allowedProtocolNegotiation()
QSKIP("ALPN is unsupported, skipping test");
#endif
#if QT_CONFIG(schannel)
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1)
QSKIP("ALPN is not supported on this version of Windows using Schannel.");
#endif
if (isTestingSchannel) {
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1)
QSKIP("ALPN is not supported on this version of Windows using Schannel.");
}
QFETCH_GLOBAL(bool, setProxy);
if (setProxy)
return;
const QByteArray expectedNegotiated("cool-protocol");
QList<QByteArray> serverProtos;
serverProtos << expectedNegotiated << "not-so-cool-protocol";
@ -4158,9 +4186,9 @@ void tst_QSslSocket::ephemeralServerKey()
void tst_QSslSocket::pskServer()
{
#if QT_CONFIG(schannel)
QSKIP("Schannel does not have PSK support implemented.");
#endif
if (!isTestingOpenSsl)
QSKIP("The active TLS-backend does not have PSK support implemented.");
QFETCH_GLOBAL(bool, setProxy);
if (!QSslSocket::supportsSsl() || setProxy)
return;