summaryrefslogtreecommitdiffstats
path: root/src/network/ssl/qsslcontext_openssl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/ssl/qsslcontext_openssl.cpp')
-rw-r--r--src/network/ssl/qsslcontext_openssl.cpp550
1 files changed, 476 insertions, 74 deletions
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 &params = 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"));
}
}