OSDN Git Service

require OpenSSL v1.1.0 as minumum
authorIvailo Monev <xakepa10@gmail.com>
Mon, 28 Jun 2021 08:30:49 +0000 (11:30 +0300)
committerIvailo Monev <xakepa10@gmail.com>
Mon, 28 Jun 2021 08:30:49 +0000 (11:30 +0300)
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
CMakeLists.txt
src/network/ssl/qssl.cpp
src/network/ssl/qssl.h
src/network/ssl/qsslcertificate.cpp
src/network/ssl/qsslkey.cpp
src/network/ssl/qsslsocket_openssl.cpp
src/network/ssl/qsslsocket_openssl_p.h
src/network/ssl/qsslsocket_p.h

index d477532..24e99b0 100644 (file)
@@ -222,8 +222,8 @@ set_package_properties(Jansson PROPERTIES
     TYPE REQUIRED
 )
 
-# v0.9.8+ required for SHA-224...SHA-512 support
-find_package(OpenSSL 0.9.8)
+# v1.1.0+ required for thread-safety without use of locking callbacks
+find_package(OpenSSL 1.1.0)
 set_package_properties(OpenSSL PROPERTIES
     PURPOSE "Required for HTTPS support"
     DESCRIPTION "Robust, commercial-grade, and full-featured toolkit for SSL and TLS"
index ece2601..b966b6c 100644 (file)
@@ -82,16 +82,12 @@ QT_BEGIN_NAMESPACE
     Describes the protocol of the cipher.
 
     \value SslV3 SSLv3
-    \value SslV2 SSLv2
     \value TlsV1 TLSv1
     \value UnknownProtocol The cipher's protocol cannot be determined.
     \value AnyProtocol The socket understands SSLv2, SSLv3, and TLSv1. This
     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;
-    currently behaves like TlsV1SslV3.
+    currently behaves like AnyProtocol.
 
     Note: most servers using SSL understand both versions (2 and 3),
     but it is recommended to use the latest version only for security
index 963e30a..dcff5da 100644 (file)
@@ -52,10 +52,8 @@ namespace QSsl {
 
     enum SslProtocol {
         SslV3,
-        SslV2,
         TlsV1, // ### Qt 5: rename to TlsV1_0 or so
         AnyProtocol,
-        TlsV1SslV3,
         SecureProtocols,
         UnknownProtocol = -1
     };
index 974ab17..c2d2bdd 100644 (file)
@@ -401,11 +401,7 @@ QMultiMap<QSsl::AlternateNameEntryType, QString> QSslCertificate::alternateSubje
                 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));
-#endif
             const QString altName = QString::fromLatin1(altNameStr, len);
             if (genName->type == GEN_DNS)
                 result.insert(QSsl::DnsEntry, altName);
@@ -467,19 +463,11 @@ QSslKey QSslCertificate::publicKey() const
     QSslKey key;
 
     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);
-#endif
     EVP_PKEY *pkey = X509_PUBKEY_get(xkey);
     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);
-#endif
     if (key_id == EVP_PKEY_RSA) {
         key.d->rsa = EVP_PKEY_get1_RSA(pkey);
         key.d->algorithm = QSsl::Rsa;
index 4e6f875..a0df77e 100644 (file)
@@ -286,10 +286,6 @@ int QSslKey::length() const
 {
     if (d->isNull)
         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) {
         return RSA_bits(d->rsa);
     }else{
@@ -297,7 +293,6 @@ int QSslKey::length() const
         DSA_get0_pqg(d->dsa, &p, NULL, NULL);
         return BN_num_bits(p);
     }
-#endif
 
 }
 
index 31406ff..62b3e14 100644 (file)
@@ -45,90 +45,6 @@ bool QSslSocketPrivate::s_libraryLoaded = false;
 bool QSslSocketPrivate::s_loadedCiphersAndCerts = 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()
     : ssl(0),
       ctx(0),
@@ -164,8 +80,6 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(const SSL_CIPHER
         ciph.d->protocol = QSsl::UnknownProtocol;
         if (protoString == QLatin1String("SSLv3"))
             ciph.d->protocol = QSsl::SslV3;
-        else if (protoString == QLatin1String("SSLv2"))
-            ciph.d->protocol = QSsl::SslV2;
         else if (protoString == QLatin1String("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->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);
-#endif
     }
     return ciph;
 }
@@ -217,13 +126,6 @@ bool QSslSocketBackendPrivate::initSslContext()
     bool reinitialized = false;
 init_context:
     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:
 #ifndef OPENSSL_NO_SSL3_METHOD
         ctx = SSL_CTX_new(client ? SSLv3_client_method() : SSLv3_server_method());
@@ -234,8 +136,7 @@ init_context:
     case QSsl::TlsV1:
         ctx = SSL_CTX_new(client ? TLSv1_client_method() : TLSv1_server_method());
         break;
-    case QSsl::SecureProtocols: // SslV2 will be disabled below
-    case QSsl::TlsV1SslV3: // SslV2 will be disabled below
+    case QSsl::SecureProtocols:
     case QSsl::AnyProtocol:
     default:
         ctx = SSL_CTX_new(client ? SSLv23_client_method() : SSLv23_server_method());
@@ -258,11 +159,7 @@ init_context:
     }
 
     // Enable bug workarounds.
-    long options;
-    if (configuration.protocol == QSsl::TlsV1SslV3 || configuration.protocol == QSsl::SecureProtocols)
-        options = SSL_OP_ALL|SSL_OP_NO_SSLv2;
-    else
-        options = SSL_OP_ALL;
+    long options = SSL_OP_ALL;
 
     // This option is disabled by default, so we need to be able to clear it
     if (configuration.sslOptions & QSsl::SslOptionDisableEmptyFragments)
@@ -392,12 +289,10 @@ init_context:
         return false;
     }
 
-#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
-    if ((configuration.protocol == QSsl::TlsV1SslV3 ||
-        configuration.protocol == QSsl::TlsV1 ||
+#if !defined(OPENSSL_NO_TLSEXT)
+    if (configuration.protocol == QSsl::TlsV1 ||
         configuration.protocol == QSsl::SecureProtocols ||
-        configuration.protocol == QSsl::AnyProtocol) &&
-        client && SSLeay() >= 0x00090806fL) {
+        configuration.protocol == QSsl::AnyProtocol) {
         // Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format.
         QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName;
         if (tlsHostName.isEmpty())
@@ -461,17 +356,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
 
     Does the minimum amount of initialization to determine whether SSL
     is supported or not.
@@ -485,15 +369,8 @@ bool QSslSocketPrivate::supportsSsl()
 bool QSslSocketPrivate::ensureLibraryLoaded()
 {
     // Check if the library itself needs to be initialized.
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-    QMutexLocker locker(openssl_locks()->initLock());
-#endif
     if (!s_libraryLoaded) {
         // 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)
             return false;
         SSL_load_error_strings();
@@ -516,9 +393,6 @@ bool QSslSocketPrivate::ensureLibraryLoaded()
 
 void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
 {
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-  QMutexLocker locker(openssl_locks()->initLock());
-#endif
     if (s_loadedCiphersAndCerts)
         return;
     s_loadedCiphersAndCerts = true;
@@ -568,18 +442,11 @@ void QSslSocketPrivate::resetDefaultCiphers()
     for (int i = 0; i < sk_SSL_CIPHER_num(supportedCiphers); ++i) {
         const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(supportedCiphers, i);
         if (cipher) {
-
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-            if (cipher->valid) {
-#endif
-                QSslCipher ciph = QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(cipher);
-                if (!ciph.isNull()) {
-                    if (!ciph.name().toLower().startsWith(QLatin1String("adh")))
-                        ciphers << ciph;
-                }
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
+            QSslCipher ciph = QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(cipher);
+            if (!ciph.isNull()) {
+                if (!ciph.name().toLower().startsWith(QLatin1String("adh")))
+                    ciphers << ciph;
             }
-#endif
         }
     }
 
@@ -1122,14 +989,7 @@ QSslCipher QSslSocketBackendPrivate::sessionCipher() const
 {
     if (!ssl || !ctx)
         return QSslCipher();
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
-    // 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
+    const SSL_CIPHER *sessionCipher = SSL_get_current_cipher(ssl);
     return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
 }
 
index e05b5f4..c609d71 100644 (file)
 #include <openssl/dsa.h>
 #include <openssl/rsa.h>
 #include <openssl/crypto.h>
-#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
+#if !defined(OPENSSL_NO_TLSEXT)
 #include <openssl/tls1.h>
 #endif
 
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
 typedef _STACK STACK;
-#endif
 
 QT_BEGIN_NAMESPACE
 
index 2ea5f51..62445e3 100644 (file)
@@ -72,7 +72,6 @@ public:
 
     static bool supportsSsl();
     static void ensureInitialized();
-    static void deinitialize();
     static QList<QSslCipher> defaultCiphers();
     static QList<QSslCipher> supportedCiphers();
     static void setDefaultCiphers(const QList<QSslCipher> &ciphers);