diff options
Diffstat (limited to 'tests/auto/qsslsocket/tst_qsslsocket.cpp')
-rw-r--r-- | tests/auto/qsslsocket/tst_qsslsocket.cpp | 2095 |
1 files changed, 0 insertions, 2095 deletions
diff --git a/tests/auto/qsslsocket/tst_qsslsocket.cpp b/tests/auto/qsslsocket/tst_qsslsocket.cpp deleted file mode 100644 index 4ffcba6e65..0000000000 --- a/tests/auto/qsslsocket/tst_qsslsocket.cpp +++ /dev/null @@ -1,2095 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtCore/qthread.h> -#include <QtNetwork/qhostaddress.h> -#include <QtNetwork/qhostinfo.h> -#include <QtNetwork/qnetworkproxy.h> -#include <QtNetwork/qsslcipher.h> -#include <QtNetwork/qsslconfiguration.h> -#include <QtNetwork/qsslkey.h> -#include <QtNetwork/qsslsocket.h> -#include <QtNetwork/qtcpserver.h> -#include <QtTest/QtTest> - -#include <QNetworkProxy> -#include <QAuthenticator> - -#include "private/qhostinfo_p.h" -#include "private/qsslsocket_openssl_p.h" -#include "private/qsslsocket_openssl_symbols_p.h" - -#include "../network-settings.h" - -Q_DECLARE_METATYPE(QAbstractSocket::SocketState) -Q_DECLARE_METATYPE(QAbstractSocket::SocketError) -#ifndef QT_NO_OPENSSL -Q_DECLARE_METATYPE(QSslSocket::SslMode) -typedef QList<QSslError::SslError> SslErrorList; -Q_DECLARE_METATYPE(SslErrorList) -Q_DECLARE_METATYPE(QSslError) -Q_DECLARE_METATYPE(QSsl::SslProtocol) -Q_DECLARE_METATYPE(QSslConfiguration) -#endif - -#if defined Q_OS_HPUX && defined Q_CC_GNU -// This error is delivered every time we try to use the fluke CA -// certificate. For now we work around this bug. Task 202317. -#define QSSLSOCKET_CERTUNTRUSTED_WORKAROUND -#endif - -#ifdef Q_OS_SYMBIAN -#define SRCDIR "" -#endif - -#ifndef QT_NO_OPENSSL -class QSslSocketPtr: public QSharedPointer<QSslSocket> -{ -public: - inline QSslSocketPtr(QSslSocket *ptr = 0) - : QSharedPointer<QSslSocket>(ptr) - { } - - inline operator QSslSocket *() const { return data(); } -}; -#endif - -class tst_QSslSocket : public QObject -{ - Q_OBJECT - - int proxyAuthCalled; - -public: - tst_QSslSocket(); - virtual ~tst_QSslSocket(); - - static void enterLoop(int secs) - { - ++loopLevel; - QTestEventLoop::instance().enterLoop(secs); - } - - static bool timeout() - { - return QTestEventLoop::instance().timeout(); - } - -#ifndef QT_NO_OPENSSL - QSslSocketPtr newSocket(); -#endif - -public slots: - void initTestCase_data(); - void init(); - void cleanup(); - void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth); - -#ifndef QT_NO_OPENSSL -private slots: - void constructing(); - void simpleConnect(); - void simpleConnectWithIgnore(); - - // API tests - void sslErrors_data(); - void sslErrors(); - void addCaCertificate(); - void addCaCertificates(); - void addCaCertificates2(); - void ciphers(); - void connectToHostEncrypted(); - void connectToHostEncryptedWithVerificationPeerName(); - void sessionCipher(); - void flush(); - void isEncrypted(); - void localCertificate(); - void mode(); - void peerCertificate(); - void peerCertificateChain(); - void privateKey(); - void privateKeyOpaque(); - void protocol(); - void protocolServerSide_data(); - void protocolServerSide(); - void setCaCertificates(); - void setLocalCertificate(); - void setPrivateKey(); - void setSocketDescriptor(); - void setSslConfiguration_data(); - void setSslConfiguration(); - void waitForEncrypted(); - void waitForEncryptedMinusOne(); - void waitForConnectedEncryptedReadyRead(); - void startClientEncryption(); - void startServerEncryption(); - void addDefaultCaCertificate(); - void addDefaultCaCertificates(); - void addDefaultCaCertificates2(); - void defaultCaCertificates(); - void defaultCiphers(); - void resetDefaultCiphers(); - void setDefaultCaCertificates(); - void setDefaultCiphers(); - void supportedCiphers(); - void systemCaCertificates(); - void wildcardCertificateNames(); - void wildcard(); - void setEmptyKey(); - void spontaneousWrite(); - void setReadBufferSize(); - void setReadBufferSize_task_250027(); - void waitForMinusOne(); - void verifyMode(); - void verifyDepth(); - void peerVerifyError(); - void disconnectFromHostWhenConnecting(); - void disconnectFromHostWhenConnected(); - void resetProxy(); - void ignoreSslErrorsList_data(); - void ignoreSslErrorsList(); - void ignoreSslErrorsListWithSlot_data(); - void ignoreSslErrorsListWithSlot(); - void readFromClosedSocket(); - void writeBigChunk(); - void blacklistedCertificates(); - void setEmptyDefaultConfiguration(); - void versionAccessors(); - - static void exitLoop() - { - // Safe exit - if we aren't in an event loop, don't - // exit one. - if (loopLevel > 0) { - --loopLevel; - QTestEventLoop::instance().exitLoop(); - } - } - -protected slots: - void ignoreErrorSlot() - { - socket->ignoreSslErrors(); - } - void untrustedWorkaroundSlot(const QList<QSslError> &errors) - { - if (errors.size() == 1 && - (errors.first().error() == QSslError::CertificateUntrusted || - errors.first().error() == QSslError::SelfSignedCertificate)) - socket->ignoreSslErrors(); - } - void ignoreErrorListSlot(const QList<QSslError> &errors); - -private: - QSslSocket *socket; - QList<QSslError> storedExpectedSslErrors; -#endif // QT_NO_OPENSSL -private: - static int loopLevel; -}; - -int tst_QSslSocket::loopLevel = 0; - -tst_QSslSocket::tst_QSslSocket() -{ -#ifndef QT_NO_OPENSSL - qRegisterMetaType<QList<QSslError> >("QList<QSslError>"); - qRegisterMetaType<QSslError>("QSslError"); - qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState"); - qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError"); - qRegisterMetaType<QAbstractSocket::SocketState>("QSslSocket::SslMode"); -#endif - Q_SET_DEFAULT_IAP -} - -tst_QSslSocket::~tst_QSslSocket() -{ -} - -enum ProxyTests { - NoProxy = 0x00, - Socks5Proxy = 0x01, - HttpProxy = 0x02, - TypeMask = 0x0f, - - NoAuth = 0x00, - AuthBasic = 0x10, - AuthNtlm = 0x20, - AuthMask = 0xf0 -}; - -void tst_QSslSocket::initTestCase_data() -{ - QTest::addColumn<bool>("setProxy"); - QTest::addColumn<int>("proxyType"); - - QTest::newRow("WithoutProxy") << false << 0; - QTest::newRow("WithSocks5Proxy") << true << int(Socks5Proxy); - QTest::newRow("WithSocks5ProxyAuth") << true << int(Socks5Proxy | AuthBasic); - - QTest::newRow("WithHttpProxy") << true << int(HttpProxy); - QTest::newRow("WithHttpProxyBasicAuth") << true << int(HttpProxy | AuthBasic); - // uncomment the line below when NTLM works -// QTest::newRow("WithHttpProxyNtlmAuth") << true << int(HttpProxy | AuthNtlm); -} - -void tst_QSslSocket::init() -{ - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) { - QFETCH_GLOBAL(int, proxyType); - QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(); - QNetworkProxy proxy; - - switch (proxyType) { - case Socks5Proxy: - proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1080); - break; - - case Socks5Proxy | AuthBasic: - proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1081); - break; - - case HttpProxy | NoAuth: - proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3128); - break; - - case HttpProxy | AuthBasic: - proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3129); - break; - - case HttpProxy | AuthNtlm: - proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3130); - break; - } - QNetworkProxy::setApplicationProxy(proxy); - } - - qt_qhostinfo_clear_cache(); -} - -void tst_QSslSocket::cleanup() -{ - QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy); -} - -#ifndef QT_NO_OPENSSL -QSslSocketPtr tst_QSslSocket::newSocket() -{ - QSslSocket *socket = new QSslSocket; - - proxyAuthCalled = 0; - connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), - SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), - Qt::DirectConnection); - - return QSslSocketPtr(socket); -} -#endif - -void tst_QSslSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth) -{ - ++proxyAuthCalled; - auth->setUser("qsockstest"); - auth->setPassword("password"); -} - -#ifndef QT_NO_OPENSSL - -void tst_QSslSocket::constructing() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocket socket; - - QCOMPARE(socket.state(), QSslSocket::UnconnectedState); - QCOMPARE(socket.mode(), QSslSocket::UnencryptedMode); - QVERIFY(!socket.isEncrypted()); - QCOMPARE(socket.bytesAvailable(), qint64(0)); - QCOMPARE(socket.bytesToWrite(), qint64(0)); - QVERIFY(!socket.canReadLine()); - QVERIFY(socket.atEnd()); - QCOMPARE(socket.localCertificate(), QSslCertificate()); - QCOMPARE(socket.sslConfiguration(), QSslConfiguration::defaultConfiguration()); - QCOMPARE(socket.errorString(), QString("Unknown error")); - char c = '\0'; - QVERIFY(!socket.getChar(&c)); - QCOMPARE(c, '\0'); - QVERIFY(!socket.isOpen()); - QVERIFY(!socket.isReadable()); - QVERIFY(socket.isSequential()); - QVERIFY(!socket.isTextModeEnabled()); - QVERIFY(!socket.isWritable()); - QCOMPARE(socket.openMode(), QIODevice::NotOpen); - QVERIFY(socket.peek(2).isEmpty()); - QCOMPARE(socket.pos(), qint64(0)); - QVERIFY(!socket.putChar('c')); - QVERIFY(socket.read(2).isEmpty()); - QCOMPARE(socket.read(0, 0), qint64(-1)); - QVERIFY(socket.readAll().isEmpty()); - QTest::ignoreMessage(QtWarningMsg, "QIODevice::readLine: Called with maxSize < 2"); - QCOMPARE(socket.readLine(0, 0), qint64(-1)); - char buf[10]; - QCOMPARE(socket.readLine(buf, sizeof(buf)), qint64(-1)); - QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek: The device is not open"); - QVERIFY(!socket.reset()); - QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek: The device is not open"); - QVERIFY(!socket.seek(2)); - QCOMPARE(socket.size(), qint64(0)); - QVERIFY(!socket.waitForBytesWritten(10)); - QVERIFY(!socket.waitForReadyRead(10)); - QCOMPARE(socket.write(0, 0), qint64(-1)); - QCOMPARE(socket.write(QByteArray()), qint64(-1)); - QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError); - QVERIFY(!socket.flush()); - QVERIFY(!socket.isValid()); - QCOMPARE(socket.localAddress(), QHostAddress()); - QCOMPARE(socket.localPort(), quint16(0)); - QCOMPARE(socket.peerAddress(), QHostAddress()); - QVERIFY(socket.peerName().isEmpty()); - QCOMPARE(socket.peerPort(), quint16(0)); - QCOMPARE(socket.proxy().type(), QNetworkProxy::DefaultProxy); - QCOMPARE(socket.readBufferSize(), qint64(0)); - QCOMPARE(socket.socketDescriptor(), -1); - QCOMPARE(socket.socketType(), QAbstractSocket::TcpSocket); - QVERIFY(!socket.waitForConnected(10)); - QTest::ignoreMessage(QtWarningMsg, "QSslSocket::waitForDisconnected() is not allowed in UnconnectedState"); - QVERIFY(!socket.waitForDisconnected(10)); - QCOMPARE(socket.protocol(), QSsl::SecureProtocols); - - QSslConfiguration savedDefault = QSslConfiguration::defaultConfiguration(); - - // verify that changing the default config doesn't affect this socket - // (on Unix, the ca certs might be empty, depending on whether we load - // them on demand or not, so set them explicitly) - socket.setCaCertificates(QSslSocket::systemCaCertificates()); - QSslSocket::setDefaultCaCertificates(QList<QSslCertificate>()); - QSslSocket::setDefaultCiphers(QList<QSslCipher>()); - QVERIFY(!socket.caCertificates().isEmpty()); - QVERIFY(!socket.ciphers().isEmpty()); - - // verify the default as well: - QVERIFY(QSslConfiguration::defaultConfiguration().caCertificates().isEmpty()); - QVERIFY(QSslConfiguration::defaultConfiguration().ciphers().isEmpty()); - - QSslConfiguration::setDefaultConfiguration(savedDefault); -} - -void tst_QSslSocket::simpleConnect() -{ - if (!QSslSocket::supportsSsl()) - return; - - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) - return; - - QSslSocket socket; - QSignalSpy connectedSpy(&socket, SIGNAL(connected())); - QSignalSpy hostFoundSpy(&socket, SIGNAL(hostFound())); - QSignalSpy disconnectedSpy(&socket, SIGNAL(disconnected())); - QSignalSpy connectionEncryptedSpy(&socket, SIGNAL(encrypted())); - QSignalSpy sslErrorsSpy(&socket, SIGNAL(sslErrors(const QList<QSslError> &))); - - connect(&socket, SIGNAL(connected()), this, SLOT(exitLoop())); - connect(&socket, SIGNAL(disconnected()), this, SLOT(exitLoop())); - connect(&socket, SIGNAL(modeChanged(QSslSocket::SslMode)), this, SLOT(exitLoop())); - connect(&socket, SIGNAL(encrypted()), this, SLOT(exitLoop())); - connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(exitLoop())); - connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(exitLoop())); - - // Start connecting - socket.connectToHost(QtNetworkSettings::serverName(), 993); - QCOMPARE(socket.state(), QAbstractSocket::HostLookupState); - enterLoop(10); - - // Entered connecting state -#ifndef Q_OS_SYMBIAN - QCOMPARE(socket.state(), QAbstractSocket::ConnectingState); - QCOMPARE(connectedSpy.count(), 0); -#endif - QCOMPARE(hostFoundSpy.count(), 1); - QCOMPARE(disconnectedSpy.count(), 0); - enterLoop(10); - - // Entered connected state - QCOMPARE(socket.state(), QAbstractSocket::ConnectedState); - QCOMPARE(socket.mode(), QSslSocket::UnencryptedMode); - QVERIFY(!socket.isEncrypted()); - QCOMPARE(connectedSpy.count(), 1); - QCOMPARE(hostFoundSpy.count(), 1); - QCOMPARE(disconnectedSpy.count(), 0); - - // Enter encrypted mode - socket.startClientEncryption(); - QCOMPARE(socket.mode(), QSslSocket::SslClientMode); - QVERIFY(!socket.isEncrypted()); - QCOMPARE(connectionEncryptedSpy.count(), 0); - QCOMPARE(sslErrorsSpy.count(), 0); - - // Starting handshake - enterLoop(10); - QCOMPARE(sslErrorsSpy.count(), 1); - QCOMPARE(connectionEncryptedSpy.count(), 0); - QVERIFY(!socket.isEncrypted()); - QCOMPARE(socket.state(), QAbstractSocket::UnconnectedState); -} - -void tst_QSslSocket::simpleConnectWithIgnore() -{ - if (!QSslSocket::supportsSsl()) - return; - - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) - return; - - QSslSocket socket; - this->socket = &socket; - QSignalSpy encryptedSpy(&socket, SIGNAL(encrypted())); - QSignalSpy sslErrorsSpy(&socket, SIGNAL(sslErrors(const QList<QSslError> &))); - - connect(&socket, SIGNAL(readyRead()), this, SLOT(exitLoop())); - connect(&socket, SIGNAL(encrypted()), this, SLOT(exitLoop())); - connect(&socket, SIGNAL(connected()), this, SLOT(exitLoop())); - connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); - connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(exitLoop())); - - // Start connecting - socket.connectToHost(QtNetworkSettings::serverName(), 993); - QVERIFY(socket.state() != QAbstractSocket::UnconnectedState); // something must be in progress - enterLoop(10); - - // Start handshake - QCOMPARE(socket.state(), QAbstractSocket::ConnectedState); - socket.startClientEncryption(); - enterLoop(10); - - // Done; encryption should be enabled. - QCOMPARE(sslErrorsSpy.count(), 1); - QVERIFY(socket.isEncrypted()); - QCOMPARE(socket.state(), QAbstractSocket::ConnectedState); - QCOMPARE(encryptedSpy.count(), 1); - - // Wait for incoming data - if (!socket.canReadLine()) - enterLoop(10); - - QByteArray data = socket.readAll(); - socket.disconnectFromHost(); - QVERIFY2(QtNetworkSettings::compareReplyIMAPSSL(data), data.constData()); -} - -void tst_QSslSocket::sslErrors_data() -{ - QTest::addColumn<QString>("host"); - QTest::addColumn<int>("port"); - QTest::addColumn<SslErrorList>("expected"); - - QTest::newRow(qPrintable(QtNetworkSettings::serverLocalName())) - << QtNetworkSettings::serverLocalName() - << 993 - << (SslErrorList() << QSslError::HostNameMismatch - << QSslError::SelfSignedCertificate); -} - -void tst_QSslSocket::sslErrors() -{ - QFETCH(QString, host); - QFETCH(int, port); - QFETCH(SslErrorList, expected); - - QSslSocketPtr socket = newSocket(); - socket->connectToHostEncrypted(host, port); - if (!socket->waitForConnected()) - QEXPECT_FAIL("imap.trolltech.com", "server not open to internet", Continue); - socket->waitForEncrypted(5000); - - SslErrorList output; - foreach (QSslError error, socket->sslErrors()) { - output << error.error(); - } - -#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND - if (output.count() && output.last() == QSslError::CertificateUntrusted) - output.takeLast(); -#endif - QCOMPARE(output, expected); -} - -void tst_QSslSocket::addCaCertificate() -{ - if (!QSslSocket::supportsSsl()) - return; -} - -void tst_QSslSocket::addCaCertificates() -{ - if (!QSslSocket::supportsSsl()) - return; -} - -void tst_QSslSocket::addCaCertificates2() -{ - if (!QSslSocket::supportsSsl()) - return; -} - -void tst_QSslSocket::ciphers() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocket socket; - QCOMPARE(socket.ciphers(), QSslSocket::supportedCiphers()); - socket.setCiphers(QList<QSslCipher>()); - QVERIFY(socket.ciphers().isEmpty()); - socket.setCiphers(socket.defaultCiphers()); - QCOMPARE(socket.ciphers(), QSslSocket::supportedCiphers()); - socket.setCiphers(socket.defaultCiphers()); - QCOMPARE(socket.ciphers(), QSslSocket::supportedCiphers()); - - // Task 164356 - socket.setCiphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); -} - -void tst_QSslSocket::connectToHostEncrypted() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocketPtr socket = newSocket(); - this->socket = socket; - QVERIFY(socket->addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"))); -#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND - connect(socket, SIGNAL(sslErrors(QList<QSslError>)), - this, SLOT(untrustedWorkaroundSlot(QList<QSslError>))); -#endif - - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - - // This should pass unconditionally when using fluke's CA certificate. - // or use untrusted certificate workaround - QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString())); - - socket->disconnectFromHost(); - QVERIFY(socket->waitForDisconnected()); - - QCOMPARE(socket->mode(), QSslSocket::SslClientMode); - - socket->connectToHost(QtNetworkSettings::serverName(), 13); - - QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode); - - QVERIFY(socket->waitForDisconnected()); -} - -void tst_QSslSocket::connectToHostEncryptedWithVerificationPeerName() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocketPtr socket = newSocket(); - this->socket = socket; - - socket->addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); -#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND - connect(socket, SIGNAL(sslErrors(QList<QSslError>)), - this, SLOT(untrustedWorkaroundSlot(QList<QSslError>))); -#endif - - // connect to the server with its local name, but use the full name for verification. - socket->connectToHostEncrypted(QtNetworkSettings::serverLocalName(), 443, QtNetworkSettings::serverName()); - - // This should pass unconditionally when using fluke's CA certificate. - QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString())); - - socket->disconnectFromHost(); - QVERIFY(socket->waitForDisconnected()); - - QCOMPARE(socket->mode(), QSslSocket::SslClientMode); -} - -void tst_QSslSocket::sessionCipher() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocketPtr socket = newSocket(); - this->socket = socket; - connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot())); - QVERIFY(socket->sessionCipher().isNull()); - socket->connectToHost(QtNetworkSettings::serverName(), 443 /* https */); - QVERIFY(socket->waitForConnected(10000)); - QVERIFY(socket->sessionCipher().isNull()); - socket->startClientEncryption(); - QVERIFY(socket->waitForEncrypted(5000)); - QVERIFY(!socket->sessionCipher().isNull()); - QVERIFY(QSslSocket::supportedCiphers().contains(socket->sessionCipher())); - socket->disconnectFromHost(); - QVERIFY(socket->waitForDisconnected()); -} - -void tst_QSslSocket::flush() -{ -} - -void tst_QSslSocket::isEncrypted() -{ -} - -void tst_QSslSocket::localCertificate() -{ - if (!QSslSocket::supportsSsl()) - return; - - // This test does not make 100% sense yet. We just set some local CA/cert/key and use it - // to authenticate ourselves against the server. The server does not actually check this - // values. This test should just run the codepath inside qsslsocket_openssl.cpp - - QSslSocketPtr socket = newSocket(); - QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"); - socket->setCaCertificates(localCert); - socket->setLocalCertificate(QLatin1String(SRCDIR "certs/fluke.cert")); - socket->setPrivateKey(QLatin1String(SRCDIR "certs/fluke.key")); - - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY(socket->waitForEncrypted(10000)); -} - -void tst_QSslSocket::mode() -{ -} - -void tst_QSslSocket::peerCertificate() -{ -} - -void tst_QSslSocket::peerCertificateChain() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocketPtr socket = newSocket(); - this->socket = socket; - - QList<QSslCertificate> caCertificates = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); - QVERIFY(caCertificates.count() == 1); - socket->addCaCertificates(caCertificates); -#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND - connect(socket, SIGNAL(sslErrors(QList<QSslError>)), - this, SLOT(untrustedWorkaroundSlot(QList<QSslError>))); -#endif - - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode); - QVERIFY(socket->peerCertificateChain().isEmpty()); - QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString())); - - QList<QSslCertificate> certChain = socket->peerCertificateChain(); - QVERIFY(certChain.count() > 0); - QCOMPARE(certChain.first(), socket->peerCertificate()); - - socket->disconnectFromHost(); - QVERIFY(socket->waitForDisconnected()); - - // connect again to a different server - socket->connectToHostEncrypted("trolltech.com", 443); - socket->ignoreSslErrors(); - QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode); - QVERIFY(socket->peerCertificateChain().isEmpty()); - QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString())); - - QCOMPARE(socket->peerCertificateChain().first(), socket->peerCertificate()); - QVERIFY(socket->peerCertificateChain() != certChain); - - socket->disconnectFromHost(); - QVERIFY(socket->waitForDisconnected()); - - // now do it again back to the original server - socket->connectToHost(QtNetworkSettings::serverName(), 443); - QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode); - QVERIFY(socket->peerCertificateChain().isEmpty()); - QVERIFY2(socket->waitForConnected(10000), "Network timeout"); - - socket->startClientEncryption(); - QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString())); - - QCOMPARE(socket->peerCertificateChain().first(), socket->peerCertificate()); - QVERIFY(socket->peerCertificateChain() == certChain); - - socket->disconnectFromHost(); - QVERIFY(socket->waitForDisconnected()); -} - -void tst_QSslSocket::privateKey() -{ -} - -void tst_QSslSocket::privateKeyOpaque() -{ - if (!QSslSocket::supportsSsl()) - return; - - QFile file(SRCDIR "certs/fluke.key"); - QVERIFY(file.open(QIODevice::ReadOnly)); - QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); - QVERIFY(!key.isNull()); - - EVP_PKEY *pkey = q_EVP_PKEY_new(); - q_EVP_PKEY_set1_RSA(pkey, reinterpret_cast<RSA *>(key.handle())); - - // This test does not make 100% sense yet. We just set some local CA/cert/key and use it - // to authenticate ourselves against the server. The server does not actually check this - // values. This test should just run the codepath inside qsslsocket_openssl.cpp - - QSslSocketPtr socket = newSocket(); - QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"); - socket->setCaCertificates(localCert); - socket->setLocalCertificate(QLatin1String(SRCDIR "certs/fluke.cert")); - socket->setPrivateKey(QSslKey(reinterpret_cast<Qt::HANDLE>(pkey))); - - socket->setPeerVerifyMode(QSslSocket::QueryPeer); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY(socket->waitForEncrypted(10000)); -} - -void tst_QSslSocket::protocol() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocketPtr socket = newSocket(); - this->socket = socket; - QList<QSslCertificate> certs = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"); - - socket->setCaCertificates(certs); -#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND - connect(socket, SIGNAL(sslErrors(QList<QSslError>)), - this, SLOT(untrustedWorkaroundSlot(QList<QSslError>))); -#endif - - QCOMPARE(socket->protocol(), QSsl::SecureProtocols); - { - // Fluke allows SSLv3. - socket->setProtocol(QSsl::SslV3); - QCOMPARE(socket->protocol(), QSsl::SslV3); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString())); - QCOMPARE(socket->protocol(), QSsl::SslV3); - socket->abort(); - QCOMPARE(socket->protocol(), QSsl::SslV3); - socket->connectToHost(QtNetworkSettings::serverName(), 443); - QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString())); - socket->startClientEncryption(); - QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString())); - QCOMPARE(socket->protocol(), QSsl::SslV3); - socket->abort(); - } - { - // Fluke allows TLSV1. - socket->setProtocol(QSsl::TlsV1); - QCOMPARE(socket->protocol(), QSsl::TlsV1); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString())); - QCOMPARE(socket->protocol(), QSsl::TlsV1); - socket->abort(); - QCOMPARE(socket->protocol(), QSsl::TlsV1); - socket->connectToHost(QtNetworkSettings::serverName(), 443); - QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString())); - socket->startClientEncryption(); - QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString())); - QCOMPARE(socket->protocol(), QSsl::TlsV1); - socket->abort(); - } - { - // Fluke allows SSLV2. - socket->setProtocol(QSsl::SslV2); - QCOMPARE(socket->protocol(), QSsl::SslV2); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY(socket->waitForEncrypted()); - QCOMPARE(socket->protocol(), QSsl::SslV2); - socket->abort(); - QCOMPARE(socket->protocol(), QSsl::SslV2); - socket->connectToHost(QtNetworkSettings::serverName(), 443); - QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString())); - socket->startClientEncryption(); - QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString())); - socket->abort(); - } - { - // Fluke allows SSLV3, so it allows AnyProtocol. - socket->setProtocol(QSsl::AnyProtocol); - QCOMPARE(socket->protocol(), QSsl::AnyProtocol); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY(socket->waitForEncrypted()); - QCOMPARE(socket->protocol(), QSsl::AnyProtocol); - socket->abort(); - QCOMPARE(socket->protocol(), QSsl::AnyProtocol); - socket->connectToHost(QtNetworkSettings::serverName(), 443); - QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString())); - socket->startClientEncryption(); - QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString())); - QCOMPARE(socket->protocol(), QSsl::AnyProtocol); - socket->abort(); - } - { - // Fluke allows SSLV3, so it allows NoSslV2 - socket->setProtocol(QSsl::TlsV1SslV3); - QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY(socket->waitForEncrypted()); - QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3); - socket->abort(); - QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3); - socket->connectToHost(QtNetworkSettings::serverName(), 443); - QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString())); - socket->startClientEncryption(); - QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString())); - QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3); - socket->abort(); - } -} - -class SslServer : public QTcpServer -{ - Q_OBJECT -public: - SslServer(const QString &keyFile = SRCDIR "certs/fluke.key", const QString &certFile = SRCDIR "certs/fluke.cert") - : socket(0), - protocol(QSsl::TlsV1), - m_keyFile(keyFile), - m_certFile(certFile) { } - QSslSocket *socket; - QSsl::SslProtocol protocol; - QString m_keyFile; - QString m_certFile; - -protected: - void incomingConnection(int socketDescriptor) - { - socket = new QSslSocket(this); - socket->setProtocol(protocol); - connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); - - QFile file(m_keyFile); - QVERIFY(file.open(QIODevice::ReadOnly)); - QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); - QVERIFY(!key.isNull()); - socket->setPrivateKey(key); - - QList<QSslCertificate> localCert = QSslCertificate::fromPath(m_certFile); - QVERIFY(!localCert.isEmpty()); - QVERIFY(localCert.first().handle()); - socket->setLocalCertificate(localCert.first()); - - QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState)); - QVERIFY(!socket->peerAddress().isNull()); - QVERIFY(socket->peerPort() != 0); - QVERIFY(!socket->localAddress().isNull()); - QVERIFY(socket->localPort() != 0); - - socket->startServerEncryption(); - } - -protected slots: - void ignoreErrorSlot() - { - socket->ignoreSslErrors(); - } -}; - -void tst_QSslSocket::protocolServerSide_data() -{ - - QTest::addColumn<QSsl::SslProtocol>("serverProtocol"); - QTest::addColumn<QSsl::SslProtocol>("clientProtocol"); - QTest::addColumn<bool>("works"); - - QTest::newRow("ssl2-ssl2") << QSsl::SslV2 << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2 - QTest::newRow("ssl3-ssl3") << QSsl::SslV3 << QSsl::SslV3 << true; - QTest::newRow("tls1-tls1") << QSsl::TlsV1 << QSsl::TlsV1 << true; - QTest::newRow("tls1ssl3-tls1ssl3") << QSsl::TlsV1SslV3 << QSsl::TlsV1SslV3 << true; - QTest::newRow("any-any") << QSsl::AnyProtocol << QSsl::AnyProtocol << true; - QTest::newRow("secure-secure") << QSsl::SecureProtocols << QSsl::SecureProtocols << true; - - QTest::newRow("ssl2-ssl3") << QSsl::SslV2 << QSsl::SslV3 << false; - QTest::newRow("ssl2-tls1") << QSsl::SslV2 << QSsl::TlsV1 << false; - QTest::newRow("ssl2-tls1ssl3") << QSsl::SslV2 << QSsl::TlsV1SslV3 << false; - QTest::newRow("ssl2-secure") << QSsl::SslV2 << QSsl::SecureProtocols << false; - QTest::newRow("ssl2-any") << QSsl::SslV2 << QSsl::AnyProtocol << false; // no idea why it does not work, but we don't care about SSL 2 - - QTest::newRow("ssl3-ssl2") << QSsl::SslV3 << QSsl::SslV2 << false; - QTest::newRow("ssl3-tls1") << QSsl::SslV3 << QSsl::TlsV1 << false; - QTest::newRow("ssl3-tls1ssl3") << QSsl::SslV3 << QSsl::TlsV1SslV3 << true; - QTest::newRow("ssl3-secure") << QSsl::SslV3 << QSsl::SecureProtocols << true; - QTest::newRow("ssl3-any") << QSsl::SslV3 << QSsl::AnyProtocol << false; // we wont set a SNI header here because we connect to a - // numerical IP, so OpenSSL will send a SSL 2 handshake - - QTest::newRow("tls1-ssl2") << QSsl::TlsV1 << QSsl::SslV2 << false; - QTest::newRow("tls1-ssl3") << QSsl::TlsV1 << QSsl::SslV3 << false; - QTest::newRow("tls1-tls1ssl3") << QSsl::TlsV1 << QSsl::TlsV1SslV3 << true; - QTest::newRow("tls1-secure") << QSsl::TlsV1 << QSsl::SecureProtocols << true; - QTest::newRow("tls1-any") << QSsl::TlsV1 << QSsl::AnyProtocol << false; // we wont set a SNI header here because we connect to a - // numerical IP, so OpenSSL will send a SSL 2 handshake - - QTest::newRow("tls1ssl3-ssl2") << QSsl::TlsV1SslV3 << QSsl::SslV2 << false; - QTest::newRow("tls1ssl3-ssl3") << QSsl::TlsV1SslV3 << QSsl::SslV3 << true; - QTest::newRow("tls1ssl3-tls1") << QSsl::TlsV1SslV3 << QSsl::TlsV1 << true; - QTest::newRow("tls1ssl3-secure") << QSsl::TlsV1SslV3 << QSsl::SecureProtocols << true; - QTest::newRow("tls1ssl3-any") << QSsl::TlsV1SslV3 << QSsl::AnyProtocol << true; - - QTest::newRow("secure-ssl2") << QSsl::SecureProtocols << QSsl::SslV2 << false; - QTest::newRow("secure-ssl3") << QSsl::SecureProtocols << QSsl::SslV3 << true; - QTest::newRow("secure-tls1") << QSsl::SecureProtocols << QSsl::TlsV1 << true; - QTest::newRow("secure-tls1ssl3") << QSsl::SecureProtocols << QSsl::TlsV1SslV3 << true; - QTest::newRow("secure-any") << QSsl::SecureProtocols << QSsl::AnyProtocol << true; - - QTest::newRow("any-ssl2") << QSsl::AnyProtocol << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2 - QTest::newRow("any-ssl3") << QSsl::AnyProtocol << QSsl::SslV3 << true; - QTest::newRow("any-tls1") << QSsl::AnyProtocol << QSsl::TlsV1 << true; - QTest::newRow("any-tls1ssl3") << QSsl::AnyProtocol << QSsl::TlsV1SslV3 << true; - QTest::newRow("any-secure") << QSsl::AnyProtocol << QSsl::SecureProtocols << true; -} - -void tst_QSslSocket::protocolServerSide() -{ - if (!QSslSocket::supportsSsl()) { - qWarning("SSL not supported, skipping test"); - return; - } - - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) - return; - - QFETCH(QSsl::SslProtocol, serverProtocol); - SslServer server; - server.protocol = serverProtocol; - QVERIFY(server.listen()); - - QEventLoop loop; - QTimer::singleShot(5000, &loop, SLOT(quit())); - - QSslSocketPtr client = new QSslSocket; - socket = client; - QFETCH(QSsl::SslProtocol, clientProtocol); - socket->setProtocol(clientProtocol); - // upon SSL wrong version error, error will be triggered, not sslErrors - connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit())); - connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); - connect(client, SIGNAL(encrypted()), &loop, SLOT(quit())); - - client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); - - loop.exec(); - - QFETCH(bool, works); - QAbstractSocket::SocketState expectedState = (works) ? QAbstractSocket::ConnectedState : QAbstractSocket::UnconnectedState; - QCOMPARE(client->state(), expectedState); - QCOMPARE(client->isEncrypted(), works); -} - -void tst_QSslSocket::setCaCertificates() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocket socket; - QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates()); - socket.setCaCertificates(QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem")); - QCOMPARE(socket.caCertificates().size(), 1); - socket.setCaCertificates(socket.defaultCaCertificates()); - QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates()); -} - -void tst_QSslSocket::setLocalCertificate() -{ -} - -void tst_QSslSocket::setPrivateKey() -{ -} - -void tst_QSslSocket::setSocketDescriptor() -{ - if (!QSslSocket::supportsSsl()) - return; - - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) - return; - - SslServer server; - QVERIFY(server.listen()); - - QEventLoop loop; - QTimer::singleShot(5000, &loop, SLOT(quit())); - - QSslSocketPtr client = new QSslSocket; - socket = client; - connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); - connect(client, SIGNAL(encrypted()), &loop, SLOT(quit())); - - client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); - - loop.exec(); - - QCOMPARE(client->state(), QAbstractSocket::ConnectedState); - QVERIFY(client->isEncrypted()); - QVERIFY(!client->peerAddress().isNull()); - QVERIFY(client->peerPort() != 0); - QVERIFY(!client->localAddress().isNull()); - QVERIFY(client->localPort() != 0); -} - -void tst_QSslSocket::setSslConfiguration_data() -{ - QTest::addColumn<QSslConfiguration>("configuration"); - QTest::addColumn<bool>("works"); - - QTest::newRow("empty") << QSslConfiguration() << false; - QSslConfiguration conf = QSslConfiguration::defaultConfiguration(); - QTest::newRow("default") << conf << false; // does not contain test server cert - QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"); - conf.setCaCertificates(testServerCert); - QTest::newRow("set-root-cert") << conf << true; - conf.setProtocol(QSsl::SecureProtocols); - QTest::newRow("secure") << conf << true; -} - -void tst_QSslSocket::setSslConfiguration() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocketPtr socket = newSocket(); - QFETCH(QSslConfiguration, configuration); - socket->setSslConfiguration(configuration); - this->socket = socket; - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QFETCH(bool, works); - QCOMPARE(socket->waitForEncrypted(10000), works); - if (works) { - socket->disconnectFromHost(); - QVERIFY2(socket->waitForDisconnected(), qPrintable(socket->errorString())); - } -} - -void tst_QSslSocket::waitForEncrypted() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocketPtr socket = newSocket(); - this->socket = socket; - - connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - - QVERIFY(socket->waitForEncrypted(10000)); -} - -void tst_QSslSocket::waitForEncryptedMinusOne() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocketPtr socket = newSocket(); - this->socket = socket; - - connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - - QVERIFY(socket->waitForEncrypted(-1)); -} - -void tst_QSslSocket::waitForConnectedEncryptedReadyRead() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocketPtr socket = newSocket(); - this->socket = socket; - - connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993); - -#ifdef Q_OS_SYMBIAN - QVERIFY(socket->waitForConnected(10000)); - QVERIFY(socket->waitForEncrypted(10000)); - - // dont forget to login - QCOMPARE((int) socket->write("USER ftptest\r\n"), 14); - QCOMPARE((int) socket->write("PASS ftP2Ptf\r\n"), 14); - - QVERIFY(socket->waitForReadyRead(10000)); - QVERIFY(!socket->peerCertificate().isNull()); - QVERIFY(!socket->peerCertificateChain().isEmpty()); -#else - QVERIFY(socket->waitForConnected(10000)); - QVERIFY(socket->waitForEncrypted(10000)); - QVERIFY(socket->waitForReadyRead(10000)); - QVERIFY(!socket->peerCertificate().isNull()); - QVERIFY(!socket->peerCertificateChain().isEmpty()); -#endif -} - -void tst_QSslSocket::startClientEncryption() -{ -} - -void tst_QSslSocket::startServerEncryption() -{ -} - -void tst_QSslSocket::addDefaultCaCertificate() -{ - if (!QSslSocket::supportsSsl()) - return; - - // Reset the global CA chain - QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates()); - - QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"); - QCOMPARE(flukeCerts.size(), 1); - QList<QSslCertificate> globalCerts = QSslSocket::defaultCaCertificates(); - QVERIFY(!globalCerts.contains(flukeCerts.first())); - QSslSocket::addDefaultCaCertificate(flukeCerts.first()); - QCOMPARE(QSslSocket::defaultCaCertificates().size(), globalCerts.size() + 1); - QVERIFY(QSslSocket::defaultCaCertificates().contains(flukeCerts.first())); - - // Restore the global CA chain - QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates()); -} - -void tst_QSslSocket::addDefaultCaCertificates() -{ -} - -void tst_QSslSocket::addDefaultCaCertificates2() -{ -} - -void tst_QSslSocket::defaultCaCertificates() -{ - if (!QSslSocket::supportsSsl()) - return; - - QList<QSslCertificate> certs = QSslSocket::defaultCaCertificates(); - QVERIFY(certs.size() > 1); - QCOMPARE(certs, QSslSocket::systemCaCertificates()); -} - -void tst_QSslSocket::defaultCiphers() -{ -} - -void tst_QSslSocket::resetDefaultCiphers() -{ -} - -void tst_QSslSocket::setDefaultCaCertificates() -{ -} - -void tst_QSslSocket::setDefaultCiphers() -{ -} - -void tst_QSslSocket::supportedCiphers() -{ - if (!QSslSocket::supportsSsl()) - return; - - QList<QSslCipher> ciphers = QSslSocket::supportedCiphers(); - QVERIFY(ciphers.size() > 1); - - QSslSocket socket; - QCOMPARE(socket.supportedCiphers(), ciphers); - QCOMPARE(socket.defaultCiphers(), ciphers); - QCOMPARE(socket.ciphers(), ciphers); -} - -void tst_QSslSocket::systemCaCertificates() -{ - if (!QSslSocket::supportsSsl()) - return; - - QList<QSslCertificate> certs = QSslSocket::systemCaCertificates(); - QVERIFY(certs.size() > 1); - QCOMPARE(certs, QSslSocket::defaultCaCertificates()); -} - -void tst_QSslSocket::wildcardCertificateNames() -{ - // Passing CN matches - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("www.example.com"), QString("www.example.com")), true ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.example.com"), QString("www.example.com")), true ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("xxx*.example.com"), QString("xxxwww.example.com")), true ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("f*.example.com"), QString("foo.example.com")), true ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("192.168.0.0"), QString("192.168.0.0")), true ); - - // Failing CN matches - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("xxx.example.com"), QString("www.example.com")), false ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*"), QString("www.example.com")), false ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.*.com"), QString("www.example.com")), false ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.example.com"), QString("baa.foo.example.com")), false ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("f*.example.com"), QString("baa.example.com")), false ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.com"), QString("example.com")), false ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*fail.com"), QString("example.com")), false ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.example."), QString("www.example.")), false ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.example."), QString("www.example")), false ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString(""), QString("www")), false ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*"), QString("www")), false ); - QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.168.0.0"), QString("192.168.0.0")), false ); -} - -void tst_QSslSocket::wildcard() -{ - QSKIP("TODO: solve wildcard problem", SkipAll); - - if (!QSslSocket::supportsSsl()) - return; - - // Fluke runs an apache server listening on port 4443, serving the - // wildcard fluke.*.troll.no. The DNS entry for - // fluke.wildcard.dev.troll.no, served by ares (root for dev.troll.no), - // returns the CNAME fluke.troll.no for this domain. The web server - // responds with the wildcard, and QSslSocket should accept that as a - // valid connection. This was broken in 4.3.0. - QSslSocketPtr socket = newSocket(); - socket->addCaCertificates(QLatin1String("certs/aspiriniks.ca.crt")); - this->socket = socket; -#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND - connect(socket, SIGNAL(sslErrors(QList<QSslError>)), - this, SLOT(untrustedWorkaroundSlot(QList<QSslError>))); -#endif - socket->connectToHostEncrypted(QtNetworkSettings::wildcardServerName(), 4443); - - QVERIFY2(socket->waitForEncrypted(3000), qPrintable(socket->errorString())); - - QSslCertificate certificate = socket->peerCertificate(); - QCOMPARE(certificate.subjectInfo(QSslCertificate::CommonName), QString(QtNetworkSettings::serverLocalName() + ".*." + QtNetworkSettings::serverDomainName())); - QCOMPARE(certificate.issuerInfo(QSslCertificate::CommonName), QtNetworkSettings::serverName()); - - socket->close(); -} - -class SslServer2 : public QTcpServer -{ -protected: - void incomingConnection(int socketDescriptor) - { - QSslSocket *socket = new QSslSocket(this); - socket->ignoreSslErrors(); - - // Only set the certificate - QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert"); - QVERIFY(!localCert.isEmpty()); - QVERIFY(localCert.first().handle()); - socket->setLocalCertificate(localCert.first()); - - QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState)); - - socket->startServerEncryption(); - } -}; - -void tst_QSslSocket::setEmptyKey() -{ - if (!QSslSocket::supportsSsl()) - return; - - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) - return; - - SslServer2 server; - server.listen(); - - QSslSocket socket; - socket.connectToHostEncrypted("127.0.0.1", server.serverPort()); - - QTestEventLoop::instance().enterLoop(2); - - QCOMPARE(socket.state(), QAbstractSocket::ConnectedState); - QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError); -} - -void tst_QSslSocket::spontaneousWrite() -{ - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) - return; - - SslServer server; - QSslSocket *receiver = new QSslSocket(this); - connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop())); - - // connect two sockets to each other: - QVERIFY(server.listen(QHostAddress::LocalHost)); - receiver->connectToHost("127.0.0.1", server.serverPort()); - QVERIFY(receiver->waitForConnected(5000)); - QVERIFY(server.waitForNewConnection(0)); - - QSslSocket *sender = server.socket; - QVERIFY(sender); - QVERIFY(sender->state() == QAbstractSocket::ConnectedState); - receiver->setObjectName("receiver"); - sender->setObjectName("sender"); - receiver->ignoreSslErrors(); - receiver->startClientEncryption(); - - // SSL handshake: - connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop())); - enterLoop(1); - QVERIFY(!timeout()); - QVERIFY(sender->isEncrypted()); - QVERIFY(receiver->isEncrypted()); - - // make sure there's nothing to be received on the sender: - while (sender->waitForReadyRead(10) || receiver->waitForBytesWritten(10)) {} - - // spontaneously write something: - QByteArray data("Hello World"); - sender->write(data); - - // check if the other side receives it: - enterLoop(1); - QVERIFY(!timeout()); - QCOMPARE(receiver->bytesAvailable(), qint64(data.size())); - QCOMPARE(receiver->readAll(), data); -} - -void tst_QSslSocket::setReadBufferSize() -{ - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) - return; - - SslServer server; - QSslSocket *receiver = new QSslSocket(this); - connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop())); - - // connect two sockets to each other: - QVERIFY(server.listen(QHostAddress::LocalHost)); - receiver->connectToHost("127.0.0.1", server.serverPort()); - QVERIFY(receiver->waitForConnected(5000)); - QVERIFY(server.waitForNewConnection(0)); - - QSslSocket *sender = server.socket; - QVERIFY(sender); - QVERIFY(sender->state() == QAbstractSocket::ConnectedState); - receiver->setObjectName("receiver"); - sender->setObjectName("sender"); - receiver->ignoreSslErrors(); - receiver->startClientEncryption(); - - // SSL handshake: - connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop())); - enterLoop(1); - QVERIFY(!timeout()); - QVERIFY(sender->isEncrypted()); - QVERIFY(receiver->isEncrypted()); - - QByteArray data(2048, 'b'); - receiver->setReadBufferSize(39 * 1024); // make it a non-multiple of the data.size() - - // saturate the incoming buffer - while (sender->state() == QAbstractSocket::ConnectedState && - receiver->state() == QAbstractSocket::ConnectedState && - receiver->bytesAvailable() < receiver->readBufferSize()) { - sender->write(data); - //qDebug() << receiver->bytesAvailable() << "<" << receiver->readBufferSize() << (receiver->bytesAvailable() < receiver->readBufferSize()); - - while (sender->bytesToWrite()) - QVERIFY(sender->waitForBytesWritten(10)); - - // drain it: - while (receiver->bytesAvailable() < receiver->readBufferSize() && - receiver->waitForReadyRead(10)) {} - } - - //qDebug() << sender->bytesToWrite() << "bytes to write"; - //qDebug() << receiver->bytesAvailable() << "bytes available"; - - // send a bit more - sender->write(data); - sender->write(data); - sender->write(data); - sender->write(data); - QVERIFY(sender->waitForBytesWritten(10)); - - qint64 oldBytesAvailable = receiver->bytesAvailable(); - - // now unset the read buffer limit and iterate - receiver->setReadBufferSize(0); - enterLoop(1); - QVERIFY(!timeout()); - - QVERIFY(receiver->bytesAvailable() > oldBytesAvailable); -} - -class SetReadBufferSize_task_250027_handler : public QObject { - Q_OBJECT -public slots: - void readyReadSlot() { - QTestEventLoop::instance().exitLoop(); - } - void waitSomeMore(QSslSocket *socket) { - QTime t; - t.start(); - while (!socket->encryptedBytesAvailable()) { - QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents, 250); - if (t.elapsed() > 1000 || socket->state() != QAbstractSocket::ConnectedState) - return; - } - } -}; - -void tst_QSslSocket::setReadBufferSize_task_250027() -{ - // do not execute this when a proxy is set. - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) - return; - - QSslSocketPtr socket = newSocket(); - socket->setReadBufferSize(1000); // limit to 1 kb/sec - socket->ignoreSslErrors(); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - socket->ignoreSslErrors(); - QVERIFY(socket->waitForConnected(10*1000)); - QVERIFY(socket->waitForEncrypted(10*1000)); - - // exit the event loop as soon as we receive a readyRead() - SetReadBufferSize_task_250027_handler setReadBufferSize_task_250027_handler; - connect(socket, SIGNAL(readyRead()), &setReadBufferSize_task_250027_handler, SLOT(readyReadSlot())); - - // provoke a response by sending a request - socket->write("GET /qtest/fluke.gif HTTP/1.0\n"); // this file is 27 KB - socket->write("Host: "); - socket->write(QtNetworkSettings::serverName().toLocal8Bit().constData()); - socket->write("\n"); - socket->write("Connection: close\n"); - socket->write("\n"); - socket->flush(); - - QTestEventLoop::instance().enterLoop(10); - setReadBufferSize_task_250027_handler.waitSomeMore(socket); - QByteArray firstRead = socket->readAll(); - // First read should be some data, but not the whole file - QVERIFY(firstRead.size() > 0 && firstRead.size() < 20*1024); - - QTestEventLoop::instance().enterLoop(10); - setReadBufferSize_task_250027_handler.waitSomeMore(socket); - QByteArray secondRead = socket->readAll(); - // second read should be some more data - QVERIFY(secondRead.size() > 0); - - socket->close(); -} - -class SslServer3 : public QTcpServer -{ - Q_OBJECT -public: - SslServer3() : socket(0) { } - QSslSocket *socket; - -protected: - void incomingConnection(int socketDescriptor) - { - socket = new QSslSocket(this); - connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); - - QFile file(SRCDIR "certs/fluke.key"); - QVERIFY(file.open(QIODevice::ReadOnly)); - QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); - QVERIFY(!key.isNull()); - socket->setPrivateKey(key); - - QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert"); - QVERIFY(!localCert.isEmpty()); - QVERIFY(localCert.first().handle()); - socket->setLocalCertificate(localCert.first()); - - QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState)); - QVERIFY(!socket->peerAddress().isNull()); - QVERIFY(socket->peerPort() != 0); - QVERIFY(!socket->localAddress().isNull()); - QVERIFY(socket->localPort() != 0); - } - -protected slots: - void ignoreErrorSlot() - { - socket->ignoreSslErrors(); - } -}; - -class ThreadedSslServer: public QThread -{ - Q_OBJECT -public: - QSemaphore dataReadSemaphore; - int serverPort; - bool ok; - - ThreadedSslServer() : serverPort(-1), ok(false) - { } - - ~ThreadedSslServer() - { - if (isRunning()) wait(2000); - QVERIFY(ok); - } - -signals: - void listening(); - -protected: - void run() - { - // if all goes well (no timeouts), this thread will sleep for a total of 500 ms - // (i.e., 5 times 100 ms, one sleep for each operation) - - SslServer3 server; - server.listen(QHostAddress::LocalHost); - serverPort = server.serverPort(); - emit listening(); - - // delayed acceptance: - QTest::qSleep(100); -#ifndef Q_OS_SYMBIAN - bool ret = server.waitForNewConnection(2000); -#else - bool ret = server.waitForNewConnection(20000); -#endif - Q_UNUSED(ret); - - // delayed start of encryption - QTest::qSleep(100); - QSslSocket *socket = server.socket; - if (!socket || !socket->isValid()) - return; // error - socket->ignoreSslErrors(); - socket->startServerEncryption(); - if (!socket->waitForEncrypted(2000)) - return; // error - - // delayed reading data - QTest::qSleep(100); - if (!socket->waitForReadyRead(2000)) - return; // error - socket->readAll(); - dataReadSemaphore.release(); - - // delayed sending data - QTest::qSleep(100); - socket->write("Hello, World"); - while (socket->bytesToWrite()) - if (!socket->waitForBytesWritten(2000)) - return; // error - - // delayed replying (reading then sending) - QTest::qSleep(100); - if (!socket->waitForReadyRead(2000)) - return; // error - socket->write("Hello, World"); - while (socket->bytesToWrite()) - if (!socket->waitForBytesWritten(2000)) - return; // error - - // delayed disconnection: - QTest::qSleep(100); - socket->disconnectFromHost(); - if (!socket->waitForDisconnected(2000)) - return; // error - - delete socket; - ok = true; - } -}; - -void tst_QSslSocket::waitForMinusOne() -{ - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) - return; - - ThreadedSslServer server; - connect(&server, SIGNAL(listening()), SLOT(exitLoop())); - - // start the thread and wait for it to be ready - server.start(); - enterLoop(1); - QVERIFY(!timeout()); - - // connect to the server - QSslSocket socket; - QTest::qSleep(100); - socket.connectToHost("127.0.0.1", server.serverPort); - QVERIFY(socket.waitForConnected(-1)); - socket.ignoreSslErrors(); - socket.startClientEncryption(); - - // first verification: this waiting should take 200 ms - QVERIFY2(socket.waitForEncrypted(-1), qPrintable(socket.errorString())); - QVERIFY(socket.isEncrypted()); - QCOMPARE(socket.state(), QAbstractSocket::ConnectedState); - QCOMPARE(socket.bytesAvailable(), Q_INT64_C(0)); - - // second verification: write and make sure the other side got it (100 ms) - socket.write("How are you doing?"); - QVERIFY(socket.bytesToWrite() != 0); - QVERIFY(socket.waitForBytesWritten(-1)); - QVERIFY(server.dataReadSemaphore.tryAcquire(1, 2000)); - - // third verification: it should wait for 100 ms: - QVERIFY(socket.waitForReadyRead(-1)); - QVERIFY(socket.isEncrypted()); - QCOMPARE(socket.state(), QAbstractSocket::ConnectedState); - QVERIFY(socket.bytesAvailable() != 0); - - // fourth verification: deadlock prevention: - // we write and then wait for reading; the other side needs to receive before - // replying (100 ms delay) - socket.write("I'm doing just fine!"); - QVERIFY(socket.bytesToWrite() != 0); - QVERIFY(socket.waitForReadyRead(-1)); - - // fifth verification: it should wait for 200 ms more - QVERIFY(socket.waitForDisconnected(-1)); -} - -class VerifyServer : public QTcpServer -{ - Q_OBJECT -public: - VerifyServer() : socket(0) { } - QSslSocket *socket; - -protected: - void incomingConnection(int socketDescriptor) - { - socket = new QSslSocket(this); - - socket->setPrivateKey(SRCDIR "certs/fluke.key"); - socket->setLocalCertificate(SRCDIR "certs/fluke.cert"); - socket->setSocketDescriptor(socketDescriptor); - socket->startServerEncryption(); - } -}; - -void tst_QSslSocket::verifyMode() -{ - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) - return; - - QSslSocket socket; - QCOMPARE(socket.peerVerifyMode(), QSslSocket::AutoVerifyPeer); - socket.setPeerVerifyMode(QSslSocket::VerifyNone); - QCOMPARE(socket.peerVerifyMode(), QSslSocket::VerifyNone); - socket.setPeerVerifyMode(QSslSocket::VerifyNone); - socket.setPeerVerifyMode(QSslSocket::VerifyPeer); - QCOMPARE(socket.peerVerifyMode(), QSslSocket::VerifyPeer); - - socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY(!socket.waitForEncrypted()); - - QList<QSslError> expectedErrors = QList<QSslError>() - << QSslError(QSslError::SelfSignedCertificate, socket.peerCertificate()); - QCOMPARE(socket.sslErrors(), expectedErrors); - socket.abort(); - - VerifyServer server; - server.listen(); - - QSslSocket clientSocket; - clientSocket.connectToHostEncrypted("127.0.0.1", server.serverPort()); - clientSocket.ignoreSslErrors(); - - QEventLoop loop; - QTimer::singleShot(5000, &loop, SLOT(quit())); - connect(&clientSocket, SIGNAL(encrypted()), &loop, SLOT(quit())); - loop.exec(); - - QVERIFY(clientSocket.isEncrypted()); - QVERIFY(server.socket->sslErrors().isEmpty()); -} - -void tst_QSslSocket::verifyDepth() -{ - QSslSocket socket; - QCOMPARE(socket.peerVerifyDepth(), 0); - socket.setPeerVerifyDepth(1); - QCOMPARE(socket.peerVerifyDepth(), 1); - QTest::ignoreMessage(QtWarningMsg, "QSslSocket::setPeerVerifyDepth: cannot set negative depth of -1"); - socket.setPeerVerifyDepth(-1); - QCOMPARE(socket.peerVerifyDepth(), 1); -} - -void tst_QSslSocket::peerVerifyError() -{ - QSslSocketPtr socket = newSocket(); - QSignalSpy sslErrorsSpy(socket, SIGNAL(sslErrors(QList<QSslError>))); - QSignalSpy peerVerifyErrorSpy(socket, SIGNAL(peerVerifyError(QSslError))); - - socket->connectToHostEncrypted(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(), 443); - QVERIFY(!socket->waitForEncrypted(10000)); - QVERIFY(!peerVerifyErrorSpy.isEmpty()); - QVERIFY(!sslErrorsSpy.isEmpty()); - QCOMPARE(qVariantValue<QSslError>(peerVerifyErrorSpy.last().at(0)).error(), QSslError::HostNameMismatch); - QCOMPARE(qVariantValue<QList<QSslError> >(sslErrorsSpy.at(0).at(0)).size(), peerVerifyErrorSpy.size()); -} - -void tst_QSslSocket::disconnectFromHostWhenConnecting() -{ - QSslSocketPtr socket = newSocket(); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993); - socket->ignoreSslErrors(); - socket->write("XXXX LOGOUT\r\n"); - QAbstractSocket::SocketState state = socket->state(); - // without proxy, the state will be HostLookupState; - // with proxy, the state will be ConnectingState. - QVERIFY(socket->state() == QAbstractSocket::HostLookupState || - socket->state() == QAbstractSocket::ConnectingState); - socket->disconnectFromHost(); - // the state of the socket must be the same before and after calling - // disconnectFromHost() - QCOMPARE(state, socket->state()); - QVERIFY(socket->state() == QAbstractSocket::HostLookupState || - socket->state() == QAbstractSocket::ConnectingState); - QVERIFY(socket->waitForDisconnected(10000)); - QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState); - // we did not call close, so the socket must be still open - QVERIFY(socket->isOpen()); - QCOMPARE(socket->bytesToWrite(), qint64(0)); - - // dont forget to login - QCOMPARE((int) socket->write("USER ftptest\r\n"), 14); - -} - -void tst_QSslSocket::disconnectFromHostWhenConnected() -{ - QSslSocketPtr socket = newSocket(); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993); - socket->ignoreSslErrors(); -#ifndef Q_OS_SYMBIAN - QVERIFY(socket->waitForEncrypted(5000)); -#else - QVERIFY(socket->waitForEncrypted(10000)); -#endif - socket->write("XXXX LOGOUT\r\n"); - QCOMPARE(socket->state(), QAbstractSocket::ConnectedState); - socket->disconnectFromHost(); - QCOMPARE(socket->state(), QAbstractSocket::ClosingState); -#ifdef Q_OS_SYMBIAN - // I don't understand how socket->waitForDisconnected can work on other platforms - // since socket->write will end to: - // QMetaObject::invokeMethod(this, "_q_flushWriteBuffer", Qt::QueuedConnection); - // In order that _q_flushWriteBuffer will be called the eventloop need to run - // If we just call waitForDisconnected, which blocks the whole thread how that can happen? - connect(socket, SIGNAL(disconnected()), this, SLOT(exitLoop())); - enterLoop(5); - QVERIFY(!timeout()); -#else - QVERIFY(socket->waitForDisconnected(5000)); -#endif - QCOMPARE(socket->bytesToWrite(), qint64(0)); -} - -void tst_QSslSocket::resetProxy() -{ - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) - return; - - // check fix for bug 199941 - - QNetworkProxy goodProxy(QNetworkProxy::NoProxy); - QNetworkProxy badProxy(QNetworkProxy::HttpProxy, "thisCannotWorkAbsolutelyNotForSure", 333); - - // make sure the connection works, and then set a nonsense proxy, and then - // make sure it does not work anymore - QSslSocket socket; - socket.addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); - socket.setProxy(goodProxy); - socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY2(socket.waitForConnected(10000), qPrintable(socket.errorString())); - socket.abort(); - socket.setProxy(badProxy); - socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY(! socket.waitForConnected(10000)); - - // dont forget to login - QCOMPARE((int) socket.write("USER ftptest\r\n"), 14); - QCOMPARE((int) socket.write("PASS password\r\n"), 15); - - enterLoop(10); - - // now the other way round: - // set the nonsense proxy and make sure the connection does not work, - // and then set the right proxy and make sure it works - QSslSocket socket2; - socket2.addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); - socket2.setProxy(badProxy); - socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY(! socket2.waitForConnected(10000)); - socket2.abort(); - socket2.setProxy(goodProxy); - socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY2(socket2.waitForConnected(10000), qPrintable(socket.errorString())); -} - -void tst_QSslSocket::ignoreSslErrorsList_data() -{ - QTest::addColumn<QList<QSslError> >("expectedSslErrors"); - QTest::addColumn<int>("expectedSslErrorSignalCount"); - - // construct the list of errors that we will get with the SSL handshake and that we will ignore - QList<QSslError> expectedSslErrors; - // fromPath gives us a list of certs, but it actually only contains one - QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); - QSslError rightError(QSslError::SelfSignedCertificate, certs.at(0)); - QSslError wrongError(QSslError::SelfSignedCertificate); - - - QTest::newRow("SSL-failure-empty-list") << expectedSslErrors << 1; - expectedSslErrors.append(wrongError); - QTest::newRow("SSL-failure-wrong-error") << expectedSslErrors << 1; - expectedSslErrors.append(rightError); - QTest::newRow("allErrorsInExpectedList1") << expectedSslErrors << 0; - expectedSslErrors.removeAll(wrongError); - QTest::newRow("allErrorsInExpectedList2") << expectedSslErrors << 0; - expectedSslErrors.removeAll(rightError); - QTest::newRow("SSL-failure-empty-list-again") << expectedSslErrors << 1; -} - -void tst_QSslSocket::ignoreSslErrorsList() -{ - QSslSocket socket; - connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), - this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); - -// this->socket = &socket; - QSslCertificate cert; - - QFETCH(QList<QSslError>, expectedSslErrors); - socket.ignoreSslErrors(expectedSslErrors); - - QFETCH(int, expectedSslErrorSignalCount); - QSignalSpy sslErrorsSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError))); - - socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - - bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0); - QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess); - QCOMPARE(sslErrorsSpy.count(), expectedSslErrorSignalCount); -} - -void tst_QSslSocket::ignoreSslErrorsListWithSlot_data() -{ - ignoreSslErrorsList_data(); -} - -// this is not a test, just a slot called in the test below -void tst_QSslSocket::ignoreErrorListSlot(const QList<QSslError> &) -{ - socket->ignoreSslErrors(storedExpectedSslErrors); -} - -void tst_QSslSocket::ignoreSslErrorsListWithSlot() -{ - QSslSocket socket; - this->socket = &socket; - - QFETCH(QList<QSslError>, expectedSslErrors); - // store the errors to ignore them later in the slot connected below - storedExpectedSslErrors = expectedSslErrors; - connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), - this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); - connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), - this, SLOT(ignoreErrorListSlot(const QList<QSslError> &))); - socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - - QFETCH(int, expectedSslErrorSignalCount); - bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0); - QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess); -} - -// make sure a closed socket has no bytesAvailable() -// related to https://bugs.webkit.org/show_bug.cgi?id=28016 -void tst_QSslSocket::readFromClosedSocket() -{ - QSslSocketPtr socket = newSocket(); - socket->ignoreSslErrors(); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - socket->ignoreSslErrors(); - socket->waitForConnected(); - socket->waitForEncrypted(); - // provoke a response by sending a request - socket->write("GET /qtest/fluke.gif HTTP/1.1\n"); - socket->write("Host: "); - socket->write(QtNetworkSettings::serverName().toLocal8Bit().constData()); - socket->write("\n"); - socket->write("\n"); - socket->waitForBytesWritten(); - socket->waitForReadyRead(); - QVERIFY(socket->state() == QAbstractSocket::ConnectedState); - QVERIFY(socket->bytesAvailable()); - socket->close(); - QVERIFY(!socket->bytesAvailable()); - QVERIFY(!socket->bytesToWrite()); - QVERIFY(socket->state() == QAbstractSocket::UnconnectedState); -} - -void tst_QSslSocket::writeBigChunk() -{ - if (!QSslSocket::supportsSsl()) - return; - - QSslSocketPtr socket = newSocket(); - this->socket = socket; - - connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - - QByteArray data; - data.resize(1024*1024*10); // 10 MB - // init with garbage. needed so ssl cannot compress it in an efficient way. - for (size_t i = 0; i < data.size() / sizeof(int); i++) { - int r = qrand(); - data.data()[i*sizeof(int)] = r; - } - - QVERIFY(socket->waitForEncrypted(10000)); - QString errorBefore = socket->errorString(); - - int ret = socket->write(data.constData(), data.size()); - QVERIFY(data.size() == ret); - - // spin the event loop once so QSslSocket::transmit() gets called - QCoreApplication::processEvents(); - QString errorAfter = socket->errorString(); - - // no better way to do this right now since the error is the same as the default error. - if (socket->errorString().startsWith(QLatin1String("Unable to write data"))) - { - qWarning() << socket->error() << socket->errorString(); - QFAIL("Error while writing! Check if the OpenSSL BIO size is limited?!"); - } - // also check the error string. If another error (than UnknownError) occurred, it should be different than before - QVERIFY(errorBefore == errorAfter); - - // check that everything has been written to OpenSSL - QVERIFY(socket->bytesToWrite() == 0); - - socket->close(); -} - -void tst_QSslSocket::blacklistedCertificates() -{ - QFETCH_GLOBAL(bool, setProxy); - if (setProxy) - return; - - SslServer server(SRCDIR "certs/fake-login.live.com.key", SRCDIR "certs/fake-login.live.com.pem"); - QSslSocket *receiver = new QSslSocket(this); - connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop())); - - // connect two sockets to each other: - QVERIFY(server.listen(QHostAddress::LocalHost)); - receiver->connectToHost("127.0.0.1", server.serverPort()); - QVERIFY(receiver->waitForConnected(5000)); - QVERIFY(server.waitForNewConnection(0)); - - QSslSocket *sender = server.socket; - QVERIFY(sender); - QVERIFY(sender->state() == QAbstractSocket::ConnectedState); - receiver->setObjectName("receiver"); - sender->setObjectName("sender"); - receiver->startClientEncryption(); - - connect(receiver, SIGNAL(sslErrors(QList<QSslError>)), SLOT(exitLoop())); - connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop())); - enterLoop(1); - QList<QSslError> sslErrors = receiver->sslErrors(); - QVERIFY(sslErrors.count() > 0); - // there are more errors (self signed cert and hostname mismatch), but we only care about the blacklist error - QCOMPARE(sslErrors.at(0).error(), QSslError::CertificateBlacklisted); -} - -void tst_QSslSocket::setEmptyDefaultConfiguration() -{ - // used to produce a crash in QSslConfigurationPrivate::deepCopyDefaultConfiguration, QTBUG-13265 - - if (!QSslSocket::supportsSsl()) - return; - - QSslConfiguration emptyConf; - QSslConfiguration::setDefaultConfiguration(emptyConf); - - QSslSocketPtr socket = newSocket(); - connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot())); - socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443); - QVERIFY2(!socket->waitForEncrypted(4000), qPrintable(socket->errorString())); -} - -void tst_QSslSocket::versionAccessors() -{ - if (!QSslSocket::supportsSsl()) - return; - - qDebug() << QSslSocket::sslLibraryVersionString(); - qDebug() << QString::number(QSslSocket::sslLibraryVersionNumber(), 16); -} - -#endif // QT_NO_OPENSSL - -QTEST_MAIN(tst_QSslSocket) -#include "tst_qsslsocket.moc" |