diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-11-02 01:01:12 +0100 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-11-02 01:01:12 +0100 |
commit | ab6affac107cb97e7b6decbe55621259cb8a9b92 (patch) | |
tree | 70e427676c20abcd21b1354b803682b65986b2e5 /src/network | |
parent | 89f1f14c5e9a49f25345a65d81b3518d58ecb91a (diff) | |
parent | 44a26a0a79ed07b829d55979eaed6f06346ca450 (diff) |
Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: I256a4b0bac4d2f5eb170967fedc4eccaec8c7f2a
Diffstat (limited to 'src/network')
20 files changed, 913 insertions, 2557 deletions
diff --git a/src/network/configure.json b/src/network/configure.json index f501465c91..6bc71469dc 100644 --- a/src/network/configure.json +++ b/src/network/configure.json @@ -61,11 +61,11 @@ "export": "openssl", "test": { "tail": [ - "#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10000000L", - "# error OpenSSL >= 1.0.0 is required", + "#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10100000L", + "# error OpenSSL >= 1.1.0 is required", "#endif", - "#if OPENSSL_VERSION_NUMBER-0 >= 0x10002000L && !defined(OPENSSL_NO_EC) && !defined(SSL_CTRL_SET_CURVES)", - "# error OpenSSL was reported as >= 1.0.2 but is missing required features, possibly it's libressl which is unsupported", + "#if !defined(OPENSSL_NO_EC) && !defined(SSL_CTRL_SET_CURVES)", + "# error OpenSSL was reported as >= 1.1.0 but is missing required features, possibly it's libressl which is unsupported", "#endif" ] }, @@ -185,19 +185,6 @@ }, "use": "network" }, - "openssl11": { - "label": "OpenSSL 1.1 support", - "type": "compile", - "test": { - "include": "openssl/opensslv.h", - "tail": [ - "#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10100000L", - "# error OpenSSL >= 1.1 is required", - "#endif" - ] - }, - "use": "openssl" - }, "dtls": { "label": "DTLS support in OpenSSL", "type": "compile", @@ -335,7 +322,7 @@ }, "opensslv11": { "label": "OpenSSL 1.1", - "condition": "features.openssl && tests.openssl11", + "condition": "features.openssl", "output": [ "publicFeature" ] }, "sctp": { diff --git a/src/network/ssl/qdtls_openssl.cpp b/src/network/ssl/qdtls_openssl.cpp index d9ddcceb40..25a6c5f49c 100644 --- a/src/network/ssl/qdtls_openssl.cpp +++ b/src/network/ssl/qdtls_openssl.cpp @@ -156,8 +156,6 @@ void delete_connection(SSL *ssl) q_SSL_free(ssl); } -#if QT_CONFIG(opensslv11) - void delete_BIO_ADDR(BIO_ADDR *bio) { // A deleter for QSharedPointer<BIO_ADDR> @@ -172,8 +170,6 @@ void delete_bio_method(BIO_METHOD *method) q_BIO_meth_free(method); } -#endif // openssl 1.1 - // The 'deleter' for QScopedPointer<BIO>. struct bio_deleter { @@ -411,10 +407,6 @@ extern "C" long q_dgram_ctrl(BIO *bio, int cmd, long num, void *ptr) auto dtls = static_cast<dtlsopenssl::DtlsState *>(q_BIO_get_app_data(bio)); Q_ASSERT(dtls); -#if !QT_CONFIG(opensslv11) - Q_UNUSED(num) -#endif - switch (cmd) { // Let's start from the most generic ones, in the order in which they are // documented (as BIO_ctrl): @@ -578,11 +570,9 @@ extern "C" long q_dgram_ctrl(BIO *bio, int cmd, long num, void *ptr) // so that OpenSSL does not start suddenly fragmenting the first // client hello (which will result in DTLSv1_listen rejecting it). return 0; -#if QT_CONFIG(opensslv11) case BIO_CTRL_DGRAM_SET_PEEK_MODE: dtls->peeking = num; return 1; -#endif default:; #if QT_DTLS_VERBOSE qWarning() << "Unexpected cmd (" << cmd << ")"; @@ -594,15 +584,11 @@ extern "C" long q_dgram_ctrl(BIO *bio, int cmd, long num, void *ptr) extern "C" int q_dgram_create(BIO *bio) { -#if QT_CONFIG(opensslv11) + q_BIO_set_init(bio, 1); -#else - bio->init = 1; -#endif // With a custom BIO you'd normally allocate some implementation-specific - // data and append it to this new BIO: bio->ptr = ... (pre 1.0.2) or - // BIO_set_data (1.1). We don't need it and thus q_dgram_destroy below - // is a noop. + // data and append it to this new BIO using BIO_set_data. We don't need + // it and thus q_dgram_destroy below is a noop. return 1; } @@ -614,39 +600,6 @@ extern "C" int q_dgram_destroy(BIO *bio) const char * const qdtlsMethodName = "qdtlsbio"; -#if !QT_CONFIG(opensslv11) - -/* -typedef struct bio_method_st { - int type; - const char *name; - int (*bwrite) (BIO *, const char *, int); - int (*bread) (BIO *, char *, int); - int (*bputs) (BIO *, const char *); - int (*bgets) (BIO *, char *, int); - long (*ctrl) (BIO *, int, long, void *); - int (*create) (BIO *); - int (*destroy) (BIO *); - long (*callback_ctrl) (BIO *, int, bio_info_cb *); -} BIO_METHOD; -*/ - -bio_method_st qdtlsCustomBioMethod = -{ - BIO_TYPE_DGRAM, - qdtlsMethodName, - q_dgram_write, - q_dgram_read, - q_dgram_puts, - nullptr, - q_dgram_ctrl, - q_dgram_create, - q_dgram_destroy, - nullptr -}; - -#endif // openssl < 1.1 - } // namespace dtlsbio namespace dtlsopenssl @@ -777,7 +730,6 @@ bool DtlsState::initBIO(QDtlsBasePrivate *dtlsBase) Q_ASSERT(dtlsBase); Q_ASSERT(tlsContext.data() && tlsConnection.data()); -#if QT_CONFIG(opensslv11) BioMethod customMethod(q_BIO_meth_new(BIO_TYPE_DGRAM, dtlsbio::qdtlsMethodName), dtlsutil::delete_bio_method); if (!customMethod.data()) { @@ -793,9 +745,6 @@ bool DtlsState::initBIO(QDtlsBasePrivate *dtlsBase) q_BIO_meth_set_write(biom, dtlsbio::q_dgram_write); q_BIO_meth_set_puts(biom, dtlsbio::q_dgram_puts); q_BIO_meth_set_ctrl(biom, dtlsbio::q_dgram_ctrl); -#else - BIO_METHOD *biom = &dtlsbio::qdtlsCustomBioMethod; -#endif // openssl 1.1 QScopedPointer<BIO, dtlsutil::bio_deleter> newBio(q_BIO_new(biom)); BIO *bio = newBio.data(); @@ -808,9 +757,7 @@ bool DtlsState::initBIO(QDtlsBasePrivate *dtlsBase) q_SSL_set_bio(tlsConnection.data(), bio, bio); newBio.take(); -#if QT_CONFIG(opensslv11) bioMethod.swap(customMethod); -#endif // openssl 1.1 return true; } @@ -869,7 +816,6 @@ bool QDtlsClientVerifierOpenSSL::verifyClient(QUdpSocket *socket, const QByteArr dtls.hashAlgorithm = hashAlgorithm; Q_ASSERT(dtls.tlsConnection.data()); -#if QT_CONFIG(opensslv11) QSharedPointer<BIO_ADDR> peer(q_BIO_ADDR_new(), dtlsutil::delete_BIO_ADDR); if (!peer.data()) { setDtlsError(QDtlsError::TlsInitializationError, @@ -883,10 +829,7 @@ bool QDtlsClientVerifierOpenSSL::verifyClient(QUdpSocket *socket, const QByteArr setDtlsError(QDtlsError::TlsFatalError, QSslSocketBackendPrivate::getErrorsFromOpenSsl()); return false; } -#else - qt_sockaddr peer; - const int ret = q_DTLSv1_listen(dtls.tlsConnection.data(), &peer); -#endif + if (ret > 0) { verifiedClientHello = dgram; return true; @@ -953,7 +896,6 @@ bool QDtlsPrivateOpenSSL::startHandshake(QUdpSocket *socket, const QByteArray &d // surprise DTLS/OpenSSL (such a message would be disregarded as // 'stale or future' in SSL_accept otherwise): int result = 0; -#if QT_CONFIG(opensslv11) QSharedPointer<BIO_ADDR> peer(q_BIO_ADDR_new(), dtlsutil::delete_BIO_ADDR); if (!peer.data()) { setDtlsError(QDtlsError::TlsInitializationError, @@ -967,10 +909,7 @@ bool QDtlsPrivateOpenSSL::startHandshake(QUdpSocket *socket, const QByteArray &d dtls.writeSuppressed = true; result = q_DTLSv1_listen(dtls.tlsConnection.data(), peer.data()); dtls.writeSuppressed = false; -#else - qt_sockaddr peer; - result = q_DTLSv1_listen(dtls.tlsConnection.data(), &peer); -#endif + if (result <= 0) { setDtlsError(QDtlsError::TlsFatalError, QDtls::tr("Cannot start the handshake, verified client hello expected")); diff --git a/src/network/ssl/qdtls_openssl_p.h b/src/network/ssl/qdtls_openssl_p.h index 9306fa2433..35e9f29a5d 100644 --- a/src/network/ssl/qdtls_openssl_p.h +++ b/src/network/ssl/qdtls_openssl_p.h @@ -84,9 +84,8 @@ namespace dtlsopenssl class DtlsState { public: - // Note, bioMethod, if allocated (i.e. OpenSSL version >= 1.1) _must_ - // outlive BIOs it was used to create. Thus the order of declarations - // here matters. + // Note, bioMethod _must_ outlive BIOs it was used to create. Thus + // the order of declarations here matters. using BioMethod = QSharedPointer<BIO_METHOD>; BioMethod bioMethod; diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp index 8566d78aef..562aa4f518 100644 --- a/src/network/ssl/qsslcontext_openssl.cpp +++ b/src/network/ssl/qsslcontext_openssl.cpp @@ -3,6 +3,7 @@ ** Copyright (C) 2017 The Qt Company Ltd. ** Copyright (C) 2014 BlackBerry Limited. All rights reserved. ** Copyright (C) 2014 Governikus GmbH & Co. KG. +** Copyright (C) 2016 Richard J. Moore <rich@kde.org> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtNetwork module of the Qt Toolkit. @@ -39,21 +40,49 @@ ** ****************************************************************************/ - #include <QtNetwork/qsslsocket.h> +#include <QtNetwork/qssldiffiehellmanparameters.h> #include "private/qssl_p.h" +#include "private/qsslsocket_p.h" #include "private/qsslcontext_openssl_p.h" #include "private/qsslsocket_openssl_p.h" #include "private/qsslsocket_openssl_symbols_p.h" +#include "private/qssldiffiehellmanparameters_p.h" + +#include <vector> QT_BEGIN_NAMESPACE +// defined in qsslsocket_openssl.cpp: +extern int q_X509Callback(int ok, X509_STORE_CTX *ctx); +extern QString getErrorsFromOpenSsl(); + +#if QT_CONFIG(dtls) +// defined in qdtls_openssl.cpp: +namespace dtlscallbacks +{ +extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx); +extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst, + unsigned *cookieLength); +extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie, + unsigned cookieLength); +} +#endif // dtls + +// Defined in qsslsocket.cpp +QList<QSslCipher> q_getDefaultDtlsCiphers(); + static inline QString msgErrorSettingBackendConfig(const QString &why) { return QSslSocket::tr("Error when setting the OpenSSL configuration (%1)").arg(why); } +static inline QString msgErrorSettingEllipticCurves(const QString &why) +{ + return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why); +} + QSslContext::QSslContext() : ctx(nullptr), pkey(nullptr), @@ -89,7 +118,7 @@ QSharedPointer<QSslContext> QSslContext::sharedFromConfiguration(QSslSocket::Ssl return sslContext; } -#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifndef OPENSSL_NO_NEXTPROTONEG static int next_proto_cb(SSL *, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg) @@ -126,7 +155,9 @@ QSslContext::NPNContext QSslContext::npnContext() const { return m_npnContext; } -#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... +#endif // !OPENSSL_NO_NEXTPROTONEG + + // Needs to be deleted by caller SSL* QSslContext::createSsl() @@ -150,7 +181,7 @@ SSL* QSslContext::createSsl() } } -#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifndef OPENSSL_NO_NEXTPROTONEG QList<QByteArray> protocols = sslConfiguration.d->nextAllowedProtocols; if (!protocols.isEmpty()) { m_supportedNPNVersions.clear(); @@ -168,27 +199,22 @@ SSL* QSslContext::createSsl() m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data()); m_npnContext.len = m_supportedNPNVersions.count(); m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone; -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (QSslSocket::sslLibraryVersionNumber() >= 0x10002000L) { - // Callback's type has a parameter 'const unsigned char ** out' - // since it was introduced in 1.0.2. Internally, OpenSSL's own code - // (tests/examples) cast it to unsigned char * (since it's 'out'). - // We just re-use our NPN callback and cast here: - typedef int (*alpn_callback_t) (SSL *, const unsigned char **, unsigned char *, - const unsigned char *, unsigned int, void *); - // With ALPN callback is for a server side only, for a client m_npnContext.status - // will stay in NextProtocolNegotiationNone. - q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext); - // Client: - q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... - + // Callback's type has a parameter 'const unsigned char ** out' + // since it was introduced in 1.0.2. Internally, OpenSSL's own code + // (tests/examples) cast it to unsigned char * (since it's 'out'). + // We just re-use our NPN callback and cast here: + typedef int (*alpn_callback_t) (SSL *, const unsigned char **, unsigned char *, + const unsigned char *, unsigned int, void *); + // With ALPN callback is for a server side only, for a client m_npnContext.status + // will stay in NextProtocolNegotiationNone. + q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext); + // Client: + q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len); // And in case our peer does not support ALPN, but supports NPN: q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext); } } -#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... +#endif // !OPENSSL_NO_NEXTPROTONEG return ssl; } @@ -247,6 +273,392 @@ QString QSslContext::errorString() const return errorStr; } +void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, + const QSslConfiguration &configuration, + bool allowRootCertOnDemandLoading) +{ + sslContext->sslConfiguration = configuration; + sslContext->errorCode = QSslError::NoError; + + bool client = (mode == QSslSocket::SslClientMode); + + bool reinitialized = false; + bool unsupportedProtocol = false; + bool isDtls = false; +init_context: + if (sslContext->sslConfiguration.protocol() == QSsl::SslV2) { + // SSL 2 is no longer supported, but chosen deliberately -> error + sslContext->ctx = nullptr; + unsupportedProtocol = true; + } else if (sslContext->sslConfiguration.protocol() == QSsl::SslV3) { + // SSL 3 is no longer supported, but chosen deliberately -> error + sslContext->ctx = nullptr; + unsupportedProtocol = true; + } else { + switch (sslContext->sslConfiguration.protocol()) { + case QSsl::DtlsV1_0: + case QSsl::DtlsV1_0OrLater: + case QSsl::DtlsV1_2: + case QSsl::DtlsV1_2OrLater: +#if QT_CONFIG(dtls) + isDtls = true; + sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method()); +#else // dtls + sslContext->ctx = nullptr; + unsupportedProtocol = true; + qCWarning(lcSsl, "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"); + sslContext->ctx = nullptr; + unsupportedProtocol = true; + break; +#endif // TLS1_3_VERSION + default: + // The ssl options will actually control the supported methods + sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method()); + } + } + + if (!sslContext->ctx) { + // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them + // by re-initializing the library. + if (!reinitialized) { + reinitialized = true; + if (q_OPENSSL_init_ssl(0, nullptr) == 1) + goto init_context; + } + + sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg( + unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl() + ); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + + const long anyVersion = +#if QT_CONFIG(dtls) + isDtls ? DTLS_ANY_VERSION : TLS_ANY_VERSION; +#else + TLS_ANY_VERSION; +#endif // dtls + long minVersion = anyVersion; + long maxVersion = anyVersion; + + switch (sslContext->sslConfiguration.protocol()) { + case QSsl::TlsV1_0: + minVersion = TLS1_VERSION; + maxVersion = TLS1_VERSION; + break; + case QSsl::TlsV1_1: + minVersion = TLS1_1_VERSION; + maxVersion = TLS1_1_VERSION; + break; + case QSsl::TlsV1_2: + minVersion = TLS1_2_VERSION; + maxVersion = TLS1_2_VERSION; + break; + case QSsl::TlsV1_3: +#ifdef TLS1_3_VERSION + minVersion = TLS1_3_VERSION; + maxVersion = TLS1_3_VERSION; +#else + // This protocol is not supported by OpenSSL 1.1 and we handle + // it as an error (see the code above). + Q_UNREACHABLE(); +#endif // TLS1_3_VERSION + break; + // Ranges: + case QSsl::TlsV1SslV3: + case QSsl::AnyProtocol: + case QSsl::SecureProtocols: + case QSsl::TlsV1_0OrLater: + minVersion = TLS1_VERSION; + maxVersion = 0; + break; + case QSsl::TlsV1_1OrLater: + minVersion = TLS1_1_VERSION; + maxVersion = 0; + break; + case QSsl::TlsV1_2OrLater: + minVersion = TLS1_2_VERSION; + maxVersion = 0; + break; + case QSsl::DtlsV1_0: + minVersion = DTLS1_VERSION; + maxVersion = DTLS1_VERSION; + break; + case QSsl::DtlsV1_0OrLater: + minVersion = DTLS1_VERSION; + maxVersion = DTLS_MAX_VERSION; + break; + case QSsl::DtlsV1_2: + minVersion = DTLS1_2_VERSION; + maxVersion = DTLS1_2_VERSION; + break; + case QSsl::DtlsV1_2OrLater: + minVersion = DTLS1_2_VERSION; + maxVersion = DTLS_MAX_VERSION; + break; + case QSsl::TlsV1_3OrLater: +#ifdef TLS1_3_VERSION + minVersion = TLS1_3_VERSION; + maxVersion = 0; + break; +#else + // This protocol is not supported by OpenSSL 1.1 and we handle + // it as an error (see the code above). + Q_UNREACHABLE(); + break; +#endif // TLS1_3_VERSION + case QSsl::SslV2: + case QSsl::SslV3: + // These protocols are not supported, and we handle + // them as an error (see the code above). + Q_UNREACHABLE(); + break; + case QSsl::UnknownProtocol: + break; + } + + if (minVersion != anyVersion + && !q_SSL_CTX_set_min_proto_version(sslContext->ctx, minVersion)) { + sslContext->errorStr = QSslSocket::tr("Error while setting the minimal protocol version"); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + + if (maxVersion != anyVersion + && !q_SSL_CTX_set_max_proto_version(sslContext->ctx, maxVersion)) { + sslContext->errorStr = QSslSocket::tr("Error while setting the maximum protocol version"); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + + // Enable bug workarounds. + long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); + q_SSL_CTX_set_options(sslContext->ctx, options); + + // Tell OpenSSL to release memory early + // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html + q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS); + + auto filterCiphers = [](const QList<QSslCipher> &ciphers, bool selectTls13) + { + QByteArray cipherString; + bool first = true; + + for (const QSslCipher &cipher : qAsConst(ciphers)) { + const bool isTls13Cipher = cipher.protocol() == QSsl::TlsV1_3 || cipher.protocol() == QSsl::TlsV1_3OrLater; + if (selectTls13 != isTls13Cipher) + continue; + + if (first) + first = false; + else + cipherString.append(':'); + cipherString.append(cipher.name().toLatin1()); + } + return cipherString; + }; + + // Initialize ciphers + QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers(); + if (ciphers.isEmpty()) + ciphers = isDtls ? q_getDefaultDtlsCiphers() : QSslSocketPrivate::defaultCiphers(); + + const QByteArray preTls13Ciphers = filterCiphers(ciphers, false); + + if (preTls13Ciphers.size()) { + if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, preTls13Ciphers.data())) { + sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + } + + const QByteArray tls13Ciphers = filterCiphers(ciphers, true); +#ifdef TLS1_3_VERSION + if (tls13Ciphers.size()) { + if (!q_SSL_CTX_set_ciphersuites(sslContext->ctx, tls13Ciphers.data())) { + sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + } +#endif // TLS1_3_VERSION + if (!preTls13Ciphers.size() && !tls13Ciphers.size()) { + sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QStringLiteral("")); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + + const QDateTime now = QDateTime::currentDateTimeUtc(); + + // Add all our CAs to this store. + const auto caCertificates = sslContext->sslConfiguration.caCertificates(); + for (const QSslCertificate &caCertificate : caCertificates) { + // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html: + // + // If several CA certificates matching the name, key identifier, and + // serial number condition are available, only the first one will be + // examined. This may lead to unexpected results if the same CA + // certificate is available with different expiration dates. If a + // ``certificate expired'' verification error occurs, no other + // certificate will be searched. Make sure to not have expired + // certificates mixed with valid ones. + // + // See also: QSslSocketBackendPrivate::verify() + if (caCertificate.expiryDate() >= now) { + q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle()); + } + } + + if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) { + // tell OpenSSL the directories where to look up the root certs on demand + const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories(); + for (const QByteArray &unixDir : unixDirs) + q_SSL_CTX_load_verify_locations(sslContext->ctx, nullptr, unixDir.constData()); + } + + if (!sslContext->sslConfiguration.localCertificate().isNull()) { + // Require a private key as well. + if (sslContext->sslConfiguration.privateKey().isNull()) { + sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + + // Load certificate + if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) { + sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + + if (configuration.d->privateKey.algorithm() == QSsl::Opaque) { + sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle()); + } else { + // Load private key + sslContext->pkey = q_EVP_PKEY_new(); + // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free. + // this lead to a memory leak. Now we use the *_set1_* functions which do not + // take ownership of the RSA/DSA key instance because the QSslKey already has ownership. + if (configuration.d->privateKey.algorithm() == QSsl::Rsa) + q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle())); + else if (configuration.d->privateKey.algorithm() == QSsl::Dsa) + q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle())); +#ifndef OPENSSL_NO_EC + else if (configuration.d->privateKey.algorithm() == QSsl::Ec) + q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle())); +#endif + } + + if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) { + sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + if (configuration.d->privateKey.algorithm() == QSsl::Opaque) + sslContext->pkey = nullptr; // Don't free the private key, it belongs to QSslKey + + // Check if the certificate matches the private key. + if (!q_SSL_CTX_check_private_key(sslContext->ctx)) { + sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + + // If we have any intermediate certificates then we need to add them to our chain + bool first = true; + for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) { + if (first) { + first = false; + continue; + } + q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, + q_X509_dup(reinterpret_cast<X509 *>(cert.handle()))); + } + } + + // Initialize peer verification. + if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) { + q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, nullptr); + } else { + q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, +#if QT_CONFIG(dtls) + isDtls ? dtlscallbacks::q_X509DtlsCallback : +#endif // dtls + q_X509Callback); + } + +#if QT_CONFIG(dtls) + if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) { + q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback); + q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, dtlscallbacks::q_verify_cookie_callback); + } +#endif // dtls + + // Set verification depth. + if (sslContext->sslConfiguration.peerVerifyDepth() != 0) + q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth()); + + // set persisted session if the user set it + if (!configuration.sessionTicket().isEmpty()) + sslContext->setSessionASN1(configuration.sessionTicket()); + + // Set temp DH params + QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters(); + + if (!dhparams.isValid()) { + sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid"); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + + if (!dhparams.isEmpty()) { + const QByteArray ¶ms = dhparams.d->derData; + const char *ptr = params.constData(); + DH *dh = q_d2i_DHparams(nullptr, reinterpret_cast<const unsigned char **>(&ptr), + params.length()); + if (dh == nullptr) + qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form"); + q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh); + q_DH_free(dh); + } + +#ifndef OPENSSL_NO_PSK + if (!client) + q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData()); +#endif // !OPENSSL_NO_PSK + + const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves(); + if (!qcurves.isEmpty()) { +#ifdef OPENSSL_NO_EC + sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version with disabled elliptic curves")); + sslContext->errorCode = QSslError::UnspecifiedError; + return; +#else + // Set the curves to be used. + std::vector<int> curves; + curves.reserve(qcurves.size()); + for (const auto &sslCurve : qcurves) + curves.push_back(sslCurve.id); + if (!q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES, long(curves.size()), &curves[0])) { + sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } +#endif + } + + applyBackendConfig(sslContext); +} + #if QT_CONFIG(ocsp) extern "C" int qt_OCSP_status_server_callback(SSL *ssl, void *); // Defined in qsslsocket_openssl.cpp. #endif // ocsp @@ -269,65 +681,55 @@ void QSslContext::applyBackendConfig(QSslContext *sslContext) } #endif // ocsp -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (QSslSocket::sslLibraryVersionNumber() >= 0x10002000L) { - QSharedPointer<SSL_CONF_CTX> cctx(q_SSL_CONF_CTX_new(), &q_SSL_CONF_CTX_free); - if (cctx) { - q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx); - q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE); - - for (auto i = conf.constBegin(); i != conf.constEnd(); ++i) { - if (i.key() == "Qt-OCSP-response") // This never goes to SSL_CONF_cmd(). - continue; - - if (!i.value().canConvert(QMetaType::QByteArray)) { - sslContext->errorCode = QSslError::UnspecifiedError; - sslContext->errorStr = msgErrorSettingBackendConfig( - QSslSocket::tr("Expecting QByteArray for %1").arg( - QString::fromUtf8(i.key()))); - return; - } - - const QByteArray &value = i.value().toByteArray(); - const int result = q_SSL_CONF_cmd(cctx.data(), i.key().constData(), value.constData()); - if (result == 2) - continue; + QSharedPointer<SSL_CONF_CTX> cctx(q_SSL_CONF_CTX_new(), &q_SSL_CONF_CTX_free); + if (cctx) { + q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx); + q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE); + + for (auto i = conf.constBegin(); i != conf.constEnd(); ++i) { + if (i.key() == "Qt-OCSP-response") // This never goes to SSL_CONF_cmd(). + continue; + if (!i.value().canConvert(QMetaType::QByteArray)) { sslContext->errorCode = QSslError::UnspecifiedError; - switch (result) { - case 0: - sslContext->errorStr = msgErrorSettingBackendConfig( - QSslSocket::tr("An error occurred attempting to set %1 to %2").arg( - QString::fromUtf8(i.key()), QString::fromUtf8(value))); - return; - case 1: - sslContext->errorStr = msgErrorSettingBackendConfig( - QSslSocket::tr("Wrong value for %1 (%2)").arg( - QString::fromUtf8(i.key()), QString::fromUtf8(value))); - return; - default: - sslContext->errorStr = msgErrorSettingBackendConfig( - QSslSocket::tr("Unrecognized command %1 = %2").arg( - QString::fromUtf8(i.key()), QString::fromUtf8(value))); - return; - } + sslContext->errorStr = msgErrorSettingBackendConfig( + QSslSocket::tr("Expecting QByteArray for %1").arg( + QString::fromUtf8(i.key()))); + return; } - if (q_SSL_CONF_CTX_finish(cctx.data()) == 0) { - sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_finish() failed")); - sslContext->errorCode = QSslError::UnspecifiedError; + const QByteArray &value = i.value().toByteArray(); + const int result = q_SSL_CONF_cmd(cctx.data(), i.key().constData(), value.constData()); + if (result == 2) + continue; + + sslContext->errorCode = QSslError::UnspecifiedError; + switch (result) { + case 0: + sslContext->errorStr = msgErrorSettingBackendConfig( + QSslSocket::tr("An error occurred attempting to set %1 to %2").arg( + QString::fromUtf8(i.key()), QString::fromUtf8(value))); + return; + case 1: + sslContext->errorStr = msgErrorSettingBackendConfig( + QSslSocket::tr("Wrong value for %1 (%2)").arg( + QString::fromUtf8(i.key()), QString::fromUtf8(value))); + return; + default: + sslContext->errorStr = msgErrorSettingBackendConfig( + QSslSocket::tr("Unrecognized command %1 = %2").arg( + QString::fromUtf8(i.key()), QString::fromUtf8(value))); + return; } - } else { - sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_CTX_new() failed")); - sslContext->errorCode = QSslError::UnspecifiedError; - } - } else -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L - { - // specific algorithms requested, but not possible to set + } + + if (q_SSL_CONF_CTX_finish(cctx.data()) == 0) { + sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_finish() failed")); + sslContext->errorCode = QSslError::UnspecifiedError; + } + } else { + sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_CTX_new() failed")); sslContext->errorCode = QSslError::UnspecifiedError; - sslContext->errorStr = msgErrorSettingBackendConfig( - QSslSocket::tr("OpenSSL version too old, need at least v1.0.2")); } } diff --git a/src/network/ssl/qsslcontext_openssl11.cpp b/src/network/ssl/qsslcontext_openssl11.cpp deleted file mode 100644 index db023b7331..0000000000 --- a/src/network/ssl/qsslcontext_openssl11.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2014 BlackBerry Limited. All rights reserved. -** Copyright (C) 2014 Governikus GmbH & Co. KG. -** Copyright (C) 2016 Richard J. Moore <rich@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtNetwork/qsslsocket.h> -#include <QtNetwork/qssldiffiehellmanparameters.h> - -#include "private/qssl_p.h" -#include "private/qsslcontext_openssl_p.h" -#include "private/qsslsocket_p.h" -#include "private/qsslsocket_openssl_p.h" -#include "private/qsslsocket_openssl_symbols_p.h" -#include "private/qssldiffiehellmanparameters_p.h" - -#include <vector> - -QT_BEGIN_NAMESPACE - -// defined in qsslsocket_openssl.cpp: -extern int q_X509Callback(int ok, X509_STORE_CTX *ctx); -extern QString getErrorsFromOpenSsl(); - -#if QT_CONFIG(dtls) -// defined in qdtls_openssl.cpp: -namespace dtlscallbacks -{ -extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx); -extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst, - unsigned *cookieLength); -extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie, - unsigned cookieLength); -} -#endif // dtls - -static inline QString msgErrorSettingEllipticCurves(const QString &why) -{ - return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why); -} - -// Defined in qsslsocket.cpp -QList<QSslCipher> q_getDefaultDtlsCiphers(); - -// static -void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading) -{ - sslContext->sslConfiguration = configuration; - sslContext->errorCode = QSslError::NoError; - - bool client = (mode == QSslSocket::SslClientMode); - - bool reinitialized = false; - bool unsupportedProtocol = false; - bool isDtls = false; -init_context: - if (sslContext->sslConfiguration.protocol() == QSsl::SslV2) { - // SSL 2 is no longer supported, but chosen deliberately -> error - sslContext->ctx = nullptr; - unsupportedProtocol = true; - } else if (sslContext->sslConfiguration.protocol() == QSsl::SslV3) { - // SSL 3 is no longer supported, but chosen deliberately -> error - sslContext->ctx = nullptr; - unsupportedProtocol = true; - } else { - switch (sslContext->sslConfiguration.protocol()) { - case QSsl::DtlsV1_0: - case QSsl::DtlsV1_0OrLater: - case QSsl::DtlsV1_2: - case QSsl::DtlsV1_2OrLater: -#if QT_CONFIG(dtls) - isDtls = true; - sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method()); -#else // dtls - sslContext->ctx = nullptr; - unsupportedProtocol = true; - qCWarning(lcSsl, "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"); - sslContext->ctx = nullptr; - unsupportedProtocol = true; - break; -#endif // TLS1_3_VERSION - default: - // The ssl options will actually control the supported methods - sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method()); - } - } - - if (!sslContext->ctx) { - // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them - // by re-initializing the library. - if (!reinitialized) { - reinitialized = true; - if (q_OPENSSL_init_ssl(0, nullptr) == 1) - goto init_context; - } - - sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg( - unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl() - ); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - const long anyVersion = -#if QT_CONFIG(dtls) - isDtls ? DTLS_ANY_VERSION : TLS_ANY_VERSION; -#else - TLS_ANY_VERSION; -#endif // dtls - long minVersion = anyVersion; - long maxVersion = anyVersion; - - switch (sslContext->sslConfiguration.protocol()) { - case QSsl::TlsV1_0: - minVersion = TLS1_VERSION; - maxVersion = TLS1_VERSION; - break; - case QSsl::TlsV1_1: - minVersion = TLS1_1_VERSION; - maxVersion = TLS1_1_VERSION; - break; - case QSsl::TlsV1_2: - minVersion = TLS1_2_VERSION; - maxVersion = TLS1_2_VERSION; - break; - case QSsl::TlsV1_3: -#ifdef TLS1_3_VERSION - minVersion = TLS1_3_VERSION; - maxVersion = TLS1_3_VERSION; -#else - // This protocol is not supported by OpenSSL 1.1 and we handle - // it as an error (see the code above). - Q_UNREACHABLE(); -#endif // TLS1_3_VERSION - break; - // Ranges: - case QSsl::TlsV1SslV3: - case QSsl::AnyProtocol: - case QSsl::SecureProtocols: - case QSsl::TlsV1_0OrLater: - minVersion = TLS1_VERSION; - maxVersion = 0; - break; - case QSsl::TlsV1_1OrLater: - minVersion = TLS1_1_VERSION; - maxVersion = 0; - break; - case QSsl::TlsV1_2OrLater: - minVersion = TLS1_2_VERSION; - maxVersion = 0; - break; - case QSsl::DtlsV1_0: - minVersion = DTLS1_VERSION; - maxVersion = DTLS1_VERSION; - break; - case QSsl::DtlsV1_0OrLater: - minVersion = DTLS1_VERSION; - maxVersion = DTLS_MAX_VERSION; - break; - case QSsl::DtlsV1_2: - minVersion = DTLS1_2_VERSION; - maxVersion = DTLS1_2_VERSION; - break; - case QSsl::DtlsV1_2OrLater: - minVersion = DTLS1_2_VERSION; - maxVersion = DTLS_MAX_VERSION; - break; - case QSsl::TlsV1_3OrLater: -#ifdef TLS1_3_VERSION - minVersion = TLS1_3_VERSION; - maxVersion = 0; - break; -#else - // This protocol is not supported by OpenSSL 1.1 and we handle - // it as an error (see the code above). - Q_UNREACHABLE(); - break; -#endif // TLS1_3_VERSION - case QSsl::SslV2: - case QSsl::SslV3: - // These protocols are not supported, and we handle - // them as an error (see the code above). - Q_UNREACHABLE(); - break; - case QSsl::UnknownProtocol: - break; - } - - if (minVersion != anyVersion - && !q_SSL_CTX_set_min_proto_version(sslContext->ctx, minVersion)) { - sslContext->errorStr = QSslSocket::tr("Error while setting the minimal protocol version"); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - if (maxVersion != anyVersion - && !q_SSL_CTX_set_max_proto_version(sslContext->ctx, maxVersion)) { - sslContext->errorStr = QSslSocket::tr("Error while setting the maximum protocol version"); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - // Enable bug workarounds. - long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); - q_SSL_CTX_set_options(sslContext->ctx, options); - - // Tell OpenSSL to release memory early - // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html - q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS); - - auto filterCiphers = [](const QList<QSslCipher> &ciphers, bool selectTls13) - { - QByteArray cipherString; - bool first = true; - - for (const QSslCipher &cipher : qAsConst(ciphers)) { - const bool isTls13Cipher = cipher.protocol() == QSsl::TlsV1_3 || cipher.protocol() == QSsl::TlsV1_3OrLater; - if (selectTls13 != isTls13Cipher) - continue; - - if (first) - first = false; - else - cipherString.append(':'); - cipherString.append(cipher.name().toLatin1()); - } - return cipherString; - }; - - // Initialize ciphers - QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers(); - if (ciphers.isEmpty()) - ciphers = isDtls ? q_getDefaultDtlsCiphers() : QSslSocketPrivate::defaultCiphers(); - - const QByteArray preTls13Ciphers = filterCiphers(ciphers, false); - - if (preTls13Ciphers.size()) { - if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, preTls13Ciphers.data())) { - sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - } - - const QByteArray tls13Ciphers = filterCiphers(ciphers, true); -#ifdef TLS1_3_VERSION - if (tls13Ciphers.size()) { - if (!q_SSL_CTX_set_ciphersuites(sslContext->ctx, tls13Ciphers.data())) { - sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - } -#endif // TLS1_3_VERSION - if (!preTls13Ciphers.size() && !tls13Ciphers.size()) { - sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QStringLiteral("")); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - const QDateTime now = QDateTime::currentDateTimeUtc(); - - // Add all our CAs to this store. - const auto caCertificates = sslContext->sslConfiguration.caCertificates(); - for (const QSslCertificate &caCertificate : caCertificates) { - // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html: - // - // If several CA certificates matching the name, key identifier, and - // serial number condition are available, only the first one will be - // examined. This may lead to unexpected results if the same CA - // certificate is available with different expiration dates. If a - // ``certificate expired'' verification error occurs, no other - // certificate will be searched. Make sure to not have expired - // certificates mixed with valid ones. - // - // See also: QSslSocketBackendPrivate::verify() - if (caCertificate.expiryDate() >= now) { - q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle()); - } - } - - if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) { - // tell OpenSSL the directories where to look up the root certs on demand - const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories(); - for (const QByteArray &unixDir : unixDirs) - q_SSL_CTX_load_verify_locations(sslContext->ctx, nullptr, unixDir.constData()); - } - - if (!sslContext->sslConfiguration.localCertificate().isNull()) { - // Require a private key as well. - if (sslContext->sslConfiguration.privateKey().isNull()) { - sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - // Load certificate - if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) { - sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - if (configuration.d->privateKey.algorithm() == QSsl::Opaque) { - sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle()); - } else { - // Load private key - sslContext->pkey = q_EVP_PKEY_new(); - // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free. - // this lead to a memory leak. Now we use the *_set1_* functions which do not - // take ownership of the RSA/DSA key instance because the QSslKey already has ownership. - if (configuration.d->privateKey.algorithm() == QSsl::Rsa) - q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle())); - else if (configuration.d->privateKey.algorithm() == QSsl::Dsa) - q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle())); -#ifndef OPENSSL_NO_EC - else if (configuration.d->privateKey.algorithm() == QSsl::Ec) - q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle())); -#endif - } - - if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) { - sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - if (configuration.d->privateKey.algorithm() == QSsl::Opaque) - sslContext->pkey = nullptr; // Don't free the private key, it belongs to QSslKey - - // Check if the certificate matches the private key. - if (!q_SSL_CTX_check_private_key(sslContext->ctx)) { - sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - // If we have any intermediate certificates then we need to add them to our chain - bool first = true; - for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) { - if (first) { - first = false; - continue; - } - q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, - q_X509_dup(reinterpret_cast<X509 *>(cert.handle()))); - } - } - - // Initialize peer verification. - if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) { - q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, nullptr); - } else { - q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, -#if QT_CONFIG(dtls) - isDtls ? dtlscallbacks::q_X509DtlsCallback : -#endif // dtls - q_X509Callback); - } - -#if QT_CONFIG(dtls) - if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) { - q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback); - q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, dtlscallbacks::q_verify_cookie_callback); - } -#endif // dtls - - // Set verification depth. - if (sslContext->sslConfiguration.peerVerifyDepth() != 0) - q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth()); - - // set persisted session if the user set it - if (!configuration.sessionTicket().isEmpty()) - sslContext->setSessionASN1(configuration.sessionTicket()); - - // Set temp DH params - QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters(); - - if (!dhparams.isValid()) { - sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid"); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - if (!dhparams.isEmpty()) { - const QByteArray ¶ms = dhparams.d->derData; - const char *ptr = params.constData(); - DH *dh = q_d2i_DHparams(nullptr, reinterpret_cast<const unsigned char **>(&ptr), - params.length()); - if (dh == nullptr) - qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form"); - q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh); - q_DH_free(dh); - } - -#ifndef OPENSSL_NO_PSK - if (!client) - q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData()); -#endif // !OPENSSL_NO_PSK - - const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves(); - if (!qcurves.isEmpty()) { -#ifdef OPENSSL_NO_EC - sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version with disabled elliptic curves")); - sslContext->errorCode = QSslError::UnspecifiedError; - return; -#else - // Set the curves to be used. - std::vector<int> curves; - curves.reserve(qcurves.size()); - for (const auto &sslCurve : qcurves) - curves.push_back(sslCurve.id); - if (!q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES, long(curves.size()), &curves[0])) { - sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } -#endif - } - - applyBackendConfig(sslContext); -} - -QT_END_NAMESPACE diff --git a/src/network/ssl/qsslcontext_openssl_p.h b/src/network/ssl/qsslcontext_openssl_p.h index 1fa27279c7..70cb97aad8 100644 --- a/src/network/ssl/qsslcontext_openssl_p.h +++ b/src/network/ssl/qsslcontext_openssl_p.h @@ -86,7 +86,7 @@ public: void setSessionASN1(const QByteArray &sessionASN1); int sessionTicketLifeTimeHint() const; -#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifndef OPENSSL_NO_NEXTPROTONEG // must be public because we want to use it from an OpenSSL callback struct NPNContext { NPNContext() : data(nullptr), @@ -98,7 +98,7 @@ public: QSslConfiguration::NextProtocolNegotiationStatus status; }; NPNContext npnContext() const; -#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... +#endif // !OPENSSL_NO_NEXTPROTONEG protected: QSslContext(); @@ -118,10 +118,10 @@ private: QSslError::SslError errorCode; QString errorStr; QSslConfiguration sslConfiguration; -#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifndef OPENSSL_NO_NEXTPROTONEG QByteArray m_supportedNPNVersions; NPNContext m_npnContext; -#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... +#endif // !OPENSSL_NO_NEXTPROTONEG }; #endif // QT_NO_SSL diff --git a/src/network/ssl/qsslcontext_opensslpre11.cpp b/src/network/ssl/qsslcontext_opensslpre11.cpp deleted file mode 100644 index 956c5c32ec..0000000000 --- a/src/network/ssl/qsslcontext_opensslpre11.cpp +++ /dev/null @@ -1,407 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2014 BlackBerry Limited. All rights reserved. -** 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$ -** -****************************************************************************/ - - -#include <QtNetwork/qsslsocket.h> -#include <QtNetwork/qssldiffiehellmanparameters.h> - -#include "private/qssl_p.h" -#include "private/qsslcontext_openssl_p.h" -#include "private/qsslsocket_p.h" -#include "private/qsslsocket_openssl_p.h" -#include "private/qsslsocket_openssl_symbols_p.h" -#include "private/qssldiffiehellmanparameters_p.h" - -QT_BEGIN_NAMESPACE - -// defined in qsslsocket_openssl.cpp: -extern int q_X509Callback(int ok, X509_STORE_CTX *ctx); -extern QString getErrorsFromOpenSsl(); - -#if QT_CONFIG(dtls) -// defined in qdtls_openssl.cpp: -namespace dtlscallbacks -{ -extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx); -extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst, - unsigned *cookieLength); -extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie, - unsigned cookieLength); -} -#endif // dtls - -static inline QString msgErrorSettingEllipticCurves(const QString &why) -{ - return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why); -} - -// Defined in qsslsocket.cpp -QList<QSslCipher> q_getDefaultDtlsCiphers(); - -// static -void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading) -{ - sslContext->sslConfiguration = configuration; - sslContext->errorCode = QSslError::NoError; - - bool client = (mode == QSslSocket::SslClientMode); - bool reinitialized = false; - bool unsupportedProtocol = false; - bool isDtls = false; -init_context: - switch (sslContext->sslConfiguration.protocol()) { -#if QT_CONFIG(dtls) - case QSsl::DtlsV1_0: - isDtls = true; - sslContext->ctx = q_SSL_CTX_new(client ? q_DTLSv1_client_method() : q_DTLSv1_server_method()); - break; - case QSsl::DtlsV1_2: - case QSsl::DtlsV1_2OrLater: - // OpenSSL 1.0.2 and below will probably never receive TLS 1.3, so - // technically 1.2 or later is 1.2 and will stay so. - isDtls = true; - sslContext->ctx = q_SSL_CTX_new(client ? q_DTLSv1_2_client_method() : q_DTLSv1_2_server_method()); - break; - case QSsl::DtlsV1_0OrLater: - isDtls = true; - sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method()); - break; -#else // dtls - case QSsl::DtlsV1_0: - case QSsl::DtlsV1_0OrLater: - case QSsl::DtlsV1_2: - case QSsl::DtlsV1_2OrLater: - sslContext->ctx = nullptr; - unsupportedProtocol = true; - qCWarning(lcSsl, "DTLS protocol requested, but feature 'dtls' is disabled"); - break; -#endif // dtls - case QSsl::SslV2: - case QSsl::SslV3: - // We don't support SSLv2 / SSLv3. - sslContext->ctx = 0; - unsupportedProtocol = true; - break; - case QSsl::SecureProtocols: - // SSLv2 and SSLv3 will be disabled by SSL options - // But we need q_SSLv23_server_method() otherwise AnyProtocol will be unable to connect on Win32. - case QSsl::AnyProtocol: - default: - sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method()); - break; - case QSsl::TlsV1SslV3: - case QSsl::TlsV1_0: - sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method()); - break; - case QSsl::TlsV1_1: -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method()); -#else - // TLS 1.1 not supported by the system, but chosen deliberately -> error - sslContext->ctx = 0; - unsupportedProtocol = true; -#endif - break; - case QSsl::TlsV1_2: -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method()); -#else - // TLS 1.2 not supported by the system, but chosen deliberately -> error - sslContext->ctx = 0; - unsupportedProtocol = true; -#endif - break; - case QSsl::TlsV1_0OrLater: - // Specific protocols will be specified via SSL options. - sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method()); - break; - case QSsl::TlsV1_1OrLater: - case QSsl::TlsV1_2OrLater: -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - // Specific protocols will be specified via SSL options. - sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method()); -#else - // TLS 1.1/1.2 not supported by the system, but chosen deliberately -> error - sslContext->ctx = 0; - unsupportedProtocol = true; -#endif - break; - case QSsl::TlsV1_3: - case QSsl::TlsV1_3OrLater: - // TLS 1.3 is not supported by the system, but chosen deliberately -> error - sslContext->ctx = nullptr; - unsupportedProtocol = true; - break; - } - - if (!client && isDtls && configuration.peerVerifyMode() != QSslSocket::VerifyNone) { - sslContext->errorStr = QSslSocket::tr("DTLS server requires a 'VerifyNone' mode with your version of OpenSSL"); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - if (!sslContext->ctx) { - // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them - // by re-initializing the library. - if (!reinitialized) { - reinitialized = true; - if (q_SSL_library_init() == 1) - goto init_context; - } - - sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg( - unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl() - ); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - // Enable bug workarounds. - // DTLSTODO: check this setupOpenSslOptions ... - long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); - q_SSL_CTX_set_options(sslContext->ctx, options); - - // Tell OpenSSL to release memory early - // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html - q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS); - - // Initialize ciphers - QByteArray cipherString; - bool first = true; - QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers(); - if (ciphers.isEmpty()) - ciphers = isDtls ? q_getDefaultDtlsCiphers() : QSslSocketPrivate::defaultCiphers(); - for (const QSslCipher &cipher : qAsConst(ciphers)) { - if (first) - first = false; - else - cipherString.append(':'); - cipherString.append(cipher.name().toLatin1()); - } - - if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) { - sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - const QDateTime now = QDateTime::currentDateTimeUtc(); - - // Add all our CAs to this store. - const auto caCertificates = sslContext->sslConfiguration.caCertificates(); - for (const QSslCertificate &caCertificate : caCertificates) { - // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html: - // - // If several CA certificates matching the name, key identifier, and - // serial number condition are available, only the first one will be - // examined. This may lead to unexpected results if the same CA - // certificate is available with different expiration dates. If a - // ``certificate expired'' verification error occurs, no other - // certificate will be searched. Make sure to not have expired - // certificates mixed with valid ones. - // - // See also: QSslSocketBackendPrivate::verify() - if (caCertificate.expiryDate() >= now) { - q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle()); - } - } - - if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) { - // tell OpenSSL the directories where to look up the root certs on demand - const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories(); - for (const QByteArray &unixDir : unixDirs) - q_SSL_CTX_load_verify_locations(sslContext->ctx, 0, unixDir.constData()); - } - - if (!sslContext->sslConfiguration.localCertificate().isNull()) { - // Require a private key as well. - if (sslContext->sslConfiguration.privateKey().isNull()) { - sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - // Load certificate - if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) { - sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - if (configuration.d->privateKey.algorithm() == QSsl::Opaque) { - sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle()); - } else { - // Load private key - sslContext->pkey = q_EVP_PKEY_new(); - // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free. - // this lead to a memory leak. Now we use the *_set1_* functions which do not - // take ownership of the RSA/DSA key instance because the QSslKey already has ownership. - if (configuration.d->privateKey.algorithm() == QSsl::Rsa) - q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle())); - else if (configuration.d->privateKey.algorithm() == QSsl::Dsa) - q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle())); -#ifndef OPENSSL_NO_EC - else if (configuration.d->privateKey.algorithm() == QSsl::Ec) - q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle())); -#endif - } - - if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) { - sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - if (configuration.d->privateKey.algorithm() == QSsl::Opaque) - sslContext->pkey = 0; // Don't free the private key, it belongs to QSslKey - - // Check if the certificate matches the private key. - if (!q_SSL_CTX_check_private_key(sslContext->ctx)) { - sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - // If we have any intermediate certificates then we need to add them to our chain - bool first = true; - for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) { - if (first) { - first = false; - continue; - } - q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, - q_X509_dup(reinterpret_cast<X509 *>(cert.handle()))); - } - } - - // Initialize peer verification. - if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) { - q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, 0); - } else { - q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, -#if QT_CONFIG(dtls) - isDtls ? dtlscallbacks::q_X509DtlsCallback : -#endif // dtls - q_X509Callback); - } - -#if QT_CONFIG(dtls) - if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) { - q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback); - q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, CookieVerifyCallback(dtlscallbacks::q_verify_cookie_callback)); - } -#endif // dtls - - // Set verification depth. - if (sslContext->sslConfiguration.peerVerifyDepth() != 0) - q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth()); - - // set persisted session if the user set it - if (!configuration.sessionTicket().isEmpty()) - sslContext->setSessionASN1(configuration.sessionTicket()); - - // Set temp DH params - QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters(); - - if (!dhparams.isValid()) { - sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid"); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - - if (!dhparams.isEmpty()) { - const QByteArray ¶ms = dhparams.d->derData; - const char *ptr = params.constData(); - DH *dh = q_d2i_DHparams(NULL, reinterpret_cast<const unsigned char **>(&ptr), params.length()); - if (dh == NULL) - qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form"); - q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh); - q_DH_free(dh); - } - -#ifndef OPENSSL_NO_EC -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (q_SSLeay() >= 0x10002000L) { - q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL); - } else -#endif - { - // Set temp ECDH params - EC_KEY *ecdh = 0; - ecdh = q_EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - q_SSL_CTX_set_tmp_ecdh(sslContext->ctx, ecdh); - q_EC_KEY_free(ecdh); - } -#endif // OPENSSL_NO_EC - -#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) - if (!client) - q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData()); -#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) - - const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves(); - if (!qcurves.isEmpty()) { -#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC) - // Set the curves to be used - if (q_SSLeay() >= 0x10002000L) { - // SSL_CTX_ctrl wants a non-const pointer as last argument, - // but let's avoid a copy into a temporary array - if (!q_SSL_CTX_ctrl(sslContext->ctx, - SSL_CTRL_SET_CURVES, - qcurves.size(), - const_cast<int *>(reinterpret_cast<const int *>(qcurves.data())))) { - sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl()); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - } else -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC) - { - // specific curves requested, but not possible to set -> error - sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version too old, need at least v1.0.2")); - sslContext->errorCode = QSslError::UnspecifiedError; - return; - } - } - - applyBackendConfig(sslContext); -} - -QT_END_NAMESPACE diff --git a/src/network/ssl/qsslellipticcurve_openssl.cpp b/src/network/ssl/qsslellipticcurve_openssl.cpp index b5e38ada53..bb7ad66bd2 100644 --- a/src/network/ssl/qsslellipticcurve_openssl.cpp +++ b/src/network/ssl/qsslellipticcurve_openssl.cpp @@ -83,10 +83,8 @@ QSslEllipticCurve QSslEllipticCurve::fromShortName(const QString &name) const QByteArray curveNameLatin1 = name.toLatin1(); int nid = q_OBJ_sn2nid(curveNameLatin1.data()); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (nid == 0 && QSslSocket::sslLibraryVersionNumber() >= 0x10002000L) + if (nid == 0) nid = q_EC_curve_nist2nid(curveNameLatin1.data()); -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L result.id = nid; diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp index 888058df22..43cb8c6de8 100644 --- a/src/network/ssl/qsslkey_openssl.cpp +++ b/src/network/ssl/qsslkey_openssl.cpp @@ -93,11 +93,7 @@ bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey) if (pkey == nullptr) return false; -#if QT_CONFIG(opensslv11) const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey)); -#else - const int keyType = pkey->type; -#endif if (keyType == EVP_PKEY_RSA) { isNull = false; algorithm = QSsl::Rsa; @@ -350,33 +346,17 @@ static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, QByteArray output; output.resize(data.size() + EVP_MAX_BLOCK_LENGTH); -#if QT_CONFIG(opensslv11) EVP_CIPHER_CTX *ctx = q_EVP_CIPHER_CTX_new(); q_EVP_CIPHER_CTX_reset(ctx); -#else - EVP_CIPHER_CTX evpCipherContext; - EVP_CIPHER_CTX *ctx = &evpCipherContext; - q_EVP_CIPHER_CTX_init(ctx); -#endif - q_EVP_CipherInit(ctx, type, nullptr, nullptr, enc); q_EVP_CIPHER_CTX_set_key_length(ctx, key.size()); if (cipher == QSslKeyPrivate::Rc2Cbc) q_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), nullptr); -#if QT_CONFIG(opensslv11) - // EVP_CipherInit in 1.1 resets the context thus making the calls above useless. - // We call EVP_CipherInit_ex instead. q_EVP_CipherInit_ex(ctx, nullptr, nullptr, reinterpret_cast<const unsigned char *>(key.constData()), reinterpret_cast<const unsigned char *>(iv.constData()), enc); -#else - q_EVP_CipherInit(ctx, NULL, - reinterpret_cast<const unsigned char *>(key.constData()), - reinterpret_cast<const unsigned char *>(iv.constData()), enc); -#endif // opensslv11 - q_EVP_CipherUpdate(ctx, reinterpret_cast<unsigned char *>(output.data()), &len, reinterpret_cast<const unsigned char *>(data.constData()), data.size()); @@ -384,12 +364,8 @@ static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, reinterpret_cast<unsigned char *>(output.data()) + len, &i); len += i; -#if QT_CONFIG(opensslv11) q_EVP_CIPHER_CTX_reset(ctx); q_EVP_CIPHER_CTX_free(ctx); -#else - q_EVP_CIPHER_CTX_cleanup(ctx); -#endif return output.left(len); } diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index d4bad1b1a5..8cd0724d83 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -66,15 +66,12 @@ #include "qsslpresharedkeyauthenticator.h" #include "qsslpresharedkeyauthenticator_p.h" #include "qocspresponse_p.h" +#include "qsslkey.h" #ifdef Q_OS_WIN #include "qwindowscarootfetcher_p.h" #endif -#if !QT_CONFIG(opensslv11) -#include <openssl/x509_vfy.h> -#endif - #include <QtCore/qdatetime.h> #include <QtCore/qdebug.h> #include <QtCore/qdir.h> @@ -87,6 +84,8 @@ #include <QtCore/qurl.h> #include <QtCore/qvarlengtharray.h> #include <QtCore/qscopedvaluerollback.h> +#include <QtCore/qlibrary.h> +#include <QtCore/qoperatingsystemversion.h> #if QT_CONFIG(ocsp) #include "qocsp_p.h" @@ -98,13 +97,12 @@ QT_BEGIN_NAMESPACE +Q_GLOBAL_STATIC(QRecursiveMutex, qt_opensslInitMutex) + bool QSslSocketPrivate::s_libraryLoaded = false; bool QSslSocketPrivate::s_loadedCiphersAndCerts = false; bool QSslSocketPrivate::s_loadRootCertsOnDemand = false; - -#if OPENSSL_VERSION_NUMBER >= 0x10001000L int QSslSocketBackendPrivate::s_indexForSSLExtraData = -1; -#endif QString QSslSocketBackendPrivate::getErrorsFromOpenSsl() { @@ -122,7 +120,7 @@ QString QSslSocketBackendPrivate::getErrorsFromOpenSsl() extern "C" { -#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) +#ifndef OPENSSL_NO_PSK static unsigned int q_ssl_psk_client_callback(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, @@ -143,7 +141,6 @@ static unsigned int q_ssl_psk_server_callback(SSL *ssl, } #ifdef TLS1_3_VERSION -#ifndef OPENSSL_NO_PSK static unsigned int q_ssl_psk_restore_client(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, @@ -164,7 +161,6 @@ static unsigned int q_ssl_psk_restore_client(SSL *ssl, return 0; } -#endif // !OPENSSL_NO_PSK static int q_ssl_psk_use_session_callback(SSL *ssl, const EVP_MD *md, const unsigned char **id, size_t *idlen, SSL_SESSION **sess) @@ -175,7 +171,6 @@ static int q_ssl_psk_use_session_callback(SSL *ssl, const EVP_MD *md, const unsi Q_UNUSED(idlen); Q_UNUSED(sess); -#ifndef OPENSSL_NO_PSK #ifdef QT_DEBUG QSslSocketBackendPrivate *d = reinterpret_cast<QSslSocketBackendPrivate *>(q_SSL_get_ex_data(ssl, QSslSocketBackendPrivate::s_indexForSSLExtraData)); Q_ASSERT(d); @@ -184,13 +179,12 @@ static int q_ssl_psk_use_session_callback(SSL *ssl, const EVP_MD *md, const unsi // Temporarily rebind the psk because it will be called next. The function will restore it. q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_restore_client); -#endif return 1; // need to return 1 or else "the connection setup fails." } #endif // TLS1_3_VERSION -#endif +#endif // !OPENSSL_NO_PSK #if QT_CONFIG(ocsp) @@ -407,13 +401,8 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx) ErrorListPtr errors = nullptr; // Error list is attached to either 'SSL' or 'X509_STORE'. - if (X509_STORE *store = q_X509_STORE_CTX_get0_store(ctx)) { // We try store first: -#if QT_CONFIG(opensslv11) + if (X509_STORE *store = q_X509_STORE_CTX_get0_store(ctx)) // We try store first: errors = ErrorListPtr(q_X509_STORE_get_ex_data(store, 0)); -#else - errors = ErrorListPtr(q_CRYPTO_get_ex_data(&store->ex_data, 0)); -#endif // opensslv11 - } if (!errors) { // Not found on store? Try SSL and its external data then. According to the OpenSSL's @@ -476,17 +465,12 @@ long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, Q options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3; else if (protocol == QSsl::TlsV1_0OrLater) options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3; -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - // Choosing Tlsv1_1OrLater or TlsV1_2OrLater on OpenSSL < 1.0.1 - // will cause an error in QSslContext::fromConfiguration, meaning - // we will never get here. else if (protocol == QSsl::TlsV1_1OrLater) options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1; else if (protocol == QSsl::TlsV1_2OrLater) options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1; else if (protocol == QSsl::TlsV1_3OrLater) options = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2; -#endif else options = SSL_OP_ALL; @@ -590,15 +574,13 @@ bool QSslSocketBackendPrivate::initSslContext() q_SSL_set_ex_data(ssl, s_indexForSSLExtraData, this); -#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) +#ifndef OPENSSL_NO_PSK // Set the client callback for PSK - if (QSslSocket::sslLibraryVersionNumber() >= 0x10001000L) { - if (mode == QSslSocket::SslClientMode) - q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback); - else if (mode == QSslSocket::SslServerMode) - q_SSL_set_psk_server_callback(ssl, &q_ssl_psk_server_callback); - } -#endif + if (mode == QSslSocket::SslClientMode) + q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback); + else if (mode == QSslSocket::SslServerMode) + q_SSL_set_psk_server_callback(ssl, &q_ssl_psk_server_callback); + #if OPENSSL_VERSION_NUMBER >= 0x10101006L // Set the client callback for TLSv1.3 PSK if (mode == QSslSocket::SslClientMode @@ -607,6 +589,9 @@ bool QSslSocketBackendPrivate::initSslContext() } #endif // openssl version >= 0x10101006L +#endif // OPENSSL_NO_PSK + + #if QT_CONFIG(ocsp) if (configuration.ocspStaplingEnabled) { if (mode == QSslSocket::SslServerMode) { @@ -673,10 +658,43 @@ bool QSslSocketPrivate::supportsSsl() /*! \internal + Returns the version number of the SSL library in use. Note that + this is the version of the library in use at run-time, not compile + time. +*/ +long QSslSocketPrivate::sslLibraryVersionNumber() +{ + if (!supportsSsl()) + return 0; + + return q_OpenSSL_version_num(); +} + +/*! + \internal + + Returns the version string of the SSL library in use. Note that + this is the version of the library in use at run-time, not compile + time. If no SSL support is available then this will return an empty value. +*/ +QString QSslSocketPrivate::sslLibraryVersionString() +{ + if (!supportsSsl()) + return QString(); + + const char *versionString = q_OpenSSL_version(OPENSSL_VERSION); + if (!versionString) + return QString(); + + return QString::fromLatin1(versionString); +} + +/*! + \internal + Declared static in QSslSocketPrivate, makes sure the SSL libraries have been initialized. */ - void QSslSocketPrivate::ensureInitialized() { if (!supportsSsl()) @@ -685,11 +703,23 @@ void QSslSocketPrivate::ensureInitialized() ensureCiphersAndCertsLoaded(); } +/*! + \internal + + Returns the version number of the SSL library in use at compile + time. +*/ long QSslSocketPrivate::sslLibraryBuildVersionNumber() { return OPENSSL_VERSION_NUMBER; } +/*! + \internal + + Returns the version string of the SSL library in use at compile + time. +*/ QString QSslSocketPrivate::sslLibraryBuildVersionString() { // Using QStringLiteral to store the version string as unicode and @@ -706,11 +736,7 @@ QString QSslSocketPrivate::sslLibraryBuildVersionString() */ void QSslSocketPrivate::resetDefaultCiphers() { -#if QT_CONFIG(opensslv11) SSL_CTX *myCtx = q_SSL_CTX_new(q_TLS_client_method()); -#else - SSL_CTX *myCtx = q_SSL_CTX_new(q_SSLv23_client_method()); -#endif // Note, we assert, not just silently return/bail out early: // this should never happen and problems with OpenSSL's initialization // must be caught before this (see supportsSsl()). @@ -1737,6 +1763,174 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const return QSsl::UnknownProtocol; } + +void QSslSocketBackendPrivate::continueHandshake() +{ + Q_Q(QSslSocket); + // if we have a max read buffer size, reset the plain socket's to match + if (readBufferMaxSize) + plainSocket->setReadBufferSize(readBufferMaxSize); + + if (q_SSL_session_reused(ssl)) + configuration.peerSessionShared = true; + +#ifdef QT_DECRYPT_SSL_TRAFFIC + if (q_SSL_get_session(ssl)) { + size_t master_key_len = q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl), 0, 0); + size_t client_random_len = q_SSL_get_client_random(ssl, 0, 0); + QByteArray masterKey(int(master_key_len), 0); // Will not overflow + QByteArray clientRandom(int(client_random_len), 0); // Will not overflow + + q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl), + reinterpret_cast<unsigned char*>(masterKey.data()), + masterKey.size()); + q_SSL_get_client_random(ssl, reinterpret_cast<unsigned char *>(clientRandom.data()), + clientRandom.size()); + + QByteArray debugLineClientRandom("CLIENT_RANDOM "); + debugLineClientRandom.append(clientRandom.toHex().toUpper()); + debugLineClientRandom.append(" "); + debugLineClientRandom.append(masterKey.toHex().toUpper()); + debugLineClientRandom.append("\n"); + + 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"; + if (!file.write(debugLineClientRandom)) + qCWarning(lcSsl) << "could not write to file" << sslKeyFile; + file.close(); + } else { + qCWarning(lcSsl, "could not decrypt SSL traffic"); + } +#endif + + // Cache this SSL session inside the QSslContext + if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) { + if (!sslContextPointer->cacheSession(ssl)) { + sslContextPointer.clear(); // we could not cache the session + } else { + // Cache the session for permanent usage as well + if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) { + if (!sslContextPointer->sessionASN1().isEmpty()) + configuration.sslSession = sslContextPointer->sessionASN1(); + configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint(); + } + } + } + +#if !defined(OPENSSL_NO_NEXTPROTONEG) + + configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status; + if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) { + // we could not agree -> be conservative and use HTTP/1.1 + configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1"); + } else { + const unsigned char *proto = nullptr; + unsigned int proto_len = 0; + + q_SSL_get0_alpn_selected(ssl, &proto, &proto_len); + if (proto_len && mode == QSslSocket::SslClientMode) { + // Client does not have a callback that sets it ... + configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated; + } + + if (!proto_len) { // Test if NPN was more lucky ... + q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len); + } + + if (proto_len) + configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len); + else + configuration.nextNegotiatedProtocol.clear(); + } +#endif // !defined(OPENSSL_NO_NEXTPROTONEG) + + if (mode == QSslSocket::SslClientMode) { + EVP_PKEY *key; + if (q_SSL_get_server_tmp_key(ssl, &key)) + configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey); + } + + connectionEncrypted = true; + emit q->encrypted(); + if (autoStartHandshake && pendingClose) { + pendingClose = false; + q->disconnectFromHost(); + } +} + +bool QSslSocketPrivate::ensureLibraryLoaded() +{ + if (!q_resolveOpenSslSymbols()) + return false; + + const QMutexLocker locker(qt_opensslInitMutex); + + if (!s_libraryLoaded) { + // Initialize OpenSSL. + if (q_OPENSSL_init_ssl(0, nullptr) != 1) + return false; + q_SSL_load_error_strings(); + q_OpenSSL_add_all_algorithms(); + + QSslSocketBackendPrivate::s_indexForSSLExtraData + = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr, + nullptr, nullptr); + + // Initialize OpenSSL's random seed. + if (!q_RAND_status()) { + qWarning("Random number generator not seeded, disabling SSL support"); + return false; + } + + s_libraryLoaded = true; + } + return true; +} + +void QSslSocketPrivate::ensureCiphersAndCertsLoaded() +{ + const QMutexLocker locker(qt_opensslInitMutex); + + if (s_loadedCiphersAndCerts) + return; + s_loadedCiphersAndCerts = true; + + resetDefaultCiphers(); + resetDefaultEllipticCurves(); + +#if QT_CONFIG(library) + //load symbols needed to receive certificates from system store +#if defined(Q_OS_QNX) + s_loadRootCertsOnDemand = true; +#elif defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) + // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there) + QList<QByteArray> dirs = unixRootCertDirectories(); + QStringList symLinkFilter; + symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]"); + for (int a = 0; a < dirs.count(); ++a) { + QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files); + if (iterator.hasNext()) { + s_loadRootCertsOnDemand = true; + break; + } + } +#endif +#endif // QT_CONFIG(library) + // if on-demand loading was not enabled, load the certs now + if (!s_loadRootCertsOnDemand) + setDefaultCaCertificates(systemCaCertificates()); +#ifdef Q_OS_WIN + //Enabled for fetching additional root certs from windows update on windows. + //This flag is set false by setDefaultCaCertificates() indicating the app uses + //its own cert bundle rather than the system one. + //Same logic that disables the unix on demand cert loading. + //Unlike unix, we do preload the certificates from the cert store. + s_loadRootCertsOnDemand = true; +#endif +} + QList<QSslCertificate> QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509) { ensureInitialized(); @@ -1788,19 +1982,11 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> & } QVector<QSslErrorEntry> lastErrors; -#if QT_CONFIG(opensslv11) if (!q_X509_STORE_set_ex_data(certStore, 0, &lastErrors)) { qCWarning(lcSsl) << "Unable to attach external data (error list) to a store"; errors << QSslError(QSslError::UnspecifiedError); return errors; } -#else - if (!q_CRYPTO_set_ex_data(&certStore->ex_data, 0, &lastErrors)) { - qCWarning(lcSsl) << "Unable to attach external data (error list) to a store"; - errors << QSslError(QSslError::UnspecifiedError); - return errors; - } -#endif // opensslv11 // Register a custom callback to get all verification errors. q_X509_STORE_set_verify_cb(certStore, q_X509Callback); diff --git a/src/network/ssl/qsslsocket_openssl11.cpp b/src/network/ssl/qsslsocket_openssl11.cpp deleted file mode 100644 index 1d935c5217..0000000000 --- a/src/network/ssl/qsslsocket_openssl11.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2014 Governikus GmbH & Co. KG -** Copyright (C) 2016 Richard J. Moore <rich@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** 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. -** -****************************************************************************/ - -//#define QT_DECRYPT_SSL_TRAFFIC - -#include "qssl_p.h" -#include "qsslsocket_openssl_p.h" -#include "qsslsocket_openssl_symbols_p.h" -#include "qsslsocket.h" -#include "qsslkey.h" - -#include <QtCore/qdebug.h> -#include <QtCore/qdir.h> -#include <QtCore/qdiriterator.h> -#include <QtCore/qfile.h> -#include <QtCore/qmutex.h> -#include <QtCore/qlibrary.h> -#include <QtCore/qoperatingsystemversion.h> - -QT_BEGIN_NAMESPACE - -Q_GLOBAL_STATIC(QRecursiveMutex, qt_opensslInitMutex) - -void QSslSocketPrivate::deinitialize() -{ - // This function exists only for compatibility with the pre-11 code, - // where deinitialize() actually does some cleanup. To be discarded - // once we retire < 1.1. -} - -bool QSslSocketPrivate::ensureLibraryLoaded() -{ - if (!q_resolveOpenSslSymbols()) - return false; - - const QMutexLocker locker(qt_opensslInitMutex); - - if (!s_libraryLoaded) { - // Initialize OpenSSL. - if (q_OPENSSL_init_ssl(0, nullptr) != 1) - return false; - q_SSL_load_error_strings(); - q_OpenSSL_add_all_algorithms(); - - QSslSocketBackendPrivate::s_indexForSSLExtraData - = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr, - nullptr, nullptr); - - // Initialize OpenSSL's random seed. - if (!q_RAND_status()) { - qWarning("Random number generator not seeded, disabling SSL support"); - return false; - } - - s_libraryLoaded = true; - } - return true; -} - -void QSslSocketPrivate::ensureCiphersAndCertsLoaded() -{ - const QMutexLocker locker(qt_opensslInitMutex); - - if (s_loadedCiphersAndCerts) - return; - s_loadedCiphersAndCerts = true; - - resetDefaultCiphers(); - resetDefaultEllipticCurves(); - -#if QT_CONFIG(library) - //load symbols needed to receive certificates from system store -#if defined(Q_OS_QNX) - s_loadRootCertsOnDemand = true; -#elif defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) - // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there) - QList<QByteArray> dirs = unixRootCertDirectories(); - QStringList symLinkFilter; - symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]"); - for (int a = 0; a < dirs.count(); ++a) { - QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files); - if (iterator.hasNext()) { - s_loadRootCertsOnDemand = true; - break; - } - } -#endif -#endif // QT_CONFIG(library) - // if on-demand loading was not enabled, load the certs now - if (!s_loadRootCertsOnDemand) - setDefaultCaCertificates(systemCaCertificates()); -#ifdef Q_OS_WIN - //Enabled for fetching additional root certs from windows update on windows. - //This flag is set false by setDefaultCaCertificates() indicating the app uses - //its own cert bundle rather than the system one. - //Same logic that disables the unix on demand cert loading. - //Unlike unix, we do preload the certificates from the cert store. - s_loadRootCertsOnDemand = true; -#endif -} - -long QSslSocketPrivate::sslLibraryVersionNumber() -{ - if (!supportsSsl()) - return 0; - - return q_OpenSSL_version_num(); -} - -QString QSslSocketPrivate::sslLibraryVersionString() -{ - if (!supportsSsl()) - return QString(); - - const char *versionString = q_OpenSSL_version(OPENSSL_VERSION); - if (!versionString) - return QString(); - - return QString::fromLatin1(versionString); -} - -void QSslSocketBackendPrivate::continueHandshake() -{ - Q_Q(QSslSocket); - // if we have a max read buffer size, reset the plain socket's to match - if (readBufferMaxSize) - plainSocket->setReadBufferSize(readBufferMaxSize); - - if (q_SSL_session_reused(ssl)) - configuration.peerSessionShared = true; - -#ifdef QT_DECRYPT_SSL_TRAFFIC - if (q_SSL_get_session(ssl)) { - size_t master_key_len = q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl), 0, 0); - size_t client_random_len = q_SSL_get_client_random(ssl, 0, 0); - QByteArray masterKey(int(master_key_len), 0); // Will not overflow - QByteArray clientRandom(int(client_random_len), 0); // Will not overflow - - q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl), - reinterpret_cast<unsigned char*>(masterKey.data()), - masterKey.size()); - q_SSL_get_client_random(ssl, reinterpret_cast<unsigned char *>(clientRandom.data()), - clientRandom.size()); - - QByteArray debugLineClientRandom("CLIENT_RANDOM "); - debugLineClientRandom.append(clientRandom.toHex().toUpper()); - debugLineClientRandom.append(" "); - debugLineClientRandom.append(masterKey.toHex().toUpper()); - debugLineClientRandom.append("\n"); - - 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"; - if (!file.write(debugLineClientRandom)) - qCWarning(lcSsl) << "could not write to file" << sslKeyFile; - file.close(); - } else { - qCWarning(lcSsl, "could not decrypt SSL traffic"); - } -#endif - - // Cache this SSL session inside the QSslContext - if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) { - if (!sslContextPointer->cacheSession(ssl)) { - sslContextPointer.clear(); // we could not cache the session - } else { - // Cache the session for permanent usage as well - if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) { - if (!sslContextPointer->sessionASN1().isEmpty()) - configuration.sslSession = sslContextPointer->sessionASN1(); - configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint(); - } - } - } - -#if !defined(OPENSSL_NO_NEXTPROTONEG) - - configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status; - if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) { - // we could not agree -> be conservative and use HTTP/1.1 - configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1"); - } else { - const unsigned char *proto = nullptr; - unsigned int proto_len = 0; - - q_SSL_get0_alpn_selected(ssl, &proto, &proto_len); - if (proto_len && mode == QSslSocket::SslClientMode) { - // Client does not have a callback that sets it ... - configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated; - } - - if (!proto_len) { // Test if NPN was more lucky ... - q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len); - } - - if (proto_len) - configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len); - else - configuration.nextNegotiatedProtocol.clear(); - } -#endif // !defined(OPENSSL_NO_NEXTPROTONEG) - - if (mode == QSslSocket::SslClientMode) { - EVP_PKEY *key; - if (q_SSL_get_server_tmp_key(ssl, &key)) - configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey); - } - - connectionEncrypted = true; - emit q->encrypted(); - if (autoStartHandshake && pendingClose) { - pendingClose = false; - q->disconnectFromHost(); - } -} - -QT_END_NAMESPACE diff --git a/src/network/ssl/qsslsocket_openssl11_symbols_p.h b/src/network/ssl/qsslsocket_openssl11_symbols_p.h deleted file mode 100644 index 0fe0899d4f..0000000000 --- a/src/network/ssl/qsslsocket_openssl11_symbols_p.h +++ /dev/null @@ -1,195 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2014 BlackBerry Limited. All rights reserved. -** Copyright (C) 2016 Richard J. Moore <rich@kde.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** 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. -** -****************************************************************************/ - -#ifndef QSSLSOCKET_OPENSSL11_SYMBOLS_P_H -#define QSSLSOCKET_OPENSSL11_SYMBOLS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -// Note: this file does not have QT_BEGIN_NAMESPACE/QT_END_NAMESPACE, it's done -// in qsslsocket_openssl_symbols_p.h. - -#ifndef QSSLSOCKET_OPENSSL_SYMBOLS_P_H -#error "You are not supposed to use this header file, include qsslsocket_openssl_symbols_p.h instead" -#endif - -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(); - -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_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_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); -size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen); -size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen); -int q_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); -const SSL_METHOD *q_TLS_method(); -const SSL_METHOD *q_TLS_client_method(); -const SSL_METHOD *q_TLS_server_method(); -ASN1_TIME *q_X509_getm_notBefore(X509 *a); -ASN1_TIME *q_X509_getm_notAfter(X509 *a); - -Q_AUTOTEST_EXPORT 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); -int q_X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data); -void *q_X509_STORE_get_ex_data(X509_STORE *r, int idx); -STACK_OF(X509) *q_X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx); -void q_DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); -int q_DH_bits(DH *dh); - -# define q_SSL_load_error_strings() q_OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \ - | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL) - -#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_OPENSSL_sk_num)(st) -#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_OPENSSL_sk_value)(st, i) - -#define q_OPENSSL_add_all_algorithms_conf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ - | OPENSSL_INIT_ADD_ALL_DIGESTS \ - | OPENSSL_INIT_LOAD_CONFIG, NULL) -#define q_OPENSSL_add_all_algorithms_noconf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ - | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL) - -int q_OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); -void q_CRYPTO_free(void *str, const char *file, int line); - -long q_OpenSSL_version_num(); -const char *q_OpenSSL_version(int type); - -unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session); -unsigned long q_SSL_set_options(SSL *s, unsigned long op); - -#ifdef TLS1_3_VERSION -int q_SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str); -#endif - -#if QT_CONFIG(dtls) -// Functions and types required for DTLS support: -extern "C" -{ - -typedef int (*CookieVerifyCallback)(SSL *, const unsigned char *, unsigned); -typedef int (*DgramWriteCallback) (BIO *, const char *, int); -typedef int (*DgramReadCallback) (BIO *, char *, int); -typedef int (*DgramPutsCallback) (BIO *, const char *); -typedef long (*DgramCtrlCallback) (BIO *, int, long, void *); -typedef int (*DgramCreateCallback) (BIO *); -typedef int (*DgramDestroyCallback) (BIO *); - -} - -int q_DTLSv1_listen(SSL *s, BIO_ADDR *client); -BIO_ADDR *q_BIO_ADDR_new(); -void q_BIO_ADDR_free(BIO_ADDR *ap); - -// API we need for a custom dgram BIO: - -BIO_METHOD *q_BIO_meth_new(int type, const char *name); -void q_BIO_meth_free(BIO_METHOD *biom); -int q_BIO_meth_set_write(BIO_METHOD *biom, DgramWriteCallback); -int q_BIO_meth_set_read(BIO_METHOD *biom, DgramReadCallback); -int q_BIO_meth_set_puts(BIO_METHOD *biom, DgramPutsCallback); -int q_BIO_meth_set_ctrl(BIO_METHOD *biom, DgramCtrlCallback); -int q_BIO_meth_set_create(BIO_METHOD *biom, DgramCreateCallback); -int q_BIO_meth_set_destroy(BIO_METHOD *biom, DgramDestroyCallback); - -#endif // dtls - -void q_BIO_set_data(BIO *a, void *ptr); -void *q_BIO_get_data(BIO *a); -void q_BIO_set_init(BIO *a, int init); -int q_BIO_get_shutdown(BIO *a); -void q_BIO_set_shutdown(BIO *a, int shut); - -#if QT_CONFIG(ocsp) -const OCSP_CERTID *q_OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *x); -#endif // ocsp - -#define q_SSL_CTX_set_min_proto_version(ctx, version) \ - q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, nullptr) - -#define q_SSL_CTX_set_max_proto_version(ctx, version) \ - q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, nullptr) - -extern "C" { -typedef int (*q_SSL_psk_use_session_cb_func_t)(SSL *, const EVP_MD *, const unsigned char **, size_t *, - SSL_SESSION **); -} -void q_SSL_set_psk_use_session_callback(SSL *s, q_SSL_psk_use_session_cb_func_t); - -#endif diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index c23234e291..0370a7d2ac 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -130,9 +130,7 @@ public: BIO *writeBio; SSL_SESSION *session; QVector<QSslErrorEntry> errorList; -#if OPENSSL_VERSION_NUMBER >= 0x10001000L static int s_indexForSSLExtraData; // index used in SSL_get_ex_data to get the matching QSslSocketBackendPrivate -#endif bool inSetAndEmitError = false; diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 1fcfdf9f16..3504924888 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -137,10 +137,6 @@ void qsslSocketCannotResolveSymbolWarning(const char *functionName) #endif // QT_LINKED_OPENSSL -#if QT_CONFIG(opensslv11) - -// Below are the functions first introduced in version 1.1: - DEFINEFUNC(const unsigned char *, ASN1_STRING_get0_data, const ASN1_STRING *a, a, return nullptr, return) DEFINEFUNC2(int, OPENSSL_init_ssl, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return) DEFINEFUNC2(int, OPENSSL_init_crypto, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return) @@ -237,93 +233,6 @@ DEFINEFUNC2(void, BIO_set_init, BIO *a, a, int init, init, return, DUMMYARG) DEFINEFUNC(int, BIO_get_shutdown, BIO *a, a, return -1, return) DEFINEFUNC2(void, BIO_set_shutdown, BIO *a, a, int shut, shut, return, DUMMYARG) -#else // QT_CONFIG(opensslv11) - -// Functions below are either deprecated or removed in OpenSSL >= 1.1: - -DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return nullptr, return) - -#ifdef SSLEAY_MACROS -DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return nullptr, return) -#endif -DEFINEFUNC2(BIO *, BIO_new_file, const char *filename, filename, const char *mode, mode, return nullptr, return) -DEFINEFUNC(void, ERR_clear_error, DUMMYARG, DUMMYARG, return, DUMMYARG) -DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return nullptr, return) -DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return nullptr, return) -DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG) -DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG) -DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG) -DEFINEFUNC3(int, CRYPTO_set_ex_data, CRYPTO_EX_DATA *ad, ad, int idx, idx, void *val, val, return 0, return) -DEFINEFUNC2(void *, CRYPTO_get_ex_data, const CRYPTO_EX_DATA *ad, ad, int idx, idx, return nullptr, return) -DEFINEFUNC(unsigned long, ERR_peek_last_error, DUMMYARG, DUMMYARG, return 0, return) -DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG) -DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG) -DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG) - -#ifdef SSLEAY_MACROS -DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return nullptr, return) -DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return nullptr, return) -#endif // SSLEAY_MACROS - -DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return) -DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG) - -DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return) -DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG) -DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG) -DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return nullptr, return) - -DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return) -DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG) - -#if OPENSSL_VERSION_NUMBER >= 0x10001000L -DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return) -#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L - -DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return nullptr, return) -DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return nullptr, return) -#if OPENSSL_VERSION_NUMBER >= 0x10001000L -DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return nullptr, return) -DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return nullptr, return) -#endif -DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return nullptr, return) -DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return nullptr, return) -#if OPENSSL_VERSION_NUMBER >= 0x10001000L -DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return nullptr, return) -DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return nullptr, return) -#endif - -DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return nullptr, return) - -#ifdef SSLEAY_MACROS -DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return) -DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, return -1, return) -#ifndef OPENSSL_NO_EC -DEFINEFUNC2(int, i2d_ECPrivateKey, const EC_KEY *a, a, unsigned char **b, b, return -1, return) -#endif -DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return nullptr, return) -DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return nullptr, return) -#ifndef OPENSSL_NO_EC -DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return nullptr, return) -#endif -#endif - -#if QT_CONFIG(dtls) -DEFINEFUNC(const SSL_METHOD *, DTLSv1_server_method, void, DUMMYARG, return nullptr, return) -DEFINEFUNC(const SSL_METHOD *, DTLSv1_client_method, void, DUMMYARG, return nullptr, return) -DEFINEFUNC(const SSL_METHOD *, DTLSv1_2_server_method, void, DUMMYARG, return nullptr, return) -DEFINEFUNC(const SSL_METHOD *, DTLSv1_2_client_method, void, DUMMYARG, return nullptr, return) -#endif // dtls - -DEFINEFUNC(char *, CONF_get1_default_config_file, DUMMYARG, DUMMYARG, return nullptr, return) -DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG) -DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG) -DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return) -DEFINEFUNC(const char *, SSLeay_version, int a, a, return nullptr, return) - -#endif // QT_CONFIG(opensslv11) - DEFINEFUNC(long, ASN1_INTEGER_get, ASN1_INTEGER *a, a, return 0, return) DEFINEFUNC2(int, ASN1_INTEGER_cmp, const ASN1_INTEGER *a, a, const ASN1_INTEGER *b, b, return 1, return) DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return) @@ -392,36 +301,28 @@ DEFINEFUNC(int, OBJ_sn2nid, const char *s, s, return 0, return) DEFINEFUNC(int, OBJ_ln2nid, const char *s, s, return 0, return) DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, return -1, return) DEFINEFUNC4(int, OBJ_obj2txt, char *a, a, int b, b, ASN1_OBJECT *c, c, int d, d, return -1, return) - DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return) - -#ifndef SSLEAY_MACROS DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PrivateKey, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) + #ifndef OPENSSL_NO_EC DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -#endif +DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) +DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, return) +#endif // OPENSSL_NO_EC + DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) DEFINEFUNC7(int, PEM_write_bio_PrivateKey, BIO *a, a, EVP_PKEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) -#ifndef OPENSSL_NO_EC -DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) -#endif -#endif // !SSLEAY_MACROS DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PUBKEY, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -#ifndef OPENSSL_NO_EC -DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -#endif DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return) DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return) DEFINEFUNC2(int, PEM_write_bio_PUBKEY, BIO *a, a, EVP_PKEY *b, b, return 0, return) -#ifndef OPENSSL_NO_EC -DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, return) -#endif DEFINEFUNC2(void, RAND_seed, const void *a, a, int b, b, return, DUMMYARG) DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return) DEFINEFUNC2(int, RAND_bytes, unsigned char *b, b, int n, n, return 0, return) @@ -448,14 +349,12 @@ DEFINEFUNC2(int, SSL_CTX_use_PrivateKey, SSL_CTX *a, a, EVP_PKEY *b, b, return - DEFINEFUNC2(int, SSL_CTX_use_RSAPrivateKey, SSL_CTX *a, a, RSA *b, b, return -1, return) DEFINEFUNC3(int, SSL_CTX_use_PrivateKey_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return) DEFINEFUNC(X509_STORE *, SSL_CTX_get_cert_store, const SSL_CTX *a, a, return nullptr, return) -#if OPENSSL_VERSION_NUMBER >= 0x10002000L DEFINEFUNC(SSL_CONF_CTX *, SSL_CONF_CTX_new, DUMMYARG, DUMMYARG, return nullptr, return); DEFINEFUNC(void, SSL_CONF_CTX_free, SSL_CONF_CTX *a, a, return ,return); DEFINEFUNC2(void, SSL_CONF_CTX_set_ssl_ctx, SSL_CONF_CTX *a, a, SSL_CTX *b, b, return, return); DEFINEFUNC2(unsigned int, SSL_CONF_CTX_set_flags, SSL_CONF_CTX *a, a, unsigned int b, b, return 0, return); DEFINEFUNC(int, SSL_CONF_CTX_finish, SSL_CONF_CTX *a, a, return 0, return); DEFINEFUNC3(int, SSL_CONF_cmd, SSL_CONF_CTX *a, a, const char *b, b, const char *c, c, return 0, return); -#endif DEFINEFUNC(void, SSL_free, SSL *a, a, return, DUMMYARG) DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return nullptr, return) DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr, return) @@ -477,21 +376,19 @@ DEFINEFUNC2(int, SSL_set_session, SSL* to, to, SSL_SESSION *session, session, re DEFINEFUNC(void, SSL_SESSION_free, SSL_SESSION *ses, ses, return, DUMMYARG) DEFINEFUNC(SSL_SESSION*, SSL_get1_session, SSL *ssl, ssl, return nullptr, return) DEFINEFUNC(SSL_SESSION*, SSL_get_session, const SSL *ssl, ssl, return nullptr, return) -#if OPENSSL_VERSION_NUMBER >= 0x10001000L DEFINEFUNC3(int, SSL_set_ex_data, SSL *ssl, ssl, int idx, idx, void *arg, arg, return 0, return) DEFINEFUNC2(void *, SSL_get_ex_data, const SSL *ssl, ssl, int idx, idx, return nullptr, return) -#endif -#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) + +#ifndef OPENSSL_NO_PSK DEFINEFUNC2(void, SSL_set_psk_client_callback, SSL* ssl, ssl, q_psk_client_callback_t callback, callback, return, DUMMYARG) DEFINEFUNC2(void, SSL_set_psk_server_callback, SSL* ssl, ssl, q_psk_server_callback_t callback, callback, return, DUMMYARG) DEFINEFUNC2(int, SSL_CTX_use_psk_identity_hint, SSL_CTX* ctx, ctx, const char *hint, hint, return 0, return) -#endif +#endif // !OPENSSL_NO_PSK + DEFINEFUNC3(int, SSL_write, SSL *a, a, const void *b, b, int c, c, return -1, return) DEFINEFUNC2(int, X509_cmp, X509 *a, a, X509 *b, b, return -1, return) DEFINEFUNC4(int, X509_digest, const X509 *x509, x509, const EVP_MD *type, type, unsigned char *md, md, unsigned int *len, len, return -1, return) -#ifndef SSLEAY_MACROS DEFINEFUNC(X509 *, X509_dup, X509 *a, a, return nullptr, return) -#endif DEFINEFUNC2(void, X509_print, BIO *a, a, X509 *b, b, return, DUMMYARG); DEFINEFUNC(ASN1_OBJECT *, X509_EXTENSION_get_object, X509_EXTENSION *a, a, return nullptr, return) DEFINEFUNC(void, X509_free, X509 *a, a, return, DUMMYARG) @@ -535,7 +432,8 @@ DEFINEFUNC(int, SSL_get_ex_data_X509_STORE_CTX_idx, DUMMYARG, DUMMYARG, return - DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return) DEFINEFUNC2(int, i2d_SSL_SESSION, SSL_SESSION *in, in, unsigned char **pp, pp, return 0, return) DEFINEFUNC3(SSL_SESSION *, d2i_SSL_SESSION, SSL_SESSION **a, a, const unsigned char **pp, pp, long length, length, return nullptr, return) -#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG) + +#ifndef OPENSSL_NO_NEXTPROTONEG DEFINEFUNC6(int, SSL_select_next_proto, unsigned char **out, out, unsigned char *outlen, outlen, const unsigned char *in, in, unsigned int inlen, inlen, const unsigned char *client, client, unsigned int client_len, client_len, @@ -548,7 +446,6 @@ DEFINEFUNC3(void, SSL_CTX_set_next_proto_select_cb, SSL_CTX *s, s, void *arg, arg, return, DUMMYARG) DEFINEFUNC3(void, SSL_get0_next_proto_negotiated, const SSL *s, s, const unsigned char **data, data, unsigned *len, len, return, DUMMYARG) -#if OPENSSL_VERSION_NUMBER >= 0x10002000L DEFINEFUNC3(int, SSL_set_alpn_protos, SSL *s, s, const unsigned char *protos, protos, unsigned protos_len, protos_len, return -1, return) DEFINEFUNC3(void, SSL_CTX_set_alpn_select_cb, SSL_CTX *s, s, @@ -559,8 +456,7 @@ DEFINEFUNC3(void, SSL_CTX_set_alpn_select_cb, SSL_CTX *s, s, void *arg, arg, return, DUMMYARG) DEFINEFUNC3(void, SSL_get0_alpn_selected, const SSL *s, s, const unsigned char **data, data, unsigned *len, len, return, DUMMYARG) -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... -#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... +#endif // !OPENSSL_NO_NEXTPROTONEG // DTLS: #if QT_CONFIG(dtls) @@ -581,14 +477,13 @@ DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long len DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return) DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return) DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return nullptr, return) + #ifndef OPENSSL_NO_EC DEFINEFUNC(EC_KEY *, EC_KEY_dup, const EC_KEY *ec, ec, return nullptr, return) DEFINEFUNC(EC_KEY *, EC_KEY_new_by_curve_name, int nid, nid, return nullptr, return) DEFINEFUNC(void, EC_KEY_free, EC_KEY *ecdh, ecdh, return, DUMMYARG) DEFINEFUNC2(size_t, EC_get_builtin_curves, EC_builtin_curve * r, r, size_t nitems, nitems, return 0, return) -#if OPENSSL_VERSION_NUMBER >= 0x10002000L DEFINEFUNC(int, EC_curve_nist2nid, const char *name, name, return 0, return) -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L #endif // OPENSSL_NO_EC DEFINEFUNC5(int, PKCS12_parse, PKCS12 *p12, p12, const char *pass, pass, EVP_PKEY **pkey, pkey, \ @@ -760,7 +655,6 @@ static LoadedOpenSsl loadOpenSsl() { LoadedOpenSsl result; -#if QT_CONFIG(opensslv11) // With OpenSSL 1.1 the names have changed to libssl-1_1(-x64) and libcrypto-1_1(-x64), for builds using // MSVC and GCC, (-x64 suffix for 64-bit builds). @@ -774,21 +668,6 @@ static LoadedOpenSsl loadOpenSsl() QLatin1String("libcrypto-1_1" QT_SSL_SUFFIX), result); #undef QT_SSL_SUFFIX - -#else // QT_CONFIG(opensslv11) - - // When OpenSSL is built using MSVC then the libraries are named 'ssleay32.dll' and 'libeay32'dll'. - // When OpenSSL is built using GCC then different library names are used (depending on the OpenSSL version) - // The oldest version of a GCC-based OpenSSL which can be detected by the code below is 0.9.8g (released in 2007) - if (!tryToLoadOpenSslWin32Library(QLatin1String("ssleay32"), QLatin1String("libeay32"), result)) { - if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-10"), QLatin1String("libcrypto-10"), result)) { - if (!tryToLoadOpenSslWin32Library(QLatin1String("libssl-8"), QLatin1String("libcrypto-8"), result)) { - tryToLoadOpenSslWin32Library(QLatin1String("libssl-7"), QLatin1String("libcrypto-7"), result); - } - } - } -#endif // !QT_CONFIG(opensslv11) - return result; } #else @@ -852,27 +731,6 @@ static LoadedOpenSsl loadOpenSsl() libssl->unload(); libcrypto->unload(); } - -#if !QT_CONFIG(opensslv11) - // first-and-half attempts: for OpenSSL 1.0 try to load some hardcoded sonames: - // - "1.0.0" is the official upstream one - // - "1.0.2" is found on some distributions (e.g. Debian) that patch OpenSSL - static const QLatin1String fallbackSonames[] = { - QLatin1String("1.0.0"), - QLatin1String("1.0.2") - }; - - for (auto fallbackSoname : fallbackSonames) { - libssl->setFileNameAndVersion(QLatin1String("ssl"), fallbackSoname); - libcrypto->setFileNameAndVersion(QLatin1String("crypto"), fallbackSoname); - if (libcrypto->load() && libssl->load()) { - return result; - } else { - libssl->unload(); - libcrypto->unload(); - } - } -#endif #endif #ifndef Q_OS_DARWIN @@ -890,11 +748,9 @@ static LoadedOpenSsl loadOpenSsl() return defaultSuffix; return suffix; }; -# if QT_CONFIG(opensslv11) + static QString suffix = QString::fromLatin1(openSSLSuffix("_1_1")); -# else - static QString suffix = QString::fromLatin1(openSSLSuffix()); -# endif + libssl->setFileNameAndVersion(QLatin1String("ssl") + suffix, -1); libcrypto->setFileNameAndVersion(QLatin1String("crypto") + suffix, -1); # else @@ -968,8 +824,6 @@ bool q_resolveOpenSslSymbols() // failed to load them return false; -#if QT_CONFIG(opensslv11) - RESOLVEFUNC(OPENSSL_init_ssl) RESOLVEFUNC(OPENSSL_init_crypto) RESOLVEFUNC(ASN1_STRING_get0_data) @@ -985,10 +839,12 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(OPENSSL_sk_value) RESOLVEFUNC(DH_get0_pqg) RESOLVEFUNC(SSL_CTX_set_options) + #ifdef TLS1_3_VERSION RESOLVEFUNC(SSL_CTX_set_ciphersuites) RESOLVEFUNC(SSL_set_psk_use_session_callback) #endif // TLS 1.3 or OpenSSL > 1.1.1 + RESOLVEFUNC(SSL_get_client_random) RESOLVEFUNC(SSL_SESSION_get_master_key) RESOLVEFUNC(SSL_session_reused) @@ -1010,6 +866,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(CRYPTO_free) RESOLVEFUNC(OpenSSL_version_num) RESOLVEFUNC(OpenSSL_version) + if (!_q_OpenSSL_version) { // Apparently, we were built with OpenSSL 1.1 enabled but are now using // a wrong library. @@ -1034,6 +891,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(BIO_meth_set_create) RESOLVEFUNC(BIO_meth_set_destroy) #endif // dtls + #if QT_CONFIG(ocsp) RESOLVEFUNC(OCSP_SINGLERESP_get0_id) RESOLVEFUNC(d2i_OCSP_RESPONSE) @@ -1058,99 +916,12 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(OCSP_cert_to_id) RESOLVEFUNC(OCSP_id_cmp) #endif // ocsp + RESOLVEFUNC(BIO_set_data) RESOLVEFUNC(BIO_get_data) RESOLVEFUNC(BIO_set_init) RESOLVEFUNC(BIO_get_shutdown) RESOLVEFUNC(BIO_set_shutdown) -#else // !opensslv11 - - RESOLVEFUNC(ASN1_STRING_data) - -#ifdef SSLEAY_MACROS - RESOLVEFUNC(ASN1_dup) -#endif // SSLEAY_MACROS - RESOLVEFUNC(BIO_new_file) - RESOLVEFUNC(ERR_clear_error) - RESOLVEFUNC(CRYPTO_free) - RESOLVEFUNC(CRYPTO_num_locks) - RESOLVEFUNC(CRYPTO_set_id_callback) - RESOLVEFUNC(CRYPTO_set_locking_callback) - RESOLVEFUNC(CRYPTO_set_ex_data) - RESOLVEFUNC(CRYPTO_get_ex_data) - RESOLVEFUNC(ERR_peek_last_error) - RESOLVEFUNC(ERR_free_strings) - RESOLVEFUNC(EVP_CIPHER_CTX_cleanup) - RESOLVEFUNC(EVP_CIPHER_CTX_init) - -#ifdef SSLEAY_MACROS // ### verify - RESOLVEFUNC(PEM_ASN1_read_bio) -#endif // SSLEAY_MACROS - - RESOLVEFUNC(sk_new_null) - RESOLVEFUNC(sk_push) - RESOLVEFUNC(sk_free) - RESOLVEFUNC(sk_num) - RESOLVEFUNC(sk_pop_free) - RESOLVEFUNC(sk_value) - RESOLVEFUNC(SSL_library_init) - RESOLVEFUNC(SSL_load_error_strings) -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - RESOLVEFUNC(SSL_get_ex_new_index) -#endif - RESOLVEFUNC(SSLv23_client_method) - RESOLVEFUNC(TLSv1_client_method) -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - RESOLVEFUNC(TLSv1_1_client_method) - RESOLVEFUNC(TLSv1_2_client_method) -#endif - RESOLVEFUNC(SSLv23_server_method) - RESOLVEFUNC(TLSv1_server_method) -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - RESOLVEFUNC(TLSv1_1_server_method) - RESOLVEFUNC(TLSv1_2_server_method) -#endif - RESOLVEFUNC(X509_STORE_CTX_get_chain) -#ifdef SSLEAY_MACROS - RESOLVEFUNC(i2d_DSAPrivateKey) - RESOLVEFUNC(i2d_RSAPrivateKey) - RESOLVEFUNC(d2i_DSAPrivateKey) - RESOLVEFUNC(d2i_RSAPrivateKey) -#endif - -#if QT_CONFIG(dtls) - RESOLVEFUNC(DTLSv1_server_method) - RESOLVEFUNC(DTLSv1_client_method) - RESOLVEFUNC(DTLSv1_2_server_method) - RESOLVEFUNC(DTLSv1_2_client_method) -#endif // dtls - - RESOLVEFUNC(CONF_get1_default_config_file) - RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf) - RESOLVEFUNC(OPENSSL_add_all_algorithms_conf) - RESOLVEFUNC(SSLeay) - - if (!_q_SSLeay || q_SSLeay() >= 0x10100000L) { - // OpenSSL 1.1 has deprecated and removed SSLeay. We consider a failure to - // resolve this symbol as a failure to resolve symbols. - // The right operand of '||' above is ... a bit of paranoia. - qCWarning(lcSsl, "Incompatible version of OpenSSL"); - return false; - } - - - RESOLVEFUNC(SSLeay_version) - -#ifndef OPENSSL_NO_EC -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (q_SSLeay() >= 0x10002000L) - RESOLVEFUNC(EC_curve_nist2nid) -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L -#endif // OPENSSL_NO_EC - - -#endif // !opensslv11 - RESOLVEFUNC(ASN1_INTEGER_get) RESOLVEFUNC(ASN1_INTEGER_cmp) RESOLVEFUNC(ASN1_STRING_length) @@ -1172,9 +943,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(EC_GROUP_get_degree) #endif RESOLVEFUNC(BN_num_bits) -#if QT_CONFIG(opensslv11) RESOLVEFUNC(BN_is_word) -#endif RESOLVEFUNC(BN_mod_word) RESOLVEFUNC(DSA_new) RESOLVEFUNC(DSA_free) @@ -1207,17 +976,21 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(EVP_PKEY_set1_RSA) RESOLVEFUNC(EVP_PKEY_set1_DSA) RESOLVEFUNC(EVP_PKEY_set1_DH) + #ifndef OPENSSL_NO_EC RESOLVEFUNC(EVP_PKEY_set1_EC_KEY) -#endif + RESOLVEFUNC(EVP_PKEY_get1_EC_KEY) + RESOLVEFUNC(PEM_read_bio_ECPrivateKey) + RESOLVEFUNC(PEM_write_bio_ECPrivateKey) + RESOLVEFUNC(PEM_read_bio_EC_PUBKEY) + RESOLVEFUNC(PEM_write_bio_EC_PUBKEY) +#endif // OPENSSL_NO_EC + RESOLVEFUNC(EVP_PKEY_cmp) RESOLVEFUNC(EVP_PKEY_free) RESOLVEFUNC(EVP_PKEY_get1_DSA) RESOLVEFUNC(EVP_PKEY_get1_RSA) RESOLVEFUNC(EVP_PKEY_get1_DH) -#ifndef OPENSSL_NO_EC - RESOLVEFUNC(EVP_PKEY_get1_EC_KEY) -#endif RESOLVEFUNC(EVP_PKEY_new) RESOLVEFUNC(EVP_PKEY_type) RESOLVEFUNC(OBJ_nid2sn) @@ -1227,35 +1000,19 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(i2t_ASN1_OBJECT) RESOLVEFUNC(OBJ_obj2txt) RESOLVEFUNC(OBJ_obj2nid) - -#ifndef SSLEAY_MACROS RESOLVEFUNC(PEM_read_bio_PrivateKey) RESOLVEFUNC(PEM_read_bio_DSAPrivateKey) RESOLVEFUNC(PEM_read_bio_RSAPrivateKey) -#ifndef OPENSSL_NO_EC - RESOLVEFUNC(PEM_read_bio_ECPrivateKey) -#endif RESOLVEFUNC(PEM_read_bio_DHparams) RESOLVEFUNC(PEM_write_bio_DSAPrivateKey) RESOLVEFUNC(PEM_write_bio_RSAPrivateKey) RESOLVEFUNC(PEM_write_bio_PrivateKey) -#ifndef OPENSSL_NO_EC - RESOLVEFUNC(PEM_write_bio_ECPrivateKey) -#endif -#endif // !SSLEAY_MACROS - RESOLVEFUNC(PEM_read_bio_PUBKEY) RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY) RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY) -#ifndef OPENSSL_NO_EC - RESOLVEFUNC(PEM_read_bio_EC_PUBKEY) -#endif RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY) RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY) RESOLVEFUNC(PEM_write_bio_PUBKEY) -#ifndef OPENSSL_NO_EC - RESOLVEFUNC(PEM_write_bio_EC_PUBKEY) -#endif RESOLVEFUNC(RAND_seed) RESOLVEFUNC(RAND_status) RESOLVEFUNC(RAND_bytes) @@ -1279,14 +1036,12 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey) RESOLVEFUNC(SSL_CTX_use_PrivateKey_file) RESOLVEFUNC(SSL_CTX_get_cert_store); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L RESOLVEFUNC(SSL_CONF_CTX_new); RESOLVEFUNC(SSL_CONF_CTX_free); RESOLVEFUNC(SSL_CONF_CTX_set_ssl_ctx); RESOLVEFUNC(SSL_CONF_CTX_set_flags); RESOLVEFUNC(SSL_CONF_CTX_finish); RESOLVEFUNC(SSL_CONF_cmd); -#endif RESOLVEFUNC(SSL_accept) RESOLVEFUNC(SSL_clear) RESOLVEFUNC(SSL_connect) @@ -1311,16 +1066,16 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(SSL_SESSION_free) RESOLVEFUNC(SSL_get1_session) RESOLVEFUNC(SSL_get_session) -#if OPENSSL_VERSION_NUMBER >= 0x10001000L RESOLVEFUNC(SSL_set_ex_data) RESOLVEFUNC(SSL_get_ex_data) RESOLVEFUNC(SSL_get_ex_data_X509_STORE_CTX_idx) -#endif -#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) + +#ifndef OPENSSL_NO_PSK RESOLVEFUNC(SSL_set_psk_client_callback) RESOLVEFUNC(SSL_set_psk_server_callback) RESOLVEFUNC(SSL_CTX_use_psk_identity_hint) -#endif +#endif // !OPENSSL_NO_PSK + RESOLVEFUNC(SSL_write) RESOLVEFUNC(X509_NAME_entry_count) RESOLVEFUNC(X509_NAME_get_entry) @@ -1340,10 +1095,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(X509_STORE_CTX_get0_store) RESOLVEFUNC(X509_cmp) RESOLVEFUNC(X509_STORE_CTX_get_ex_data) - -#ifndef SSLEAY_MACROS RESOLVEFUNC(X509_dup) -#endif RESOLVEFUNC(X509_print) RESOLVEFUNC(X509_digest) RESOLVEFUNC(X509_EXTENSION_get_object) @@ -1371,22 +1123,23 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(SSL_CTX_load_verify_locations) RESOLVEFUNC(i2d_SSL_SESSION) RESOLVEFUNC(d2i_SSL_SESSION) -#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG) + +#ifndef OPENSSL_NO_NEXTPROTONEG RESOLVEFUNC(SSL_select_next_proto) RESOLVEFUNC(SSL_CTX_set_next_proto_select_cb) RESOLVEFUNC(SSL_get0_next_proto_negotiated) -#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... -#if OPENSSL_VERSION_NUMBER >= 0x10002000L RESOLVEFUNC(SSL_set_alpn_protos) RESOLVEFUNC(SSL_CTX_set_alpn_select_cb) RESOLVEFUNC(SSL_get0_alpn_selected) -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... +#endif // !OPENSSL_NO_NEXTPROTONEG + #if QT_CONFIG(dtls) RESOLVEFUNC(SSL_CTX_set_cookie_generate_cb) RESOLVEFUNC(SSL_CTX_set_cookie_verify_cb) RESOLVEFUNC(DTLS_server_method) RESOLVEFUNC(DTLS_client_method) #endif // dtls + RESOLVEFUNC(CRYPTO_malloc) RESOLVEFUNC(DH_new) RESOLVEFUNC(DH_free) @@ -1394,12 +1147,14 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(i2d_DHparams) RESOLVEFUNC(DH_check) RESOLVEFUNC(BN_bin2bn) + #ifndef OPENSSL_NO_EC RESOLVEFUNC(EC_KEY_dup) RESOLVEFUNC(EC_KEY_new_by_curve_name) RESOLVEFUNC(EC_KEY_free) RESOLVEFUNC(EC_get_builtin_curves) #endif // OPENSSL_NO_EC + RESOLVEFUNC(PKCS12_parse) RESOLVEFUNC(d2i_PKCS12_bio) RESOLVEFUNC(PKCS12_free) diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index 69b2b90fbd..baf1a43113 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -220,11 +220,129 @@ QT_BEGIN_NAMESPACE #endif // !defined QT_LINKED_OPENSSL -#if QT_CONFIG(opensslv11) -#include "qsslsocket_openssl11_symbols_p.h" -#else -#include "qsslsocket_opensslpre11_symbols_p.h" -#endif // QT_CONFIG +// TODO: the following lines previously were a part of 1.1 - specific header. +// To reduce the amount of the change, I'm directly copying and pasting the +// content of the header here. Later, can be better sorted/split into groups, +// depending on the functionality. +//#include "qsslsocket_openssl11_symbols_p.h" + +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(); + +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_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_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); +size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen); +size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen); +int q_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +const SSL_METHOD *q_TLS_method(); +const SSL_METHOD *q_TLS_client_method(); +const SSL_METHOD *q_TLS_server_method(); +ASN1_TIME *q_X509_getm_notBefore(X509 *a); +ASN1_TIME *q_X509_getm_notAfter(X509 *a); + +Q_AUTOTEST_EXPORT 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); +int q_X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data); +void *q_X509_STORE_get_ex_data(X509_STORE *r, int idx); +STACK_OF(X509) *q_X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx); +void q_DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); +int q_DH_bits(DH *dh); + +# define q_SSL_load_error_strings() q_OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \ + | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL) + +#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_OPENSSL_sk_num)(st) +#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_OPENSSL_sk_value)(st, i) + +#define q_OPENSSL_add_all_algorithms_conf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ + | OPENSSL_INIT_ADD_ALL_DIGESTS \ + | OPENSSL_INIT_LOAD_CONFIG, NULL) +#define q_OPENSSL_add_all_algorithms_noconf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ + | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL) + +int q_OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); +void q_CRYPTO_free(void *str, const char *file, int line); + +long q_OpenSSL_version_num(); +const char *q_OpenSSL_version(int type); + +unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session); +unsigned long q_SSL_set_options(SSL *s, unsigned long op); + +#ifdef TLS1_3_VERSION +int q_SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str); +#endif + +#if QT_CONFIG(dtls) +// Functions and types required for DTLS support: +extern "C" +{ + +typedef int (*CookieVerifyCallback)(SSL *, const unsigned char *, unsigned); +typedef int (*DgramWriteCallback) (BIO *, const char *, int); +typedef int (*DgramReadCallback) (BIO *, char *, int); +typedef int (*DgramPutsCallback) (BIO *, const char *); +typedef long (*DgramCtrlCallback) (BIO *, int, long, void *); +typedef int (*DgramCreateCallback) (BIO *); +typedef int (*DgramDestroyCallback) (BIO *); + +} + +int q_DTLSv1_listen(SSL *s, BIO_ADDR *client); +BIO_ADDR *q_BIO_ADDR_new(); +void q_BIO_ADDR_free(BIO_ADDR *ap); + +// API we need for a custom dgram BIO: + +BIO_METHOD *q_BIO_meth_new(int type, const char *name); +void q_BIO_meth_free(BIO_METHOD *biom); +int q_BIO_meth_set_write(BIO_METHOD *biom, DgramWriteCallback); +int q_BIO_meth_set_read(BIO_METHOD *biom, DgramReadCallback); +int q_BIO_meth_set_puts(BIO_METHOD *biom, DgramPutsCallback); +int q_BIO_meth_set_ctrl(BIO_METHOD *biom, DgramCtrlCallback); +int q_BIO_meth_set_create(BIO_METHOD *biom, DgramCreateCallback); +int q_BIO_meth_set_destroy(BIO_METHOD *biom, DgramDestroyCallback); + +#endif // dtls + +void q_BIO_set_data(BIO *a, void *ptr); +void *q_BIO_get_data(BIO *a); +void q_BIO_set_init(BIO *a, int init); +int q_BIO_get_shutdown(BIO *a); +void q_BIO_set_shutdown(BIO *a, int shut); + +#if QT_CONFIG(ocsp) +const OCSP_CERTID *q_OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *x); +#endif // ocsp + +#define q_SSL_CTX_set_min_proto_version(ctx, version) \ + q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, nullptr) + +#define q_SSL_CTX_set_max_proto_version(ctx, version) \ + q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, nullptr) + +extern "C" { +typedef int (*q_SSL_psk_use_session_cb_func_t)(SSL *, const EVP_MD *, const unsigned char **, size_t *, + SSL_SESSION **); +} +void q_SSL_set_psk_use_session_callback(SSL *s, q_SSL_psk_use_session_cb_func_t); +// Here the content of the 1.1 header ends. bool q_resolveOpenSslSymbols(); long q_ASN1_INTEGER_get(ASN1_INTEGER *a); @@ -237,27 +355,14 @@ 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_BN_num_bits(const BIGNUM *a); - -#if QT_CONFIG(opensslv11) int q_BN_is_word(BIGNUM *a, BN_ULONG w); -#else // opensslv11 -// BN_is_word is implemented purely as a -// macro in OpenSSL < 1.1. It doesn't -// call any functions. -// -// The implementation of BN_is_word is -// 100% the same between 1.0.0, 1.0.1 -// and 1.0.2. -// -// Users are required to include <openssl/bn.h>. -#define q_BN_is_word BN_is_word -#endif // !opensslv11 - BN_ULONG q_BN_mod_word(const BIGNUM *a, BN_ULONG w); + #ifndef OPENSSL_NO_EC const EC_GROUP* q_EC_KEY_get0_group(const EC_KEY* k); int q_EC_GROUP_get_degree(const EC_GROUP* g); -#endif +#endif // OPENSSL_NO_EC + DSA *q_DSA_new(); void q_DSA_free(DSA *a); X509 *q_d2i_X509(X509 **a, const unsigned char **b, long c); @@ -277,23 +382,28 @@ const EVP_MD *q_EVP_get_digestbyname(const char *name); #ifndef OPENSSL_NO_DES const EVP_CIPHER *q_EVP_des_cbc(); const EVP_CIPHER *q_EVP_des_ede3_cbc(); -#endif +#endif // OPENSSL_NO_DES + #ifndef OPENSSL_NO_RC2 const EVP_CIPHER *q_EVP_rc2_cbc(); -#endif +#endif // OPENSSL_NO_RC2 + #ifndef OPENSSL_NO_AES const EVP_CIPHER *q_EVP_aes_128_cbc(); const EVP_CIPHER *q_EVP_aes_192_cbc(); const EVP_CIPHER *q_EVP_aes_256_cbc(); -#endif +#endif // OPENSSL_NO_AES + Q_AUTOTEST_EXPORT const EVP_MD *q_EVP_sha1(); int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c); 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); + #ifndef OPENSSL_NO_EC Q_AUTOTEST_EXPORT 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); RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a); @@ -313,18 +423,18 @@ 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)) -#ifdef SSLEAY_MACROS -// ### verify -void *q_PEM_ASN1_read_bio(d2i_of_void *a, const char *b, BIO *c, void **d, pem_password_cb *e, - void *f); -// ### ditto for write -#else Q_AUTOTEST_EXPORT EVP_PKEY *q_PEM_read_bio_PrivateKey(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d); DSA *q_PEM_read_bio_DSAPrivateKey(BIO *a, DSA **b, pem_password_cb *c, void *d); RSA *q_PEM_read_bio_RSAPrivateKey(BIO *a, RSA **b, pem_password_cb *c, void *d); + #ifndef OPENSSL_NO_EC EC_KEY *q_PEM_read_bio_ECPrivateKey(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); -#endif +int q_PEM_write_bio_ECPrivateKey(BIO *a, EC_KEY *b, const EVP_CIPHER *c, unsigned char *d, + int e, pem_password_cb *f, void *g); +EC_KEY *q_PEM_read_bio_EC_PUBKEY(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); +int q_PEM_write_bio_EC_PUBKEY(BIO *a, EC_KEY *b); +#endif // OPENSSL_NO_EC + DH *q_PEM_read_bio_DHparams(BIO *a, DH **b, pem_password_cb *c, void *d); int q_PEM_write_bio_DSAPrivateKey(BIO *a, DSA *b, const EVP_CIPHER *c, unsigned char *d, int e, pem_password_cb *f, void *g); @@ -332,23 +442,13 @@ 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); -#ifndef OPENSSL_NO_EC -int q_PEM_write_bio_ECPrivateKey(BIO *a, EC_KEY *b, const EVP_CIPHER *c, unsigned char *d, - int e, pem_password_cb *f, void *g); -#endif -#endif // SSLEAY_MACROS Q_AUTOTEST_EXPORT 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); -#ifndef OPENSSL_NO_EC -EC_KEY *q_PEM_read_bio_EC_PUBKEY(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); -#endif int q_PEM_write_bio_DSA_PUBKEY(BIO *a, DSA *b); int q_PEM_write_bio_RSA_PUBKEY(BIO *a, RSA *b); int q_PEM_write_bio_PUBKEY(BIO *a, EVP_PKEY *b); -#ifndef OPENSSL_NO_EC -int q_PEM_write_bio_EC_PUBKEY(BIO *a, EC_KEY *b); -#endif + void q_RAND_seed(const void *a, int b); int q_RAND_status(); int q_RAND_bytes(unsigned char *b, int n); @@ -378,14 +478,12 @@ int q_SSL_CTX_use_PrivateKey(SSL_CTX *a, EVP_PKEY *b); int q_SSL_CTX_use_RSAPrivateKey(SSL_CTX *a, RSA *b); int q_SSL_CTX_use_PrivateKey_file(SSL_CTX *a, const char *b, int c); X509_STORE *q_SSL_CTX_get_cert_store(const SSL_CTX *a); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L SSL_CONF_CTX *q_SSL_CONF_CTX_new(); void q_SSL_CONF_CTX_free(SSL_CONF_CTX *a); void q_SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *a, SSL_CTX *b); unsigned int q_SSL_CONF_CTX_set_flags(SSL_CONF_CTX *a, unsigned int b); int q_SSL_CONF_CTX_finish(SSL_CONF_CTX *a); int q_SSL_CONF_cmd(SSL_CONF_CTX *a, const char *b, const char *c); -#endif void q_SSL_free(SSL *a); STACK_OF(SSL_CIPHER) *q_SSL_get_ciphers(const SSL *a); const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a); @@ -407,26 +505,18 @@ int q_SSL_set_session(SSL *to, SSL_SESSION *session); void q_SSL_SESSION_free(SSL_SESSION *ses); SSL_SESSION *q_SSL_get1_session(SSL *ssl); SSL_SESSION *q_SSL_get_session(const SSL *ssl); -#if OPENSSL_VERSION_NUMBER >= 0x10001000L int q_SSL_set_ex_data(SSL *ssl, int idx, void *arg); void *q_SSL_get_ex_data(const SSL *ssl, int idx); -#endif -#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) +#ifndef OPENSSL_NO_PSK typedef unsigned int (*q_psk_client_callback_t)(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len); void q_SSL_set_psk_client_callback(SSL *ssl, q_psk_client_callback_t callback); typedef unsigned int (*q_psk_server_callback_t)(SSL *ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len); void q_SSL_set_psk_server_callback(SSL *ssl, q_psk_server_callback_t callback); int q_SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *hint); -#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) +#endif // !OPENSSL_NO_PSK int q_SSL_write(SSL *a, const void *b, int c); int q_X509_cmp(X509 *a, X509 *b); -#ifdef SSLEAY_MACROS -void *q_ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x); -#define q_X509_dup(x509) (X509 *)q_ASN1_dup((i2d_of_void *)q_i2d_X509, \ - (d2i_of_void *)q_d2i_X509,(char *)x509) -#else X509 *q_X509_dup(X509 *a); -#endif 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); @@ -485,13 +575,10 @@ void q_EC_KEY_free(EC_KEY *ecdh); // EC curves management size_t q_EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L int q_EC_curve_nist2nid(const char *name); -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L #endif // OPENSSL_NO_EC -#if OPENSSL_VERSION_NUMBER >= 0x10002000L + #define q_SSL_get_server_tmp_key(ssl, key) q_SSL_ctrl((ssl), SSL_CTRL_GET_SERVER_TMP_KEY, 0, (char *)key) -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L // PKCS#12 support int q_PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca); @@ -521,7 +608,7 @@ int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char int q_i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp); SSL_SESSION *q_d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length); -#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifndef OPENSSL_NO_NEXTPROTONEG int q_SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, const unsigned char *client, unsigned int client_len); @@ -533,7 +620,6 @@ void q_SSL_CTX_set_next_proto_select_cb(SSL_CTX *s, void *arg); void q_SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, unsigned *len); -#if OPENSSL_VERSION_NUMBER >= 0x10002000L int q_SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, unsigned protos_len); void q_SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, @@ -545,8 +631,8 @@ void q_SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, void *arg), void *arg); void q_SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, unsigned *len); -#endif -#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... +#endif // !OPENSSL_NO_NEXTPROTONEG + #if QT_CONFIG(dtls) @@ -586,13 +672,9 @@ int q_BIO_set_ex_data(BIO *b, int idx, void *data); class QDateTime; QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime); -#ifndef OPENSSL_NO_TLSEXT - #define q_SSL_set_tlsext_status_type(ssl, type) \ q_SSL_ctrl((ssl), SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE, (type), nullptr) -#endif // OPENSSL_NO_TLSEXT - #if QT_CONFIG(ocsp) OCSP_RESPONSE *q_d2i_OCSP_RESPONSE(OCSP_RESPONSE **a, const unsigned char **in, long len); diff --git a/src/network/ssl/qsslsocket_opensslpre11.cpp b/src/network/ssl/qsslsocket_opensslpre11.cpp deleted file mode 100644 index 2af437f0fa..0000000000 --- a/src/network/ssl/qsslsocket_opensslpre11.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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. -** -****************************************************************************/ - -//#define QT_DECRYPT_SSL_TRAFFIC - -#include "qssl_p.h" -#include "qsslsocket_openssl_p.h" -#include "qsslsocket_openssl_symbols_p.h" -#include "qsslsocket.h" -#include "qsslkey.h" - -#include <QtCore/qdebug.h> -#include <QtCore/qdir.h> -#include <QtCore/qdiriterator.h> -#include <QtCore/qthread.h> -#include <QtCore/qfile.h> -#include <QtCore/qmutex.h> - -QT_BEGIN_NAMESPACE - -/* \internal - - From OpenSSL's thread(3) manual page: - - OpenSSL can safely be used in multi-threaded applications provided that at - least two callback functions are set. - - locking_function(int mode, int n, const char *file, int line) is needed to - perform locking on shared data structures. (Note that OpenSSL uses a - number of global data structures that will be implicitly shared - whenever multiple threads use OpenSSL.) Multi-threaded - applications will crash at random if it is not set. ... - ... - id_function(void) is a function that returns a thread ID. It is not - needed on Windows nor on platforms where getpid() returns a different - ID for each thread (most notably Linux) -*/ - -class QOpenSslLocks -{ -public: - QOpenSslLocks() - : initLocker(QMutex::Recursive), - locksLocker(QMutex::Recursive) - { - QMutexLocker locker(&locksLocker); - int numLocks = q_CRYPTO_num_locks(); - locks = new QMutex *[numLocks]; - memset(locks, 0, numLocks * sizeof(QMutex *)); - } - ~QOpenSslLocks() - { - QMutexLocker locker(&locksLocker); - for (int i = 0; i < q_CRYPTO_num_locks(); ++i) - delete locks[i]; - delete [] locks; - - QSslSocketPrivate::deinitialize(); - } - QMutex *lock(int num) - { - QMutexLocker locker(&locksLocker); - QMutex *tmp = locks[num]; - if (!tmp) - tmp = locks[num] = new QMutex(QMutex::Recursive); - return tmp; - } - - QMutex *globalLock() - { - return &locksLocker; - } - - QMutex *initLock() - { - return &initLocker; - } - -private: - QMutex initLocker; - QMutex locksLocker; - QMutex **locks; -}; - -Q_GLOBAL_STATIC(QOpenSslLocks, openssl_locks) - -extern "C" { -static void locking_function(int mode, int lockNumber, const char *, int) -{ - QMutex *mutex = openssl_locks()->lock(lockNumber); - - // Lock or unlock it - if (mode & CRYPTO_LOCK) - mutex->lock(); - else - mutex->unlock(); -} -static unsigned long id_function() -{ - return (quintptr)QThread::currentThreadId(); -} - -} // extern "C" - -static void q_OpenSSL_add_all_algorithms_safe() -{ -#ifdef Q_OS_WIN - // Prior to version 1.0.1m an attempt to call OpenSSL_add_all_algorithms on - // Windows could result in 'exit' call from OPENSSL_config (QTBUG-43843). - // We can predict this and avoid OPENSSL_add_all_algorithms call. - // From OpenSSL docs: - // "An application does not need to add algorithms to use them explicitly, - // for example by EVP_sha1(). It just needs to add them if it (or any of - // the functions it calls) needs to lookup algorithms. - // The cipher and digest lookup functions are used in many parts of the - // library. If the table is not initialized several functions will - // misbehave and complain they cannot find algorithms. This includes the - // PEM, PKCS#12, SSL and S/MIME libraries. This is a common query in - // the OpenSSL mailing lists." - // - // Anyway, as a result, we chose not to call this function if it would exit. - - if (q_SSLeay() < 0x100010DFL) - { - // Now, before we try to call it, check if an attempt to open config file - // will result in exit: - if (char *confFileName = q_CONF_get1_default_config_file()) { - BIO *confFile = q_BIO_new_file(confFileName, "r"); - const auto lastError = q_ERR_peek_last_error(); - q_CRYPTO_free(confFileName); - if (confFile) { - q_BIO_free(confFile); - } else { - q_ERR_clear_error(); - if (ERR_GET_REASON(lastError) == ERR_R_SYS_LIB) { - qCWarning(lcSsl, "failed to open openssl.conf file"); - return; - } - } - } - } -#endif // Q_OS_WIN - - q_OpenSSL_add_all_algorithms(); -} - - -void QSslSocketPrivate::deinitialize() -{ - q_CRYPTO_set_id_callback(0); - q_CRYPTO_set_locking_callback(0); - q_ERR_free_strings(); -} - - -bool QSslSocketPrivate::ensureLibraryLoaded() -{ - if (!q_resolveOpenSslSymbols()) - return false; - - // Check if the library itself needs to be initialized. - QMutexLocker locker(openssl_locks()->initLock()); - - if (!s_libraryLoaded) { - // Initialize OpenSSL. - q_CRYPTO_set_id_callback(id_function); - q_CRYPTO_set_locking_callback(locking_function); - if (q_SSL_library_init() != 1) - return false; - q_SSL_load_error_strings(); - q_OpenSSL_add_all_algorithms_safe(); - -#if OPENSSL_VERSION_NUMBER >= 0x10001000L - if (q_SSLeay() >= 0x10001000L) - QSslSocketBackendPrivate::s_indexForSSLExtraData = q_SSL_get_ex_new_index(0L, NULL, NULL, NULL, NULL); -#endif - - // Initialize OpenSSL's random seed. - if (!q_RAND_status()) { - qWarning("Random number generator not seeded, disabling SSL support"); - return false; - } - - s_libraryLoaded = true; - } - return true; -} - -void QSslSocketPrivate::ensureCiphersAndCertsLoaded() -{ - QMutexLocker locker(openssl_locks()->initLock()); - if (s_loadedCiphersAndCerts) - return; - s_loadedCiphersAndCerts = true; - - resetDefaultCiphers(); - resetDefaultEllipticCurves(); - -#if QT_CONFIG(library) - //load symbols needed to receive certificates from system store -#if defined(Q_OS_QNX) - s_loadRootCertsOnDemand = true; -#elif defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) - // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there) - QList<QByteArray> dirs = unixRootCertDirectories(); - QStringList symLinkFilter; - symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]"); - for (int a = 0; a < dirs.count(); ++a) { - QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files); - if (iterator.hasNext()) { - s_loadRootCertsOnDemand = true; - break; - } - } -#endif -#endif // QT_CONFIG(library) - // if on-demand loading was not enabled, load the certs now - if (!s_loadRootCertsOnDemand) - setDefaultCaCertificates(systemCaCertificates()); -#ifdef Q_OS_WIN - //Enabled for fetching additional root certs from windows update on windows 6+ - //This flag is set false by setDefaultCaCertificates() indicating the app uses - //its own cert bundle rather than the system one. - //Same logic that disables the unix on demand cert loading. - //Unlike unix, we do preload the certificates from the cert store. - s_loadRootCertsOnDemand = true; -#endif -} - -long QSslSocketPrivate::sslLibraryVersionNumber() -{ - if (!supportsSsl()) - return 0; - - return q_SSLeay(); -} - -QString QSslSocketPrivate::sslLibraryVersionString() -{ - if (!supportsSsl()) - return QString(); - - const char *versionString = q_SSLeay_version(SSLEAY_VERSION); - if (!versionString) - return QString(); - - return QString::fromLatin1(versionString); -} - -void QSslSocketBackendPrivate::continueHandshake() -{ - Q_Q(QSslSocket); - // if we have a max read buffer size, reset the plain socket's to match - if (readBufferMaxSize) - plainSocket->setReadBufferSize(readBufferMaxSize); - - if (q_SSL_ctrl((ssl), SSL_CTRL_GET_SESSION_REUSED, 0, NULL)) - configuration.peerSessionShared = true; - -#ifdef QT_DECRYPT_SSL_TRAFFIC - if (ssl->session && ssl->s3) { - const char *mk = reinterpret_cast<const char *>(ssl->session->master_key); - QByteArray masterKey(mk, ssl->session->master_key_length); - const char *random = reinterpret_cast<const char *>(ssl->s3->client_random); - QByteArray clientRandom(random, SSL3_RANDOM_SIZE); - - // different format, needed for e.g. older Wireshark versions: -// const char *sid = reinterpret_cast<const char *>(ssl->session->session_id); -// QByteArray sessionID(sid, ssl->session->session_id_length); -// QByteArray debugLineRSA("RSA Session-ID:"); -// debugLineRSA.append(sessionID.toHex().toUpper()); -// debugLineRSA.append(" Master-Key:"); -// debugLineRSA.append(masterKey.toHex().toUpper()); -// debugLineRSA.append("\n"); - - QByteArray debugLineClientRandom("CLIENT_RANDOM "); - debugLineClientRandom.append(clientRandom.toHex().toUpper()); - debugLineClientRandom.append(" "); - debugLineClientRandom.append(masterKey.toHex().toUpper()); - debugLineClientRandom.append("\n"); - - 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"; - if (!file.write(debugLineClientRandom)) - qCWarning(lcSsl) << "could not write to file" << sslKeyFile; - file.close(); - } else { - qCWarning(lcSsl, "could not decrypt SSL traffic"); - } -#endif - - // Cache this SSL session inside the QSslContext - if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) { - if (!sslContextPointer->cacheSession(ssl)) { - sslContextPointer.clear(); // we could not cache the session - } else { - // Cache the session for permanent usage as well - if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) { - if (!sslContextPointer->sessionASN1().isEmpty()) - configuration.sslSession = sslContextPointer->sessionASN1(); - configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint(); - } - } - } - -#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG) - - configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status; - if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) { - // we could not agree -> be conservative and use HTTP/1.1 - configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1"); - } else { - const unsigned char *proto = 0; - unsigned int proto_len = 0; -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (q_SSLeay() >= 0x10002000L) { - q_SSL_get0_alpn_selected(ssl, &proto, &proto_len); - if (proto_len && mode == QSslSocket::SslClientMode) { - // Client does not have a callback that sets it ... - configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated; - } - } - - if (!proto_len) { // Test if NPN was more lucky ... -#else - { -#endif - q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len); - } - - if (proto_len) - configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len); - else - configuration.nextNegotiatedProtocol.clear(); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... - -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (q_SSLeay() >= 0x10002000L && mode == QSslSocket::SslClientMode) { - EVP_PKEY *key; - if (q_SSL_get_server_tmp_key(ssl, &key)) - configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey); - } -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... - - connectionEncrypted = true; - emit q->encrypted(); - if (autoStartHandshake && pendingClose) { - pendingClose = false; - q->disconnectFromHost(); - } -} - -QT_END_NAMESPACE diff --git a/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h b/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h deleted file mode 100644 index f5626d5d16..0000000000 --- a/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h +++ /dev/null @@ -1,202 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2014 BlackBerry Limited. All rights reserved. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/**************************************************************************** -** -** 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. -** -****************************************************************************/ - - -#ifndef QSSLSOCKET_OPENSSLPRE11_SYMBOLS_P_H -#define QSSLSOCKET_OPENSSLPRE11_SYMBOLS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -// Note: this file does not have QT_BEGIN_NAMESPACE/QT_END_NAMESPACE, it's done -// in qsslsocket_openssl_symbols_p.h. - -#ifndef QSSLSOCKET_OPENSSL_SYMBOLS_P_H -#error "You are not supposed to use this header file, include qsslsocket_openssl_symbols_p.h instead" -#endif - -unsigned char * q_ASN1_STRING_data(ASN1_STRING *a); -BIO *q_BIO_new_file(const char *filename, const char *mode); -void q_ERR_clear_error(); -Q_AUTOTEST_EXPORT BIO *q_BIO_new(BIO_METHOD *a); -Q_AUTOTEST_EXPORT BIO_METHOD *q_BIO_s_mem(); -int q_CRYPTO_num_locks(); -void q_CRYPTO_set_locking_callback(void (*a)(int, int, const char *, int)); -void q_CRYPTO_set_id_callback(unsigned long (*a)()); -void q_CRYPTO_free(void *a); -int q_CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val); -void *q_CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx); -unsigned long q_ERR_peek_last_error(); -void q_ERR_free_strings(); -void q_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a); -void q_EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a); - -typedef _STACK STACK; - -// The typedef we use to make our pre 1.1 code look more like 1.1 (less ifdefs). -typedef STACK OPENSSL_STACK; - -// We resolve q_sk_ functions, but use q_OPENSSL_sk_ macros in code to reduce -// the amount of #ifdefs. -int q_sk_num(STACK *a); -#define q_OPENSSL_sk_num(a) q_sk_num(a) -void q_sk_pop_free(STACK *a, void (*b)(void *)); -#define q_OPENSSL_sk_pop_free(a, b) q_sk_pop_free(a, b) -STACK *q_sk_new_null(); -#define q_OPENSSL_sk_new_null() q_sk_new_null() - -void q_sk_free(STACK *a); - -// Just a name alias (not a function call expression) since in code we take an -// address of this: -#define q_OPENSSL_sk_free q_sk_free - -void *q_sk_value(STACK *a, int b); -void q_sk_push(STACK *st, void *data); - -#define q_OPENSSL_sk_value(a, b) q_sk_value(a, b) -#define q_OPENSSL_sk_push(st, data) q_sk_push(st, data) - -SSL_CTX *q_SSL_CTX_new(const SSL_METHOD *a); - -int q_SSL_library_init(); -void q_SSL_load_error_strings(); - -#if OPENSSL_VERSION_NUMBER >= 0x10001000L -int q_SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); -#endif - -const SSL_METHOD *q_SSLv23_client_method(); -const SSL_METHOD *q_TLSv1_client_method(); -const SSL_METHOD *q_TLSv1_1_client_method(); -const SSL_METHOD *q_TLSv1_2_client_method(); -const SSL_METHOD *q_SSLv23_server_method(); -const SSL_METHOD *q_TLSv1_server_method(); -const SSL_METHOD *q_TLSv1_1_server_method(); -const SSL_METHOD *q_TLSv1_2_server_method(); - -STACK_OF(X509) *q_X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx); - -#ifdef SSLEAY_MACROS -int q_i2d_DSAPrivateKey(const DSA *a, unsigned char **pp); -int q_i2d_RSAPrivateKey(const RSA *a, unsigned char **pp); -RSA *q_d2i_RSAPrivateKey(RSA **a, unsigned char **pp, long length); -DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length); -#define q_PEM_read_bio_RSAPrivateKey(bp, x, cb, u) \ - (RSA *)q_PEM_ASN1_read_bio( \ - (void *(*)(void**, const unsigned char**, long int))q_d2i_RSAPrivateKey, PEM_STRING_RSA, bp, (void **)x, cb, u) -#define q_PEM_read_bio_DSAPrivateKey(bp, x, cb, u) \ - (DSA *)q_PEM_ASN1_read_bio( \ - (void *(*)(void**, const unsigned char**, long int))q_d2i_DSAPrivateKey, PEM_STRING_DSA, bp, (void **)x, cb, u) -#define q_PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \ - PEM_ASN1_write_bio((int (*)(void*, unsigned char**))q_i2d_RSAPrivateKey,PEM_STRING_RSA,\ - bp,(char *)x,enc,kstr,klen,cb,u) -#define q_PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \ - PEM_ASN1_write_bio((int (*)(void*, unsigned char**))q_i2d_DSAPrivateKey,PEM_STRING_DSA,\ - bp,(char *)x,enc,kstr,klen,cb,u) -#define q_PEM_read_bio_DHparams(bp, dh, cb, u) \ - (DH *)q_PEM_ASN1_read_bio( \ - (void *(*)(void**, const unsigned char**, long int))q_d2i_DHparams, PEM_STRING_DHPARAMS, bp, (void **)x, cb, u) -#endif // SSLEAY_MACROS - -#define q_SSL_CTX_set_options(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL) -#define q_SSL_set_options(ssl,op) q_SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),nullptr) -#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_sk_num)(st) -#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_sk_value)(st, i) -#define q_X509_getm_notAfter(x) X509_get_notAfter(x) -#define q_X509_getm_notBefore(x) X509_get_notBefore(x) - -// "Forward compatibility" with OpenSSL 1.1 (to save on #if-ery elsewhere): -#define q_X509_get_version(x509) q_ASN1_INTEGER_get((x509)->cert_info->version) -#define q_ASN1_STRING_get0_data(x) q_ASN1_STRING_data(x) -#define q_EVP_PKEY_base_id(pkey) ((pkey)->type) -#define q_X509_get_pubkey(x509) q_X509_PUBKEY_get((x509)->cert_info->key) -#define q_SSL_SESSION_get_ticket_lifetime_hint(s) ((s)->tlsext_tick_lifetime_hint) -#define q_RSA_bits(rsa) q_BN_num_bits((rsa)->n) -#define q_DSA_bits(dsa) q_BN_num_bits((dsa)->p) -#define q_DH_bits(dsa) q_BN_num_bits((dh)->p) -#define q_X509_STORE_set_verify_cb(s,c) X509_STORE_set_verify_cb_func((s),(c)) - -char *q_CONF_get1_default_config_file(); -void q_OPENSSL_add_all_algorithms_noconf(); -void q_OPENSSL_add_all_algorithms_conf(); - -long q_SSLeay(); -const char *q_SSLeay_version(int type); - -#if QT_CONFIG(dtls) -// DTLS: -extern "C" -{ -typedef int (*CookieVerifyCallback)(SSL *, unsigned char *, unsigned); -} - -#define q_DTLSv1_listen(ssl, peer) q_SSL_ctrl(ssl, DTLS_CTRL_LISTEN, 0, (void *)peer) - -const SSL_METHOD *q_DTLSv1_server_method(); -const SSL_METHOD *q_DTLSv1_client_method(); -const SSL_METHOD *q_DTLSv1_2_server_method(); -const SSL_METHOD *q_DTLSv1_2_client_method(); -#endif // dtls - -#endif // QSSLSOCKET_OPENSSL_PRE11_SYMBOLS_P_H diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index daa9be23f4..1abd18bb32 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -127,7 +127,6 @@ public: static long sslLibraryBuildVersionNumber(); static QString sslLibraryBuildVersionString(); static void ensureInitialized(); - static void deinitialize(); static QList<QSslCipher> defaultCiphers(); static QList<QSslCipher> supportedCiphers(); static void setDefaultCiphers(const QList<QSslCipher> &ciphers); diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp index cb0e86fa1f..4286b5ea42 100644 --- a/src/network/ssl/qsslsocket_winrt.cpp +++ b/src/network/ssl/qsslsocket_winrt.cpp @@ -157,11 +157,6 @@ QSslSocketBackendPrivate::~QSslSocketBackendPrivate() g->syncCaCertificates(QSet<QSslCertificate>(), previousCaCertificates); } -void QSslSocketPrivate::deinitialize() -{ - Q_UNIMPLEMENTED(); -} - bool QSslSocketPrivate::supportsSsl() { return true; diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri index 8bb70a2aed..0c8b9ccd40 100644 --- a/src/network/ssl/ssl.pri +++ b/src/network/ssl/ssl.pri @@ -102,17 +102,7 @@ qtConfig(ssl) { qtConfig(ocsp): HEADERS += ssl/qocsp_p.h - qtConfig(opensslv11) { - HEADERS += ssl/qsslsocket_openssl11_symbols_p.h - SOURCES += ssl/qsslsocket_openssl11.cpp \ - ssl/qsslcontext_openssl11.cpp - - QMAKE_CXXFLAGS += -DOPENSSL_API_COMPAT=0x10100000L - } else { - HEADERS += ssl/qsslsocket_opensslpre11_symbols_p.h - SOURCES += ssl/qsslsocket_opensslpre11.cpp \ - ssl/qsslcontext_opensslpre11.cpp - } + QMAKE_CXXFLAGS += -DOPENSSL_API_COMPAT=0x10100000L darwin:SOURCES += ssl/qsslsocket_mac_shared.cpp |