summaryrefslogtreecommitdiffstats
path: root/src/network/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/ssl')
-rw-r--r--src/network/ssl/qssl.cpp4
-rw-r--r--src/network/ssl/qssl.h3
-rw-r--r--src/network/ssl/qsslcertificate.h7
-rw-r--r--src/network/ssl/qsslcertificate_openssl.cpp3
-rw-r--r--src/network/ssl/qsslcertificateextension.h8
-rw-r--r--src/network/ssl/qsslcipher.h7
-rw-r--r--src/network/ssl/qsslconfiguration.h5
-rw-r--r--src/network/ssl/qsslellipticcurve.h3
-rw-r--r--src/network/ssl/qsslerror.h5
-rw-r--r--src/network/ssl/qsslkey.h7
-rw-r--r--src/network/ssl/qsslkey_openssl.cpp49
-rw-r--r--src/network/ssl/qsslkey_p.h19
-rw-r--r--src/network/ssl/qsslpresharedkeyauthenticator.h8
-rw-r--r--src/network/ssl/qsslpresharedkeyauthenticator_p.h11
-rw-r--r--src/network/ssl/qsslsocket.cpp21
-rw-r--r--src/network/ssl/qsslsocket.h2
-rw-r--r--src/network/ssl/qsslsocket_mac.cpp74
-rw-r--r--src/network/ssl/qsslsocket_mac_p.h7
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp113
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp105
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h25
-rw-r--r--src/network/ssl/qsslsocket_winrt.cpp30
22 files changed, 293 insertions, 223 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.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 092a414f99..b62cfd2fde 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());
@@ -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..0a4c68d7c0 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -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) {