diff options
Diffstat (limited to 'src/network/ssl')
23 files changed, 297 insertions, 227 deletions
diff --git a/src/network/ssl/qssl.cpp b/src/network/ssl/qssl.cpp index 26381fcb8e..84aa9d7dca 100644 --- a/src/network/ssl/qssl.cpp +++ b/src/network/ssl/qssl.cpp @@ -166,6 +166,10 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl"); in ASN.1 format as returned by QSslConfiguration::sessionTicket(). Enabling this feature adds memory overhead of approximately 1K per used session ticket. + \value SslOptionDisableServerCipherPreference Disables selecting the cipher + chosen based on the servers preferences rather than the order ciphers were + sent by the client. This option is only relevant to server sockets, and is + only honored by the OpenSSL backend. By default, SslOptionDisableEmptyFragments is turned on since this causes problems with a large number of servers. SslOptionDisableLegacyRenegotiation diff --git a/src/network/ssl/qssl.h b/src/network/ssl/qssl.h index f56c36b219..03497ecf76 100644 --- a/src/network/ssl/qssl.h +++ b/src/network/ssl/qssl.h @@ -95,7 +95,8 @@ namespace QSsl { SslOptionDisableServerNameIndication = 0x08, SslOptionDisableLegacyRenegotiation = 0x10, SslOptionDisableSessionSharing = 0x20, - SslOptionDisableSessionPersistence = 0x40 + SslOptionDisableSessionPersistence = 0x40, + SslOptionDisableServerCipherPreference = 0x80 }; Q_DECLARE_FLAGS(SslOptions, SslOption) } diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index ef0767ae8f..af605b0629 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -83,9 +83,12 @@ public: explicit QSslCertificate(const QByteArray &data = QByteArray(), QSsl::EncodingFormat format = QSsl::Pem); QSslCertificate(const QSslCertificate &other); ~QSslCertificate(); +#ifdef Q_COMPILER_RVALUE_REFS + QSslCertificate &operator=(QSslCertificate &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif QSslCertificate &operator=(const QSslCertificate &other); - inline void swap(QSslCertificate &other) + void swap(QSslCertificate &other) Q_DECL_NOTHROW { qSwap(d, other.d); } bool operator==(const QSslCertificate &other) const; @@ -144,7 +147,7 @@ public: static bool importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *cert, - QList<QSslCertificate> *caCertificates=0, + QList<QSslCertificate> *caCertificates = Q_NULLPTR, const QByteArray &passPhrase=QByteArray()); Qt::HANDLE handle() const; diff --git a/src/network/ssl/qsslcertificate_openssl.cpp b/src/network/ssl/qsslcertificate_openssl.cpp index ad88ea5d56..3324587821 100644 --- a/src/network/ssl/qsslcertificate_openssl.cpp +++ b/src/network/ssl/qsslcertificate_openssl.cpp @@ -464,8 +464,9 @@ QList<QSslCertificateExtension> QSslCertificate::extensions() const return result; int count = q_X509_get_ext_count(d->x509); + result.reserve(count); - for (int i=0; i < count; i++) { + for (int i = 0; i < count; i++) { X509_EXTENSION *ext = q_X509_get_ext(d->x509, i); result << QSslCertificatePrivate::convertExtension(ext); } diff --git a/src/network/ssl/qsslcertificateextension.h b/src/network/ssl/qsslcertificateextension.h index 7c958eff30..8dd0e8eb4b 100644 --- a/src/network/ssl/qsslcertificateextension.h +++ b/src/network/ssl/qsslcertificateextension.h @@ -51,11 +51,13 @@ class Q_NETWORK_EXPORT QSslCertificateExtension public: QSslCertificateExtension(); QSslCertificateExtension(const QSslCertificateExtension &other); - ~QSslCertificateExtension(); - +#ifdef Q_COMPILER_RVALUE_REFS + QSslCertificateExtension &operator=(QSslCertificateExtension &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif QSslCertificateExtension &operator=(const QSslCertificateExtension &other); + ~QSslCertificateExtension(); - void swap(QSslCertificateExtension &other) { qSwap(d, other.d); } + void swap(QSslCertificateExtension &other) Q_DECL_NOTHROW { qSwap(d, other.d); } QString oid() const; QString name() const; diff --git a/src/network/ssl/qsslcipher.h b/src/network/ssl/qsslcipher.h index dc65e32111..64122cdd53 100644 --- a/src/network/ssl/qsslcipher.h +++ b/src/network/ssl/qsslcipher.h @@ -52,10 +52,13 @@ public: explicit QSslCipher(const QString &name); QSslCipher(const QString &name, QSsl::SslProtocol protocol); QSslCipher(const QSslCipher &other); - ~QSslCipher(); +#ifdef Q_COMPILER_RVALUE_REFS + QSslCipher &operator=(QSslCipher &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif QSslCipher &operator=(const QSslCipher &other); + ~QSslCipher(); - inline void swap(QSslCipher &other) + void swap(QSslCipher &other) Q_DECL_NOTHROW { qSwap(d, other.d); } bool operator==(const QSslCipher &other) const; diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h index 960aec60ce..2cbc31b032 100644 --- a/src/network/ssl/qsslconfiguration.h +++ b/src/network/ssl/qsslconfiguration.h @@ -71,9 +71,12 @@ public: QSslConfiguration(); QSslConfiguration(const QSslConfiguration &other); ~QSslConfiguration(); +#ifdef Q_COMPILER_RVALUE_REFS + QSslConfiguration &operator=(QSslConfiguration &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif QSslConfiguration &operator=(const QSslConfiguration &other); - inline void swap(QSslConfiguration &other) + void swap(QSslConfiguration &other) Q_DECL_NOTHROW { qSwap(d, other.d); } bool operator==(const QSslConfiguration &other) const; diff --git a/src/network/ssl/qsslellipticcurve.cpp b/src/network/ssl/qsslellipticcurve.cpp index b4396d567b..0824a61e8d 100644 --- a/src/network/ssl/qsslellipticcurve.cpp +++ b/src/network/ssl/qsslellipticcurve.cpp @@ -170,7 +170,7 @@ QDebug operator<<(QDebug debug, QSslEllipticCurve curve) { QDebugStateSaver saver(debug); debug.resetFormat().nospace(); - debug << "QSslEllipticCurve(" << curve.shortName() << ")"; + debug << "QSslEllipticCurve(" << curve.shortName() << ')'; return debug; } #endif diff --git a/src/network/ssl/qsslellipticcurve.h b/src/network/ssl/qsslellipticcurve.h index a991881b93..5716e3447d 100644 --- a/src/network/ssl/qsslellipticcurve.h +++ b/src/network/ssl/qsslellipticcurve.h @@ -37,7 +37,10 @@ #include <QtCore/QtGlobal> #include <QtCore/QString> #include <QtCore/QMetaType> +#if QT_DEPRECATED_SINCE(5, 5) #include <QtCore/QHash> +#endif +#include <QtCore/qhashfunctions.h> QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/qsslerror.h b/src/network/ssl/qsslerror.h index b149f86d9e..bc2a2d5220 100644 --- a/src/network/ssl/qsslerror.h +++ b/src/network/ssl/qsslerror.h @@ -84,10 +84,13 @@ public: QSslError(const QSslError &other); - inline void swap(QSslError &other) + void swap(QSslError &other) Q_DECL_NOTHROW { qSwap(d, other.d); } ~QSslError(); +#ifdef Q_COMPILER_RVALUE_REFS + QSslError &operator=(QSslError &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif QSslError &operator=(const QSslError &other); bool operator==(const QSslError &other) const; inline bool operator!=(const QSslError &other) const diff --git a/src/network/ssl/qsslkey.h b/src/network/ssl/qsslkey.h index b89069e4cb..d02c031015 100644 --- a/src/network/ssl/qsslkey.h +++ b/src/network/ssl/qsslkey.h @@ -64,10 +64,13 @@ public: const QByteArray &passPhrase = QByteArray()); explicit QSslKey(Qt::HANDLE handle, QSsl::KeyType type = QSsl::PrivateKey); QSslKey(const QSslKey &other); - ~QSslKey(); +#ifdef Q_COMPILER_RVALUE_REFS + QSslKey &operator=(QSslKey &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif QSslKey &operator=(const QSslKey &other); + ~QSslKey(); - inline void swap(QSslKey &other) { qSwap(d, other.d); } + void swap(QSslKey &other) Q_DECL_NOTHROW { qSwap(d, other.d); } bool isNull() const; void clear(); diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp index 33cb81ce71..a90c9411b7 100644 --- a/src/network/ssl/qsslkey_openssl.cpp +++ b/src/network/ssl/qsslkey_openssl.cpp @@ -265,4 +265,53 @@ Qt::HANDLE QSslKeyPrivate::handle() const } } +static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv, int enc) +{ + EVP_CIPHER_CTX ctx; + const EVP_CIPHER* type = 0; + int i = 0, len = 0; + + switch (cipher) { + case QSslKeyPrivate::DesCbc: + type = q_EVP_des_cbc(); + break; + case QSslKeyPrivate::DesEde3Cbc: + type = q_EVP_des_ede3_cbc(); + break; + case QSslKeyPrivate::Rc2Cbc: + type = q_EVP_rc2_cbc(); + break; + } + + QByteArray output; + output.resize(data.size() + EVP_MAX_BLOCK_LENGTH); + q_EVP_CIPHER_CTX_init(&ctx); + q_EVP_CipherInit(&ctx, type, NULL, NULL, 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(), NULL); + q_EVP_CipherInit(&ctx, NULL, + reinterpret_cast<const unsigned char *>(key.constData()), + reinterpret_cast<const unsigned char *>(iv.constData()), enc); + q_EVP_CipherUpdate(&ctx, + reinterpret_cast<unsigned char *>(output.data()), &len, + reinterpret_cast<const unsigned char *>(data.constData()), data.size()); + q_EVP_CipherFinal(&ctx, + reinterpret_cast<unsigned char *>(output.data()) + len, &i); + len += i; + q_EVP_CIPHER_CTX_cleanup(&ctx); + + return output.left(len); +} + +QByteArray QSslKeyPrivate::decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) +{ + return doCrypt(cipher, data, key, iv, 0); +} + +QByteArray QSslKeyPrivate::encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) +{ + return doCrypt(cipher, data, key, iv, 1); +} + QT_END_NAMESPACE diff --git a/src/network/ssl/qsslkey_p.h b/src/network/ssl/qsslkey_p.h index be981bb484..fea0e30bbc 100644 --- a/src/network/ssl/qsslkey_p.h +++ b/src/network/ssl/qsslkey_p.h @@ -90,6 +90,16 @@ public: bool isNull; QSsl::KeyType type; QSsl::KeyAlgorithm algorithm; + + enum Cipher { + DesCbc, + DesEde3Cbc, + Rc2Cbc + }; + + Q_AUTOTEST_EXPORT static QByteArray decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv); + Q_AUTOTEST_EXPORT static QByteArray encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv); + #ifndef QT_NO_OPENSSL union { EVP_PKEY *opaque; @@ -100,15 +110,6 @@ public: #endif }; #else - enum Cipher { - DesCbc, - DesEde3Cbc, - Rc2Cbc - }; - - Q_AUTOTEST_EXPORT static QByteArray decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv); - Q_AUTOTEST_EXPORT static QByteArray encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv); - Qt::HANDLE opaque; QByteArray derData; int keyLength; diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.h b/src/network/ssl/qsslpresharedkeyauthenticator.h index 159b16d563..34e5d6fd50 100644 --- a/src/network/ssl/qsslpresharedkeyauthenticator.h +++ b/src/network/ssl/qsslpresharedkeyauthenticator.h @@ -52,14 +52,10 @@ public: Q_NETWORK_EXPORT QSslPreSharedKeyAuthenticator &operator=(const QSslPreSharedKeyAuthenticator &authenticator); #ifdef Q_COMPILER_RVALUE_REFS - inline QSslPreSharedKeyAuthenticator &operator=(QSslPreSharedKeyAuthenticator &&authenticator) - { d.swap(authenticator.d); return *this; } + QSslPreSharedKeyAuthenticator &operator=(QSslPreSharedKeyAuthenticator &&other) Q_DECL_NOTHROW { swap(other); return *this; } #endif - void swap(QSslPreSharedKeyAuthenticator &authenticator) - { - d.swap(authenticator.d); - } + void swap(QSslPreSharedKeyAuthenticator &other) Q_DECL_NOTHROW { qSwap(d, other.d); } Q_NETWORK_EXPORT QByteArray identityHint() const; diff --git a/src/network/ssl/qsslpresharedkeyauthenticator_p.h b/src/network/ssl/qsslpresharedkeyauthenticator_p.h index ba7a740907..c57b6b10ca 100644 --- a/src/network/ssl/qsslpresharedkeyauthenticator_p.h +++ b/src/network/ssl/qsslpresharedkeyauthenticator_p.h @@ -34,6 +34,17 @@ #ifndef QSSLPRESHAREDKEYAUTHENTICATOR_P_H #define QSSLPRESHAREDKEYAUTHENTICATOR_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + #include <QSharedData> QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 9b5d90225f..788e59df24 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -499,8 +499,7 @@ bool QSslSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState state d->createPlainSocket(openMode); bool retVal = d->plainSocket->setSocketDescriptor(socketDescriptor, state, openMode); d->cachedSocketDescriptor = d->plainSocket->socketDescriptor(); - setSocketError(d->plainSocket->error()); - setErrorString(d->plainSocket->errorString()); + d->setError(d->plainSocket->error(), d->plainSocket->errorString()); setSocketState(state); setOpenMode(openMode); setLocalPort(d->plainSocket->localPort()); @@ -1243,7 +1242,7 @@ void QSslSocket::setCiphers(const QString &ciphers) { Q_D(QSslSocket); d->configuration.ciphers.clear(); - foreach (const QString &cipherName, ciphers.split(QLatin1String(":"),QString::SkipEmptyParts)) { + foreach (const QString &cipherName, ciphers.split(QLatin1Char(':'), QString::SkipEmptyParts)) { QSslCipher cipher(cipherName); if (!cipher.isNull()) d->configuration.ciphers << cipher; @@ -1532,8 +1531,7 @@ bool QSslSocket::waitForConnected(int msecs) bool retVal = d->plainSocket->waitForConnected(msecs); if (!retVal) { setSocketState(d->plainSocket->state()); - setSocketError(d->plainSocket->error()); - setErrorString(d->plainSocket->errorString()); + d->setError(d->plainSocket->error(), d->plainSocket->errorString()); } return retVal; } @@ -1688,8 +1686,7 @@ bool QSslSocket::waitForDisconnected(int msecs) bool retVal = d->plainSocket->waitForDisconnected(qt_subtract_from_timeout(msecs, stopWatch.elapsed())); if (!retVal) { setSocketState(d->plainSocket->state()); - setSocketError(d->plainSocket->error()); - setErrorString(d->plainSocket->errorString()); + d->setError(d->plainSocket->error(), d->plainSocket->errorString()); } return retVal; } @@ -2402,8 +2399,9 @@ void QSslSocketPrivate::_q_stateChangedSlot(QAbstractSocket::SocketState state) */ void QSslSocketPrivate::_q_errorSlot(QAbstractSocket::SocketError error) { - Q_Q(QSslSocket); + Q_UNUSED(error) #ifdef QSSLSOCKET_DEBUG + Q_Q(QSslSocket); qCDebug(lcSsl) << "QSslSocket::_q_errorSlot(" << error << ')'; qCDebug(lcSsl) << "\tstate =" << q->state(); qCDebug(lcSsl) << "\terrorString =" << q->errorString(); @@ -2416,9 +2414,7 @@ void QSslSocketPrivate::_q_errorSlot(QAbstractSocket::SocketError error) readBufferMaxSize = tmpReadBufferMaxSize; } - q->setSocketError(plainSocket->error()); - q->setErrorString(plainSocket->errorString()); - emit q->error(error); + setErrorAndEmit(plainSocket->error(), plainSocket->errorString()); } /*! @@ -2483,7 +2479,6 @@ void QSslSocketPrivate::_q_flushReadBuffer() */ void QSslSocketPrivate::_q_resumeImplementation() { - Q_Q(QSslSocket); if (plainSocket) plainSocket->resume(); paused = false; @@ -2491,9 +2486,7 @@ void QSslSocketPrivate::_q_resumeImplementation() if (verifyErrorsHaveBeenIgnored()) { continueHandshake(); } else { - q->setErrorString(sslErrors.first().errorString()); - q->setSocketError(QAbstractSocket::SslHandshakeFailedError); - emit q->error(QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.first().errorString()); plainSocket->disconnectFromHost(); return; } diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h index 4124f5b7e5..22856c6ea9 100644 --- a/src/network/ssl/qsslsocket.h +++ b/src/network/ssl/qsslsocket.h @@ -72,7 +72,7 @@ public: AutoVerifyPeer }; - explicit QSslSocket(QObject *parent = 0); + explicit QSslSocket(QObject *parent = Q_NULLPTR); ~QSslSocket(); void resume() Q_DECL_OVERRIDE; // to continue after proxy authentication required, SSL errors etc. diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index b83e56c29e..06c707f271 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -51,6 +51,10 @@ #include <algorithm> #include <cstddef> +#ifdef Q_OS_OSX +#include <CoreServices/CoreServices.h> +#endif + QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_securetransport_mutex, (QMutex::Recursive)) @@ -318,7 +322,7 @@ void QSslSocketBackendPrivate::startClientEncryption() // Error description/code were set, 'error' emitted // by initSslContext, but OpenSSL socket also sets error // emits a signal twice, so ... - setError("Unable to init SSL Context", QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, "Unable to init SSL Context"); return; } @@ -331,7 +335,7 @@ void QSslSocketBackendPrivate::startServerEncryption() // Error description/code were set, 'error' emitted // by initSslContext, but OpenSSL socket also sets error // emits a signal twice, so ... - setError("Unable to init SSL Context", QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, "Unable to init SSL Context"); return; } @@ -360,8 +364,8 @@ void QSslSocketBackendPrivate::transmit() qCDebug(lcSsl) << plainSocket << "SSLWrite returned" << err; #endif if (err != noErr && err != errSSLWouldBlock) { - setError(QStringLiteral("SSLWrite failed: %1").arg(err), - QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QStringLiteral("SSLWrite failed: %1").arg(err)); break; } @@ -395,12 +399,12 @@ void QSslSocketBackendPrivate::transmit() #endif if (err == errSSLClosedGraceful) { shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves - setError(QSslSocket::tr("The TLS/SSL connection has been closed"), - QAbstractSocket::RemoteHostClosedError); + setErrorAndEmit(QAbstractSocket::RemoteHostClosedError, + QSslSocket::tr("The TLS/SSL connection has been closed")); break; } else if (err != noErr && err != errSSLWouldBlock) { - setError(QStringLiteral("SSLRead failed: %1").arg(err), - QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QStringLiteral("SSLRead failed: %1").arg(err)); break; } @@ -658,7 +662,7 @@ bool QSslSocketBackendPrivate::initSslContext() context = SSLCreateContext(Q_NULLPTR, side, kSSLStreamType); if (!context) { - setError("SSLCreateContext failed", QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, "SSLCreateContext failed"); return false; } @@ -666,8 +670,8 @@ bool QSslSocketBackendPrivate::initSslContext() reinterpret_cast<SSLWriteFunc>(&_q_SSLWrite)); if (err != noErr) { destroySslContext(); - setError(QStringLiteral("SSLSetIOFuncs failed: %1").arg(err), - QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QStringLiteral("SSLSetIOFuncs failed: %1").arg(err)); return false; } @@ -679,14 +683,14 @@ bool QSslSocketBackendPrivate::initSslContext() QAbstractSocket::SocketError errorCode = QAbstractSocket::UnknownSocketError; if (!setSessionCertificate(errorDescription, errorCode)) { destroySslContext(); - setError(errorDescription, errorCode); + setErrorAndEmit(errorCode, errorDescription); return false; } } if (!setSessionProtocol()) { destroySslContext(); - setError("Failed to set protocol version", QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, "Failed to set protocol version"); return false; } @@ -698,8 +702,8 @@ bool QSslSocketBackendPrivate::initSslContext() const OSStatus err = SSLSetEnableCertVerify(context, false); if (err != noErr) { destroySslContext(); - setError(QStringLiteral("SSLSetEnableCertVerify failed: %1").arg(err), - QSslSocket::SslInternalError); + setErrorAndEmit(QSslSocket::SslInternalError, + QStringLiteral("SSLSetEnableCertVerify failed: %1").arg(err)); return false; } } @@ -720,8 +724,8 @@ bool QSslSocketBackendPrivate::initSslContext() if (err != noErr) { destroySslContext(); - setError(QStringLiteral("SSLSetSessionOption failed: %1").arg(err), - QSslSocket::SslInternalError); + setErrorAndEmit(QSslSocket::SslInternalError, + QStringLiteral("SSLSetSessionOption failed: %1").arg(err)); return false; } // @@ -737,8 +741,8 @@ bool QSslSocketBackendPrivate::initSslContext() if (err != noErr) { destroySslContext(); - setError(QStringLiteral("failed to set SSL context option in server mode: %1").arg(err), - QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QStringLiteral("failed to set SSL context option in server mode: %1").arg(err)); return false; } } @@ -981,8 +985,8 @@ bool QSslSocketBackendPrivate::verifyPeerTrust() // !trust - SSLCopyPeerTrust can return noErr but null trust. if (err != noErr || !trust) { if (!canIgnoreVerify) { - setError(QStringLiteral("Failed to obtain peer trust: %1").arg(err), - QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, + QStringLiteral("Failed to obtain peer trust: %1").arg(err)); plainSocket->disconnectFromHost(); return false; } else { @@ -1005,8 +1009,8 @@ bool QSslSocketBackendPrivate::verifyPeerTrust() if (err != noErr) { // We can not ignore this, it's not even about trust verification // probably ... - setError(QStringLiteral("SecTrustEvaluate failed: %1").arg(err), - QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, + QStringLiteral("SecTrustEvaluate failed: %1").arg(err)); plainSocket->disconnectFromHost(); return false; } @@ -1124,8 +1128,8 @@ bool QSslSocketBackendPrivate::checkSslErrors() pauseSocketNotifiers(q); paused = true; } else { - setError(sslErrors.first().errorString(), - QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, + sslErrors.first().errorString()); plainSocket->disconnectFromHost(); } return false; @@ -1162,7 +1166,7 @@ bool QSslSocketBackendPrivate::startHandshake() // setSessionCertificate does not fail if we have no certificate. // Failure means a real error (invalid certificate, no private key, etc). if (!setSessionCertificate(errorDescription, errorCode)) { - setError(errorDescription, errorCode); + setErrorAndEmit(errorCode, errorDescription); return false; } else { // We try to resume a handshake, even if have no @@ -1177,8 +1181,8 @@ bool QSslSocketBackendPrivate::startHandshake() return startHandshake(); } - setError(QStringLiteral("SSLHandshake failed: %1").arg(err), - QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, + QStringLiteral("SSLHandshake failed: %1").arg(err)); plainSocket->disconnectFromHost(); return false; } @@ -1192,8 +1196,8 @@ bool QSslSocketBackendPrivate::startHandshake() // check protocol version ourselves, as Secure Transport does not enforce // the requested min / max versions. if (!verifySessionProtocol()) { - setError("Protocol version mismatch", - QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, + "Protocol version mismatch"); plainSocket->disconnectFromHost(); return false; } @@ -1206,16 +1210,6 @@ bool QSslSocketBackendPrivate::startHandshake() } } -void QSslSocketBackendPrivate::setError(const QString &errorString, - QAbstractSocket::SocketError errorCode) -{ - Q_Q(QSslSocket); - - q->setErrorString(errorString); - q->setSocketError(errorCode); - emit q->error(errorCode); -} - /* PKCS12 helpers. */ diff --git a/src/network/ssl/qsslsocket_mac_p.h b/src/network/ssl/qsslsocket_mac_p.h index 868b816957..414c155882 100644 --- a/src/network/ssl/qsslsocket_mac_p.h +++ b/src/network/ssl/qsslsocket_mac_p.h @@ -101,13 +101,6 @@ private: bool checkSslErrors(); bool startHandshake(); - // Aux. function, sets: - //1) socket error code, - //2) error string (description) - //3) emits a signal. - void setError(const QString &errorString, - QAbstractSocket::SocketError errorCode); - mutable QCFType<SSLContextRef> context; Q_DISABLE_COPY(QSslSocketBackendPrivate); diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index a21317d0f2..a8e4c61e9a 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -225,7 +225,7 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *ciph char buf [256]; QString descriptionOneLine = QString::fromLatin1(q_SSL_CIPHER_description(cipher, buf, sizeof(buf))); - QStringList descriptionList = descriptionOneLine.split(QLatin1String(" "), QString::SkipEmptyParts); + QStringList descriptionList = descriptionOneLine.split(QLatin1Char(' '), QString::SkipEmptyParts); if (descriptionList.size() > 5) { // ### crude code. ciph.d->isNull = false; @@ -290,7 +290,7 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx) << "OU=" << cert.subjectInfo(QSslCertificate::OrganizationalUnitName) << "C=" << cert.subjectInfo(QSslCertificate::CountryName) << "ST=" << cert.subjectInfo(QSslCertificate::StateOrProvinceName); - qCDebug(lcSsl) << "Valid:" << cert.effectiveDate() << "-" << cert.expiryDate(); + qCDebug(lcSsl) << "Valid:" << cert.effectiveDate() << '-' << cert.expiryDate(); } #endif } @@ -344,6 +344,9 @@ long QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SslProtocol protocol, Q options |= SSL_OP_NO_COMPRESSION; #endif + if (!(sslOptions & QSsl::SslOptionDisableServerCipherPreference)) + options |= SSL_OP_CIPHER_SERVER_PREFERENCE; + return options; } @@ -361,9 +364,7 @@ bool QSslSocketBackendPrivate::initSslContext() } if (sslContextPointer->error() != QSslError::NoError) { - q->setErrorString(sslContextPointer->errorString()); - q->setSocketError(QAbstractSocket::SslInvalidUserDataError); - emit q->error(QAbstractSocket::SslInvalidUserDataError); + setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError, sslContextPointer->errorString()); sslContextPointer.clear(); // deletes the QSslContext return false; } @@ -371,9 +372,8 @@ bool QSslSocketBackendPrivate::initSslContext() // Create and initialize SSL session if (!(ssl = sslContextPointer->createSsl())) { // ### Bad error code - q->setErrorString(QSslSocket::tr("Error creating SSL session, %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Error creating SSL session, %1").arg(getErrorsFromOpenSsl())); return false; } @@ -402,9 +402,8 @@ bool QSslSocketBackendPrivate::initSslContext() readBio = q_BIO_new(q_BIO_s_mem()); writeBio = q_BIO_new(q_BIO_s_mem()); if (!readBio || !writeBio) { - q->setErrorString(QSslSocket::tr("Error creating SSL session: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Error creating SSL session: %1").arg(getErrorsFromOpenSsl())); return false; } @@ -488,30 +487,8 @@ bool QSslSocketPrivate::ensureLibraryLoaded() // Initialize OpenSSL's random seed. if (!q_RAND_status()) { - struct { - int msec; - int sec; - void *stack; - } randomish; - - int attempts = 500; - do { - if (attempts < 500) { -#ifdef Q_OS_UNIX - struct timespec ts = {0, 33333333}; - nanosleep(&ts, 0); -#else - Sleep(3); -#endif - randomish.msec = attempts; - } - randomish.stack = (void *)&randomish; - randomish.msec = QTime::currentTime().msec(); - randomish.sec = QTime::currentTime().second(); - q_RAND_seed((const char *)&randomish, sizeof(randomish)); - } while (!q_RAND_status() && --attempts); - if (!attempts) - return false; + qWarning("Random number generator not seeded, disabling SSL support"); + return false; } } return true; @@ -659,8 +636,10 @@ void QSslSocketPrivate::resetDefaultCiphers() if (SSL_CIPHER *cipher = q_sk_SSL_CIPHER_value(supportedCiphers, i)) { QSslCipher ciph = QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(cipher); if (!ciph.isNull()) { - // Unconditionally exclude ADH ciphers since they offer no MITM protection - if (!ciph.name().toLower().startsWith(QLatin1String("adh"))) + // Unconditionally exclude ADH and AECDH ciphers since they offer no MITM protection + if (!ciph.name().toLower().startsWith(QLatin1String("adh")) && + !ciph.name().toLower().startsWith(QLatin1String("exp-adh")) && + !ciph.name().toLower().startsWith(QLatin1String("aecdh"))) ciphers << ciph; if (ciph.usedBits() >= 128) defaultCiphers << ciph; @@ -685,6 +664,7 @@ void QSslSocketPrivate::resetDefaultEllipticCurves() QVarLengthArray<EC_builtin_curve> builtinCurves(static_cast<int>(curveCount)); if (q_EC_get_builtin_curves(builtinCurves.data(), curveCount) == curveCount) { + curves.reserve(int(curveCount)); for (size_t i = 0; i < curveCount; ++i) { QSslEllipticCurve curve; curve.id = builtinCurves[int(i)].nid; @@ -824,11 +804,9 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates() void QSslSocketBackendPrivate::startClientEncryption() { - Q_Q(QSslSocket); if (!initSslContext()) { - q->setErrorString(QSslSocket::tr("Unable to init SSL Context: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Unable to init SSL Context: %1").arg(getErrorsFromOpenSsl())); return; } @@ -840,11 +818,9 @@ void QSslSocketBackendPrivate::startClientEncryption() void QSslSocketBackendPrivate::startServerEncryption() { - Q_Q(QSslSocket); if (!initSslContext()) { - q->setErrorString(QSslSocket::tr("Unable to init SSL Context: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Unable to init SSL Context: %1").arg(getErrorsFromOpenSsl())); return; } @@ -890,9 +866,9 @@ void QSslSocketBackendPrivate::transmit() break; } else { // ### Better error handling. - q->setErrorString(QSslSocket::tr("Unable to write data: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Unable to write data: %1").arg( + getErrorsFromOpenSsl())); return; } } @@ -934,9 +910,7 @@ void QSslSocketBackendPrivate::transmit() #endif if (actualWritten < 0) { //plain socket write fails if it was in the pending close state. - q->setErrorString(plainSocket->errorString()); - q->setSocketError(plainSocket->error()); - emit q->error(plainSocket->error()); + setErrorAndEmit(plainSocket->error(), plainSocket->errorString()); return; } transmitting = true; @@ -962,9 +936,9 @@ void QSslSocketBackendPrivate::transmit() plainSocket->read(data.data(), writtenToBio); } else { // ### Better error handling. - q->setErrorString(QSslSocket::tr("Unable to decrypt data: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Unable to decrypt data: %1").arg( + getErrorsFromOpenSsl())); return; } @@ -1038,17 +1012,15 @@ void QSslSocketBackendPrivate::transmit() qCDebug(lcSsl) << "QSslSocketBackendPrivate::transmit: remote disconnect"; #endif shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves - q->setErrorString(QSslSocket::tr("The TLS/SSL connection has been closed")); - q->setSocketError(QAbstractSocket::RemoteHostClosedError); - emit q->error(QAbstractSocket::RemoteHostClosedError); + setErrorAndEmit(QAbstractSocket::RemoteHostClosedError, + QSslSocket::tr("The TLS/SSL connection has been closed")); return; case SSL_ERROR_SYSCALL: // some IO error case SSL_ERROR_SSL: // error in the SSL library // we do not know exactly what the error is, nor whether we can recover from it, // so just return to prevent an endless loop in the outer "while" statement - q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl())); return; default: // SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: can only happen with a @@ -1056,9 +1028,8 @@ void QSslSocketBackendPrivate::transmit() // SSL_ERROR_WANT_X509_LOOKUP: can only happen with a // SSL_CTX_set_client_cert_cb(), which we do not call. // So this default case should never be triggered. - q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl())); break; } } while (ssl && readBytes > 0); @@ -1150,12 +1121,12 @@ bool QSslSocketBackendPrivate::startHandshake() // The handshake is not yet complete. break; default: - q->setErrorString(QSslSocket::tr("Error during SSL handshake: %1").arg(getErrorsFromOpenSsl())); - q->setSocketError(QAbstractSocket::SslHandshakeFailedError); + QString errorString + = QSslSocket::tr("Error during SSL handshake: %1").arg(getErrorsFromOpenSsl()); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << "QSslSocketBackendPrivate::startHandshake: error!" << q->errorString(); + qCDebug(lcSsl) << "QSslSocketBackendPrivate::startHandshake: error!" << errorString; #endif - emit q->error(QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, errorString); q->abort(); } return false; @@ -1213,7 +1184,9 @@ bool QSslSocketBackendPrivate::startHandshake() } // Translate errors from the error list into QSslErrors. - for (int i = 0; i < errorList.size(); ++i) { + const int numErrors = errorList.size(); + errors.reserve(errors.size() + numErrors); + for (int i = 0; i < numErrors; ++i) { const QPair<int, int> &errorAndDepth = errorList.at(i); int err = errorAndDepth.first; int depth = errorAndDepth.second; @@ -1304,9 +1277,7 @@ bool QSslSocketBackendPrivate::checkSslErrors() pauseSocketNotifiers(q); paused = true; } else { - q->setErrorString(sslErrors.first().errorString()); - q->setSocketError(QAbstractSocket::SslHandshakeFailedError); - emit q->error(QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.first().errorString()); plainSocket->disconnectFromHost(); } return false; @@ -1782,7 +1753,9 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> & } // Translate errors from the error list into QSslErrors. - for (int i = 0; i < errorList.size(); ++i) { + const int numErrors = errorList.size(); + errors.reserve(errors.size() + numErrors); + for (int i = 0; i < numErrors; ++i) { const QPair<int, int> &errorAndDepth = errorList.at(i); int err = errorAndDepth.first; int depth = errorAndDepth.second; diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index e2700df3cc..e7829bac90 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -119,10 +119,13 @@ void qsslSocketUnresolvedSymbolWarning(const char *functionName) qCWarning(lcSsl, "QSslSocket: cannot call unresolved function %s", functionName); } +#ifndef QT_NO_LIBRARY void qsslSocketCannotResolveSymbolWarning(const char *functionName) { qCWarning(lcSsl, "QSslSocket: cannot resolve %s", functionName); } +#endif + } #endif // QT_LINKED_OPENSSL @@ -156,7 +159,16 @@ DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return 0, return) DEFINEFUNC(unsigned long, ERR_get_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) +DEFINEFUNC4(int, EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX *ctx, ctx, int type, type, int arg, arg, void *ptr, ptr, return 0, return); +DEFINEFUNC2(int, EVP_CIPHER_CTX_set_key_length, EVP_CIPHER_CTX *ctx, ctx, int keylen, keylen, return 0, return) +DEFINEFUNC5(int, EVP_CipherInit, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *type, type, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return); +DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return); +DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return); +DEFINEFUNC(const EVP_CIPHER *, EVP_des_cbc, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const EVP_CIPHER *, EVP_rc2_cbc, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return) DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return) DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return) @@ -309,13 +321,17 @@ DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return 0, return) #endif #else +#ifndef OPENSSL_NO_SSL2 DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return) +#endif #ifndef OPENSSL_NO_SSL3_METHOD DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return) #endif DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return) +#ifndef OPENSSL_NO_SSL2 DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return) +#endif #ifndef OPENSSL_NO_SSL3_METHOD DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return) #endif @@ -436,39 +452,41 @@ bool q_resolveOpenSslSymbols() #else # ifdef Q_OS_UNIX -static bool libGreaterThan(const QString &lhs, const QString &rhs) +struct NumericallyLess { - QStringList lhsparts = lhs.split(QLatin1Char('.')); - QStringList rhsparts = rhs.split(QLatin1Char('.')); - Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1); - - for (int i = 1; i < rhsparts.count(); ++i) { - if (lhsparts.count() <= i) - // left hand side is shorter, so it's less than rhs - return false; - + typedef bool result_type; + result_type operator()(const QStringRef &lhs, const QStringRef &rhs) const + { bool ok = false; int b = 0; - int a = lhsparts.at(i).toInt(&ok); + int a = lhs.toInt(&ok); if (ok) - b = rhsparts.at(i).toInt(&ok); + b = rhs.toInt(&ok); if (ok) { // both toInt succeeded - if (a == b) - continue; - return a > b; + return a < b; } else { // compare as strings; - if (lhsparts.at(i) == rhsparts.at(i)) - continue; - return lhsparts.at(i) > rhsparts.at(i); + return lhs < rhs; } } +}; - // they compared strictly equally so far - // lhs cannot be less than rhs - return true; -} +struct LibGreaterThan +{ + typedef bool result_type; + result_type operator()(const QString &lhs, const QString &rhs) const + { + const QVector<QStringRef> lhsparts = lhs.splitRef(QLatin1Char('.')); + const QVector<QStringRef> rhsparts = rhs.splitRef(QLatin1Char('.')); + Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1); + + // note: checking rhs < lhs, the same as lhs > rhs + return std::lexicographical_compare(rhsparts.begin() + 1, rhsparts.end(), + lhsparts.begin() + 1, lhsparts.end(), + NumericallyLess()); + } +}; #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) static int dlIterateCallback(struct dl_phdr_info *info, size_t size, void *data) @@ -522,39 +540,33 @@ static QStringList libraryPathList() return paths; } - -static QStringList findAllLibSsl() +Q_NEVER_INLINE +static QStringList findAllLibs(QLatin1String filter) { QStringList paths = libraryPathList(); - QStringList foundSsls; + QStringList found; + const QStringList filters((QString(filter))); foreach (const QString &path, paths) { QDir dir(path); - QStringList entryList = dir.entryList(QStringList() << QLatin1String("libssl.*"), QDir::Files); + QStringList entryList = dir.entryList(filters, QDir::Files); - std::sort(entryList.begin(), entryList.end(), libGreaterThan); + std::sort(entryList.begin(), entryList.end(), LibGreaterThan()); foreach (const QString &entry, entryList) - foundSsls << path + QLatin1Char('/') + entry; + found << path + QLatin1Char('/') + entry; } - return foundSsls; + return found; } -static QStringList findAllLibCrypto() +static QStringList findAllLibSsl() { - QStringList paths = libraryPathList(); - - QStringList foundCryptos; - foreach (const QString &path, paths) { - QDir dir(path); - QStringList entryList = dir.entryList(QStringList() << QLatin1String("libcrypto.*"), QDir::Files); - - std::sort(entryList.begin(), entryList.end(), libGreaterThan); - foreach (const QString &entry, entryList) - foundCryptos << path + QLatin1Char('/') + entry; - } + return findAllLibs(QLatin1String("libssl.*")); +} - return foundCryptos; +static QStringList findAllLibCrypto() +{ + return findAllLibs(QLatin1String("libcrypto.*")); } # endif @@ -759,7 +771,16 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(ERR_error_string) RESOLVEFUNC(ERR_get_error) RESOLVEFUNC(ERR_free_strings) + RESOLVEFUNC(EVP_CIPHER_CTX_cleanup) + RESOLVEFUNC(EVP_CIPHER_CTX_init) + RESOLVEFUNC(EVP_CIPHER_CTX_ctrl) + RESOLVEFUNC(EVP_CIPHER_CTX_set_key_length) + RESOLVEFUNC(EVP_CipherInit) + RESOLVEFUNC(EVP_CipherUpdate) + RESOLVEFUNC(EVP_CipherFinal) + RESOLVEFUNC(EVP_des_cbc) RESOLVEFUNC(EVP_des_ede3_cbc) + RESOLVEFUNC(EVP_rc2_cbc) RESOLVEFUNC(EVP_PKEY_assign) RESOLVEFUNC(EVP_PKEY_set1_RSA) RESOLVEFUNC(EVP_PKEY_set1_DSA) diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index 626c049629..7f87f11b7c 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -235,7 +235,16 @@ X509 *q_d2i_X509(X509 **a, const unsigned char **b, long c); char *q_ERR_error_string(unsigned long a, char *b); unsigned long q_ERR_get_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); +int q_EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); +int q_EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen); +int q_EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned char *key, const unsigned char *iv, int enc); +int q_EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl); +int q_EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); +const EVP_CIPHER *q_EVP_des_cbc(); const EVP_CIPHER *q_EVP_des_ede3_cbc(); +const EVP_CIPHER *q_EVP_rc2_cbc(); 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); int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b); @@ -363,27 +372,43 @@ typedef unsigned int (*q_psk_client_callback_t)(SSL *ssl, const char *hint, char void q_SSL_set_psk_client_callback(SSL *ssl, q_psk_client_callback_t callback); #endif // OPENSSL_NO_PSK #if OPENSSL_VERSION_NUMBER >= 0x10000000L +#ifndef OPENSSL_NO_SSL2 const SSL_METHOD *q_SSLv2_client_method(); +#endif +#ifndef OPENSSL_NO_SSL3_METHOD const SSL_METHOD *q_SSLv3_client_method(); +#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(); +#ifndef OPENSSL_NO_SSL2 const SSL_METHOD *q_SSLv2_server_method(); +#endif +#ifndef OPENSSL_NO_SSL3_METHOD const SSL_METHOD *q_SSLv3_server_method(); +#endif 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(); #else +#ifndef OPENSSL_NO_SSL2 SSL_METHOD *q_SSLv2_client_method(); +#endif +#ifndef OPENSSL_NO_SSL3_METHOD SSL_METHOD *q_SSLv3_client_method(); +#endif SSL_METHOD *q_SSLv23_client_method(); SSL_METHOD *q_TLSv1_client_method(); SSL_METHOD *q_TLSv1_1_client_method(); SSL_METHOD *q_TLSv1_2_client_method(); +#ifndef OPENSSL_NO_SSL2 SSL_METHOD *q_SSLv2_server_method(); +#endif +#ifndef OPENSSL_NO_SSL3_METHOD SSL_METHOD *q_SSLv3_server_method(); +#endif SSL_METHOD *q_SSLv23_server_method(); SSL_METHOD *q_TLSv1_server_method(); SSL_METHOD *q_TLSv1_1_server_method(); diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp index aba3ea8170..b03f234d49 100644 --- a/src/network/ssl/qsslsocket_winrt.cpp +++ b/src/network/ssl/qsslsocket_winrt.cpp @@ -251,9 +251,8 @@ void QSslSocketBackendPrivate::startClientEncryption() case QSsl::TlsV1_2OrLater: // TlsV1_0OrLater, TlsV1_1OrLater and TlsV1_2OrLater are disabled on WinRT // because there is no good way to map them to the native API. - q->setErrorString(QStringLiteral("unsupported protocol")); - q->setSocketError(QAbstractSocket::SslInvalidUserDataError); - emit q->error(QAbstractSocket::SslInvalidUserDataError); + setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError, + QStringLiteral("unsupported protocol")); return; default: protectionLevel = SocketProtectionLevel_Tls12; // default to highest @@ -347,13 +346,10 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const void QSslSocketBackendPrivate::continueHandshake() { - Q_Q(QSslSocket); - IStreamSocket *socket = reinterpret_cast<IStreamSocket *>(plainSocket->socketDescriptor()); if (qintptr(socket) == -1) { - q->setErrorString(QStringLiteral("At attempt was made to continue the handshake on an invalid socket.")); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QStringLiteral("At attempt was made to continue the handshake on an invalid socket.")); return; } @@ -372,9 +368,7 @@ void QSslSocketBackendPrivate::continueHandshake() Q_ASSERT_SUCCEEDED(hr); } if (FAILED(hr)) { - q->setErrorString(qt_error_string(hr)); - q->setSocketError(QAbstractSocket::SslInvalidUserDataError); - emit q->error(QAbstractSocket::SslInvalidUserDataError); + setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError, qt_error_string(hr)); return; } @@ -440,10 +434,8 @@ void QSslSocketBackendPrivate::continueHandshake() ComPtr<IAsyncAction> op; hr = socket->UpgradeToSslAsync(protectionLevel, hostName.Get(), &op); if (FAILED(hr)) { - q->setErrorString(QSslSocket::tr("Error creating SSL session: %1") - .arg(qt_error_string(hr))); - q->setSocketError(QAbstractSocket::SslInternalError); - emit q->error(QAbstractSocket::SslInternalError); + setErrorAndEmit(QAbstractSocket::SslInternalError, + QSslSocket::tr("Error creating SSL session: %1").arg(qt_error_string(hr))); return; } @@ -467,9 +459,7 @@ HRESULT QSslSocketBackendPrivate::onSslUpgrade(IAsyncAction *action, AsyncStatus QSet<QSslError> errors; switch (hr) { case SEC_E_INVALID_TOKEN: // Occurs when the server doesn't support the requested protocol - q->setErrorString(qt_error_string(hr)); - q->setSocketError(QAbstractSocket::SslHandshakeFailedError); - emit q->error(QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, qt_error_string(hr)); q->disconnectFromHost(); return S_OK; default: @@ -628,9 +618,7 @@ HRESULT QSslSocketBackendPrivate::onSslUpgrade(IAsyncAction *action, AsyncStatus if (!sslErrors.isEmpty()) { emit q->sslErrors(sslErrors); - q->setErrorString(sslErrors.first().errorString()); - q->setSocketError(QAbstractSocket::SslHandshakeFailedError); - emit q->error(QAbstractSocket::SslHandshakeFailedError); + setErrorAndEmit(QAbstractSocket::SslHandshakeFailedError, sslErrors.first().errorString()); // Disconnect if there are any non-ignorable errors foreach (const QSslError &error, sslErrors) { |