require OpenSSL v1.1.0 as minumum

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-06-28 11:30:49 +03:00
parent d2bb27a0c5
commit a5df6c4ad7
8 changed files with 14 additions and 180 deletions

View file

@ -222,8 +222,8 @@ set_package_properties(Jansson PROPERTIES
TYPE REQUIRED TYPE REQUIRED
) )
# v0.9.8+ required for SHA-224...SHA-512 support # v1.1.0+ required for thread-safety without use of locking callbacks
find_package(OpenSSL 0.9.8) find_package(OpenSSL 1.1.0)
set_package_properties(OpenSSL PROPERTIES set_package_properties(OpenSSL PROPERTIES
PURPOSE "Required for HTTPS support" PURPOSE "Required for HTTPS support"
DESCRIPTION "Robust, commercial-grade, and full-featured toolkit for SSL and TLS" DESCRIPTION "Robust, commercial-grade, and full-featured toolkit for SSL and TLS"

View file

@ -82,16 +82,12 @@ QT_BEGIN_NAMESPACE
Describes the protocol of the cipher. Describes the protocol of the cipher.
\value SslV3 SSLv3 \value SslV3 SSLv3
\value SslV2 SSLv2
\value TlsV1 TLSv1 \value TlsV1 TLSv1
\value UnknownProtocol The cipher's protocol cannot be determined. \value UnknownProtocol The cipher's protocol cannot be determined.
\value AnyProtocol The socket understands SSLv2, SSLv3, and TLSv1. This \value AnyProtocol The socket understands SSLv2, SSLv3, and TLSv1. This
value is used by QSslSocket only. value is used by QSslSocket only.
\value TlsV1SslV3 On the client side, this will send
a TLS 1.0 Client Hello, enabling TLSv1 and SSLv3 connections.
On the server side, this will enable both SSLv3 and TLSv1 connections.
\value SecureProtocols The default option, using protocols known to be secure; \value SecureProtocols The default option, using protocols known to be secure;
currently behaves like TlsV1SslV3. currently behaves like AnyProtocol.
Note: most servers using SSL understand both versions (2 and 3), Note: most servers using SSL understand both versions (2 and 3),
but it is recommended to use the latest version only for security but it is recommended to use the latest version only for security

View file

@ -52,10 +52,8 @@ namespace QSsl {
enum SslProtocol { enum SslProtocol {
SslV3, SslV3,
SslV2,
TlsV1, // ### Qt 5: rename to TlsV1_0 or so TlsV1, // ### Qt 5: rename to TlsV1_0 or so
AnyProtocol, AnyProtocol,
TlsV1SslV3,
SecureProtocols, SecureProtocols,
UnknownProtocol = -1 UnknownProtocol = -1
}; };

View file

@ -401,11 +401,7 @@ QMultiMap<QSsl::AlternateNameEntryType, QString> QSslCertificate::alternateSubje
continue; continue;
} }
#if OPENSSL_VERSION_NUMBER < 0x10100000L
const char *altNameStr = reinterpret_cast<const char *>(ASN1_STRING_data(genName->d.ia5));
#else
const char *altNameStr = reinterpret_cast<const char *>(ASN1_STRING_get0_data(genName->d.ia5)); const char *altNameStr = reinterpret_cast<const char *>(ASN1_STRING_get0_data(genName->d.ia5));
#endif
const QString altName = QString::fromLatin1(altNameStr, len); const QString altName = QString::fromLatin1(altNameStr, len);
if (genName->type == GEN_DNS) if (genName->type == GEN_DNS)
result.insert(QSsl::DnsEntry, altName); result.insert(QSsl::DnsEntry, altName);
@ -467,19 +463,11 @@ QSslKey QSslCertificate::publicKey() const
QSslKey key; QSslKey key;
key.d->type = QSsl::PublicKey; key.d->type = QSsl::PublicKey;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
X509_PUBKEY *xkey = d->x509->cert_info->key;
#else
X509_PUBKEY *xkey = X509_get_X509_PUBKEY(d->x509); X509_PUBKEY *xkey = X509_get_X509_PUBKEY(d->x509);
#endif
EVP_PKEY *pkey = X509_PUBKEY_get(xkey); EVP_PKEY *pkey = X509_PUBKEY_get(xkey);
Q_ASSERT(pkey); Q_ASSERT(pkey);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
const int key_id = EVP_PKEY_type(pkey->type);
#else
const int key_id = EVP_PKEY_base_id(pkey); const int key_id = EVP_PKEY_base_id(pkey);
#endif
if (key_id == EVP_PKEY_RSA) { if (key_id == EVP_PKEY_RSA) {
key.d->rsa = EVP_PKEY_get1_RSA(pkey); key.d->rsa = EVP_PKEY_get1_RSA(pkey);
key.d->algorithm = QSsl::Rsa; key.d->algorithm = QSsl::Rsa;

View file

@ -286,10 +286,6 @@ int QSslKey::length() const
{ {
if (d->isNull) if (d->isNull)
return -1; return -1;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
return (d->algorithm == QSsl::Rsa)
? BN_num_bits(d->rsa->n) : BN_num_bits(d->dsa->p);
#else
if (d->algorithm == QSsl::Rsa) { if (d->algorithm == QSsl::Rsa) {
return RSA_bits(d->rsa); return RSA_bits(d->rsa);
}else{ }else{
@ -297,7 +293,6 @@ int QSslKey::length() const
DSA_get0_pqg(d->dsa, &p, NULL, NULL); DSA_get0_pqg(d->dsa, &p, NULL, NULL);
return BN_num_bits(p); return BN_num_bits(p);
} }
#endif
} }

View file

@ -45,90 +45,6 @@ bool QSslSocketPrivate::s_libraryLoaded = false;
bool QSslSocketPrivate::s_loadedCiphersAndCerts = false; bool QSslSocketPrivate::s_loadedCiphersAndCerts = false;
bool QSslSocketPrivate::s_loadRootCertsOnDemand = false; bool QSslSocketPrivate::s_loadRootCertsOnDemand = false;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
/* \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
when-whenever ever 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:
inline QOpenSslLocks()
: initLocker(QMutex::Recursive),
locksLocker(QMutex::Recursive)
{
QMutexLocker locker(&locksLocker);
int numLocks = CRYPTO_num_locks();
locks = new QMutex *[numLocks];
memset(locks, 0, numLocks * sizeof(QMutex *));
}
inline ~QOpenSslLocks()
{
QMutexLocker locker(&locksLocker);
for (int i = 0; i < CRYPTO_num_locks(); ++i)
delete locks[i];
delete [] locks;
QSslSocketPrivate::deinitialize();
}
inline 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"
#endif //OPENSSL_VERSION_NUMBER >= 0x10100000L
QSslSocketBackendPrivate::QSslSocketBackendPrivate() QSslSocketBackendPrivate::QSslSocketBackendPrivate()
: ssl(0), : ssl(0),
ctx(0), ctx(0),
@ -164,8 +80,6 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(const SSL_CIPHER
ciph.d->protocol = QSsl::UnknownProtocol; ciph.d->protocol = QSsl::UnknownProtocol;
if (protoString == QLatin1String("SSLv3")) if (protoString == QLatin1String("SSLv3"))
ciph.d->protocol = QSsl::SslV3; ciph.d->protocol = QSsl::SslV3;
else if (protoString == QLatin1String("SSLv2"))
ciph.d->protocol = QSsl::SslV2;
else if (protoString == QLatin1String("TLSv1")) else if (protoString == QLatin1String("TLSv1"))
ciph.d->protocol = QSsl::TlsV1; ciph.d->protocol = QSsl::TlsV1;
@ -177,12 +91,7 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(const SSL_CIPHER
ciph.d->encryptionMethod = descriptionList.at(4).mid(4); ciph.d->encryptionMethod = descriptionList.at(4).mid(4);
ciph.d->exportable = (descriptionList.size() > 6 && descriptionList.at(6) == QLatin1String("export")); ciph.d->exportable = (descriptionList.size() > 6 && descriptionList.at(6) == QLatin1String("export"));
#if OPENSSL_VERSION_NUMBER < 0x10100000L
ciph.d->bits = cipher->strength_bits;
ciph.d->supportedBits = cipher->alg_bits;
#else
ciph.d->bits = SSL_CIPHER_get_bits(cipher, &ciph.d->supportedBits); ciph.d->bits = SSL_CIPHER_get_bits(cipher, &ciph.d->supportedBits);
#endif
} }
return ciph; return ciph;
} }
@ -217,13 +126,6 @@ bool QSslSocketBackendPrivate::initSslContext()
bool reinitialized = false; bool reinitialized = false;
init_context: init_context:
switch (configuration.protocol) { switch (configuration.protocol) {
case QSsl::SslV2:
#if !defined(OPENSSL_NO_SSL2) && OPENSSL_VERSION_NUMBER < 0x10100000L
ctx = SSL_CTX_new(client ? SSLv2_client_method() : SSLv2_server_method());
#else
ctx = 0; // SSL 2 not supported by the system, but chosen deliberately -> error
#endif
break;
case QSsl::SslV3: case QSsl::SslV3:
#ifndef OPENSSL_NO_SSL3_METHOD #ifndef OPENSSL_NO_SSL3_METHOD
ctx = SSL_CTX_new(client ? SSLv3_client_method() : SSLv3_server_method()); ctx = SSL_CTX_new(client ? SSLv3_client_method() : SSLv3_server_method());
@ -234,8 +136,7 @@ init_context:
case QSsl::TlsV1: case QSsl::TlsV1:
ctx = SSL_CTX_new(client ? TLSv1_client_method() : TLSv1_server_method()); ctx = SSL_CTX_new(client ? TLSv1_client_method() : TLSv1_server_method());
break; break;
case QSsl::SecureProtocols: // SslV2 will be disabled below case QSsl::SecureProtocols:
case QSsl::TlsV1SslV3: // SslV2 will be disabled below
case QSsl::AnyProtocol: case QSsl::AnyProtocol:
default: default:
ctx = SSL_CTX_new(client ? SSLv23_client_method() : SSLv23_server_method()); ctx = SSL_CTX_new(client ? SSLv23_client_method() : SSLv23_server_method());
@ -258,11 +159,7 @@ init_context:
} }
// Enable bug workarounds. // Enable bug workarounds.
long options; long options = SSL_OP_ALL;
if (configuration.protocol == QSsl::TlsV1SslV3 || configuration.protocol == QSsl::SecureProtocols)
options = SSL_OP_ALL|SSL_OP_NO_SSLv2;
else
options = SSL_OP_ALL;
// This option is disabled by default, so we need to be able to clear it // This option is disabled by default, so we need to be able to clear it
if (configuration.sslOptions & QSsl::SslOptionDisableEmptyFragments) if (configuration.sslOptions & QSsl::SslOptionDisableEmptyFragments)
@ -392,12 +289,10 @@ init_context:
return false; return false;
} }
#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) #if !defined(OPENSSL_NO_TLSEXT)
if ((configuration.protocol == QSsl::TlsV1SslV3 || if (configuration.protocol == QSsl::TlsV1 ||
configuration.protocol == QSsl::TlsV1 ||
configuration.protocol == QSsl::SecureProtocols || configuration.protocol == QSsl::SecureProtocols ||
configuration.protocol == QSsl::AnyProtocol) && configuration.protocol == QSsl::AnyProtocol) {
client && SSLeay() >= 0x00090806fL) {
// Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format. // Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format.
QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName; QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName;
if (tlsHostName.isEmpty()) if (tlsHostName.isEmpty())
@ -459,17 +354,6 @@ void QSslSocketBackendPrivate::destroySslContext()
} }
} }
/*!
\internal
*/
void QSslSocketPrivate::deinitialize()
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L
CRYPTO_set_id_callback(0);
CRYPTO_set_locking_callback(0);
#endif
}
/*! /*!
\internal \internal
@ -485,15 +369,8 @@ bool QSslSocketPrivate::supportsSsl()
bool QSslSocketPrivate::ensureLibraryLoaded() bool QSslSocketPrivate::ensureLibraryLoaded()
{ {
// Check if the library itself needs to be initialized. // Check if the library itself needs to be initialized.
#if OPENSSL_VERSION_NUMBER < 0x10100000L
QMutexLocker locker(openssl_locks()->initLock());
#endif
if (!s_libraryLoaded) { if (!s_libraryLoaded) {
// Initialize OpenSSL. // Initialize OpenSSL.
#if OPENSSL_VERSION_NUMBER < 0x10100000L
CRYPTO_set_id_callback(id_function);
CRYPTO_set_locking_callback(locking_function);
#endif
if (SSL_library_init() != 1) if (SSL_library_init() != 1)
return false; return false;
SSL_load_error_strings(); SSL_load_error_strings();
@ -516,9 +393,6 @@ bool QSslSocketPrivate::ensureLibraryLoaded()
void QSslSocketPrivate::ensureCiphersAndCertsLoaded() void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
{ {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
QMutexLocker locker(openssl_locks()->initLock());
#endif
if (s_loadedCiphersAndCerts) if (s_loadedCiphersAndCerts)
return; return;
s_loadedCiphersAndCerts = true; s_loadedCiphersAndCerts = true;
@ -568,18 +442,11 @@ void QSslSocketPrivate::resetDefaultCiphers()
for (int i = 0; i < sk_SSL_CIPHER_num(supportedCiphers); ++i) { for (int i = 0; i < sk_SSL_CIPHER_num(supportedCiphers); ++i) {
const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(supportedCiphers, i); const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(supportedCiphers, i);
if (cipher) { if (cipher) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if (cipher->valid) {
#endif
QSslCipher ciph = QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(cipher); QSslCipher ciph = QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(cipher);
if (!ciph.isNull()) { if (!ciph.isNull()) {
if (!ciph.name().toLower().startsWith(QLatin1String("adh"))) if (!ciph.name().toLower().startsWith(QLatin1String("adh")))
ciphers << ciph; ciphers << ciph;
} }
#if OPENSSL_VERSION_NUMBER < 0x10100000L
}
#endif
} }
} }
@ -1122,14 +989,7 @@ QSslCipher QSslSocketBackendPrivate::sessionCipher() const
{ {
if (!ssl || !ctx) if (!ssl || !ctx)
return QSslCipher(); return QSslCipher();
#if OPENSSL_VERSION_NUMBER >= 0x10000000L const SSL_CIPHER *sessionCipher = SSL_get_current_cipher(ssl);
// FIXME This is fairly evil, but needed to keep source level compatibility
// with the OpenSSL 0.9.x implementation at maximum -- some other functions
// don't take a const SSL_CIPHER* when they should
SSL_CIPHER *sessionCipher = const_cast<SSL_CIPHER *>(SSL_get_current_cipher(ssl));
#else
SSL_CIPHER *sessionCipher = SSL_get_current_cipher(ssl);
#endif
return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher(); return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
} }

View file

@ -53,13 +53,11 @@
#include <openssl/dsa.h> #include <openssl/dsa.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include <openssl/crypto.h> #include <openssl/crypto.h>
#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) #if !defined(OPENSSL_NO_TLSEXT)
#include <openssl/tls1.h> #include <openssl/tls1.h>
#endif #endif
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
typedef _STACK STACK; typedef _STACK STACK;
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View file

@ -72,7 +72,6 @@ public:
static bool supportsSsl(); static bool supportsSsl();
static void ensureInitialized(); static void ensureInitialized();
static void deinitialize();
static QList<QSslCipher> defaultCiphers(); static QList<QSslCipher> defaultCiphers();
static QList<QSslCipher> supportedCiphers(); static QList<QSslCipher> supportedCiphers();
static void setDefaultCiphers(const QList<QSslCipher> &ciphers); static void setDefaultCiphers(const QList<QSslCipher> &ciphers);