tests/auto/qsslsocket/tst_qsslsocket.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtCore/qthread.h>
       
    44 #include <QtNetwork/qhostaddress.h>
       
    45 #include <QtNetwork/qhostinfo.h>
       
    46 #include <QtNetwork/qnetworkproxy.h>
       
    47 #include <QtNetwork/qsslcipher.h>
       
    48 #include <QtNetwork/qsslconfiguration.h>
       
    49 #include <QtNetwork/qsslkey.h>
       
    50 #include <QtNetwork/qsslsocket.h>
       
    51 #include <QtNetwork/qtcpserver.h>
       
    52 #include <QtTest/QtTest>
       
    53 
       
    54 #ifndef TEST_QNETWORK_PROXY
       
    55 #define TEST_QNETWORK_PROXY
       
    56 #endif
       
    57 #ifdef TEST_QNETWORK_PROXY
       
    58 #include <QNetworkProxy>
       
    59 #include <QAuthenticator>
       
    60 #endif
       
    61 
       
    62 #include "../network-settings.h"
       
    63 
       
    64 Q_DECLARE_METATYPE(QAbstractSocket::SocketState)
       
    65 Q_DECLARE_METATYPE(QAbstractSocket::SocketError)
       
    66 #ifndef QT_NO_OPENSSL
       
    67 Q_DECLARE_METATYPE(QSslSocket::SslMode)
       
    68 typedef QList<QSslError::SslError> SslErrorList;
       
    69 Q_DECLARE_METATYPE(SslErrorList)
       
    70 Q_DECLARE_METATYPE(QSslError)
       
    71 #endif
       
    72 
       
    73 #if defined Q_OS_HPUX && defined Q_CC_GNU
       
    74 // This error is delivered every time we try to use the fluke CA
       
    75 // certificate. For now we work around this bug. Task 202317.
       
    76 #define QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
       
    77 #endif
       
    78 
       
    79 #ifdef Q_OS_SYMBIAN
       
    80 #define SRCDIR ""
       
    81 #endif
       
    82 
       
    83 #ifndef QT_NO_OPENSSL
       
    84 class QSslSocketPtr: public QSharedPointer<QSslSocket>
       
    85 {
       
    86 public:
       
    87     inline QSslSocketPtr(QSslSocket *ptr = 0)
       
    88         : QSharedPointer<QSslSocket>(ptr)
       
    89     { }
       
    90 
       
    91     inline operator QSslSocket *() const { return data(); }
       
    92 };
       
    93 #endif
       
    94 
       
    95 class tst_QSslSocket : public QObject
       
    96 {
       
    97     Q_OBJECT
       
    98 
       
    99     int proxyAuthCalled;
       
   100 
       
   101 public:
       
   102     tst_QSslSocket();
       
   103     virtual ~tst_QSslSocket();
       
   104 
       
   105     static void enterLoop(int secs)
       
   106     {
       
   107         ++loopLevel;
       
   108         QTestEventLoop::instance().enterLoop(secs);
       
   109     }
       
   110 
       
   111     static bool timeout()
       
   112     {
       
   113         return QTestEventLoop::instance().timeout();
       
   114     }
       
   115 
       
   116 #ifndef QT_NO_OPENSSL
       
   117     QSslSocketPtr newSocket();
       
   118 #endif
       
   119 
       
   120 public slots:
       
   121     void initTestCase_data();
       
   122     void init();
       
   123     void cleanup();
       
   124     void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth);
       
   125 
       
   126 #ifndef QT_NO_OPENSSL
       
   127 private slots:
       
   128     void constructing();
       
   129     void simpleConnect();
       
   130     void simpleConnectWithIgnore();
       
   131 
       
   132     // API tests
       
   133     void sslErrors_data();
       
   134     void sslErrors();
       
   135     void addCaCertificate();
       
   136     void addCaCertificates();
       
   137     void addCaCertificates2();
       
   138     void ciphers();
       
   139     void connectToHostEncrypted();
       
   140     void connectToHostEncryptedWithVerificationPeerName();
       
   141     void sessionCipher();
       
   142     void flush();
       
   143     void isEncrypted();
       
   144     void localCertificate();
       
   145     void mode();
       
   146     void peerCertificate();
       
   147     void peerCertificateChain();
       
   148     void privateKey();
       
   149     void protocol();
       
   150     void setCaCertificates();
       
   151     void setLocalCertificate();
       
   152     void setPrivateKey();
       
   153     void setProtocol();
       
   154     void setSocketDescriptor();
       
   155     void waitForEncrypted();
       
   156     void waitForConnectedEncryptedReadyRead();
       
   157     void startClientEncryption();
       
   158     void startServerEncryption();
       
   159     void addDefaultCaCertificate();
       
   160     void addDefaultCaCertificates();
       
   161     void addDefaultCaCertificates2();
       
   162     void defaultCaCertificates();
       
   163     void defaultCiphers();
       
   164     void resetDefaultCiphers();
       
   165     void setDefaultCaCertificates();
       
   166     void setDefaultCiphers();
       
   167     void supportedCiphers();
       
   168     void systemCaCertificates();
       
   169     void wildcard();
       
   170     void setEmptyKey();
       
   171     void spontaneousWrite();
       
   172     void setReadBufferSize();
       
   173     void setReadBufferSize_task_250027();
       
   174     void waitForMinusOne();
       
   175     void verifyMode();
       
   176     void verifyDepth();
       
   177     void peerVerifyError();
       
   178     void disconnectFromHostWhenConnecting();
       
   179     void disconnectFromHostWhenConnected();
       
   180     void resetProxy();
       
   181     void ignoreSslErrorsList_data();
       
   182     void ignoreSslErrorsList();
       
   183     void ignoreSslErrorsListWithSlot_data();
       
   184     void ignoreSslErrorsListWithSlot();
       
   185     void readFromClosedSocket();
       
   186     void writeBigChunk();
       
   187 
       
   188     static void exitLoop()
       
   189     {
       
   190         // Safe exit - if we aren't in an event loop, don't
       
   191         // exit one.
       
   192         if (loopLevel > 0) {
       
   193             --loopLevel;
       
   194             QTestEventLoop::instance().exitLoop();
       
   195         }
       
   196     }
       
   197 
       
   198 protected slots:
       
   199     void ignoreErrorSlot()
       
   200     {
       
   201         socket->ignoreSslErrors();
       
   202     }
       
   203     void untrustedWorkaroundSlot(const QList<QSslError> &errors)
       
   204     {
       
   205         if (errors.size() == 1 &&
       
   206                 (errors.first().error() == QSslError::CertificateUntrusted ||
       
   207                         errors.first().error() == QSslError::SelfSignedCertificate))
       
   208             socket->ignoreSslErrors();
       
   209     }
       
   210     void ignoreErrorListSlot(const QList<QSslError> &errors);
       
   211 
       
   212 private:
       
   213     QSslSocket *socket;
       
   214     QList<QSslError> storedExpectedSslErrors;
       
   215 #endif // QT_NO_OPENSSL
       
   216 private:
       
   217     static int loopLevel;
       
   218 };
       
   219 
       
   220 int tst_QSslSocket::loopLevel = 0;
       
   221 
       
   222 tst_QSslSocket::tst_QSslSocket()
       
   223 {
       
   224 #ifndef QT_NO_OPENSSL
       
   225     qRegisterMetaType<QList<QSslError> >("QList<QSslError>");
       
   226     qRegisterMetaType<QSslError>("QSslError");
       
   227     qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
       
   228     qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
       
   229     qRegisterMetaType<QAbstractSocket::SocketState>("QSslSocket::SslMode");
       
   230 #endif
       
   231     Q_SET_DEFAULT_IAP
       
   232 }
       
   233 
       
   234 tst_QSslSocket::~tst_QSslSocket()
       
   235 {
       
   236 }
       
   237 
       
   238 enum ProxyTests {
       
   239     NoProxy = 0x00,
       
   240     Socks5Proxy = 0x01,
       
   241     HttpProxy = 0x02,
       
   242     TypeMask = 0x0f,
       
   243 
       
   244     NoAuth = 0x00,
       
   245     AuthBasic = 0x10,
       
   246     AuthNtlm = 0x20,
       
   247     AuthMask = 0xf0
       
   248 };
       
   249 
       
   250 void tst_QSslSocket::initTestCase_data()
       
   251 {
       
   252     QTest::addColumn<bool>("setProxy");
       
   253     QTest::addColumn<int>("proxyType");
       
   254 
       
   255     QTest::newRow("WithoutProxy") << false << 0;
       
   256 #ifdef TEST_QNETWORK_PROXY
       
   257     QTest::newRow("WithSocks5Proxy") << true << int(Socks5Proxy);
       
   258     QTest::newRow("WithSocks5ProxyAuth") << true << int(Socks5Proxy | AuthBasic);
       
   259 
       
   260     QTest::newRow("WithHttpProxy") << true << int(HttpProxy);
       
   261     QTest::newRow("WithHttpProxyBasicAuth") << true << int(HttpProxy | AuthBasic);
       
   262     // uncomment the line below when NTLM works
       
   263 //    QTest::newRow("WithHttpProxyNtlmAuth") << true << int(HttpProxy | AuthNtlm);
       
   264 #endif
       
   265 }
       
   266 
       
   267 void tst_QSslSocket::init()
       
   268 {
       
   269     QFETCH_GLOBAL(bool, setProxy);
       
   270     if (setProxy) {
       
   271 #ifdef TEST_QNETWORK_PROXY
       
   272         QFETCH_GLOBAL(int, proxyType);
       
   273         QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
       
   274         QNetworkProxy proxy;
       
   275 
       
   276         switch (proxyType) {
       
   277         case Socks5Proxy:
       
   278             proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1080);
       
   279             break;
       
   280 
       
   281         case Socks5Proxy | AuthBasic:
       
   282             proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1081);
       
   283             break;
       
   284 
       
   285         case HttpProxy | NoAuth:
       
   286             proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3128);
       
   287             break;
       
   288 
       
   289         case HttpProxy | AuthBasic:
       
   290             proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3129);
       
   291             break;
       
   292 
       
   293         case HttpProxy | AuthNtlm:
       
   294             proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3130);
       
   295             break;
       
   296         }
       
   297         QNetworkProxy::setApplicationProxy(proxy);
       
   298 #endif
       
   299     }
       
   300 }
       
   301 
       
   302 void tst_QSslSocket::cleanup()
       
   303 {
       
   304 #ifdef TEST_QNETWORK_PROXY
       
   305     QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
       
   306 #endif
       
   307 }
       
   308 
       
   309 #ifndef QT_NO_OPENSSL
       
   310 QSslSocketPtr tst_QSslSocket::newSocket()
       
   311 {
       
   312     QSslSocket *socket = new QSslSocket;
       
   313 
       
   314     proxyAuthCalled = 0;
       
   315     connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
       
   316             SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
       
   317             Qt::DirectConnection);
       
   318 
       
   319     return QSslSocketPtr(socket);
       
   320 }
       
   321 #endif
       
   322 
       
   323 void tst_QSslSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
       
   324 {
       
   325     ++proxyAuthCalled;
       
   326     auth->setUser("qsockstest");
       
   327     auth->setPassword("password");
       
   328 }
       
   329 
       
   330 #ifndef QT_NO_OPENSSL
       
   331 
       
   332 void tst_QSslSocket::constructing()
       
   333 {
       
   334     if (!QSslSocket::supportsSsl())
       
   335         return;
       
   336 
       
   337     QSslSocket socket;
       
   338 
       
   339     QCOMPARE(socket.state(), QSslSocket::UnconnectedState);
       
   340     QCOMPARE(socket.mode(), QSslSocket::UnencryptedMode);
       
   341     QVERIFY(!socket.isEncrypted());
       
   342     QCOMPARE(socket.bytesAvailable(), qint64(0));
       
   343     QCOMPARE(socket.bytesToWrite(), qint64(0));
       
   344     QVERIFY(!socket.canReadLine());
       
   345     QVERIFY(socket.atEnd());
       
   346     QCOMPARE(socket.localCertificate(), QSslCertificate());
       
   347     QCOMPARE(socket.sslConfiguration(), QSslConfiguration::defaultConfiguration());
       
   348     QCOMPARE(socket.errorString(), QString("Unknown error"));
       
   349     char c = '\0';
       
   350     QTest::ignoreMessage(QtWarningMsg, "QIODevice::getChar: Closed device");
       
   351     QVERIFY(!socket.getChar(&c));
       
   352     QCOMPARE(c, '\0');
       
   353     QVERIFY(!socket.isOpen());
       
   354     QVERIFY(!socket.isReadable());
       
   355     QVERIFY(socket.isSequential());
       
   356     QVERIFY(!socket.isTextModeEnabled());
       
   357     QVERIFY(!socket.isWritable());
       
   358     QCOMPARE(socket.openMode(), QIODevice::NotOpen);
       
   359     QVERIFY(socket.peek(2).isEmpty());
       
   360     QCOMPARE(socket.pos(), qint64(0));
       
   361     QVERIFY(!socket.putChar('c'));
       
   362     QVERIFY(socket.read(2).isEmpty());
       
   363     QCOMPARE(socket.read(0, 0), qint64(-1));
       
   364     QVERIFY(socket.readAll().isEmpty());
       
   365     QTest::ignoreMessage(QtWarningMsg, "QIODevice::readLine: Called with maxSize < 2");
       
   366     QCOMPARE(socket.readLine(0, 0), qint64(-1));
       
   367     char buf[10];
       
   368     QCOMPARE(socket.readLine(buf, sizeof(buf)), qint64(-1));
       
   369     QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek: The device is not open");
       
   370     QVERIFY(!socket.reset());
       
   371     QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek: The device is not open");
       
   372     QVERIFY(!socket.seek(2));
       
   373     QCOMPARE(socket.size(), qint64(0));
       
   374     QVERIFY(!socket.waitForBytesWritten(10));
       
   375     QVERIFY(!socket.waitForReadyRead(10));
       
   376     QCOMPARE(socket.write(0, 0), qint64(-1));
       
   377     QCOMPARE(socket.write(QByteArray()), qint64(-1));
       
   378     QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
       
   379     QVERIFY(!socket.flush());
       
   380     QVERIFY(!socket.isValid());
       
   381     QCOMPARE(socket.localAddress(), QHostAddress());
       
   382     QCOMPARE(socket.localPort(), quint16(0));
       
   383     QCOMPARE(socket.peerAddress(), QHostAddress());
       
   384     QVERIFY(socket.peerName().isEmpty());
       
   385     QCOMPARE(socket.peerPort(), quint16(0));
       
   386     QCOMPARE(socket.proxy().type(), QNetworkProxy::DefaultProxy);
       
   387     QCOMPARE(socket.readBufferSize(), qint64(0));
       
   388     QCOMPARE(socket.socketDescriptor(), -1);
       
   389     QCOMPARE(socket.socketType(), QAbstractSocket::TcpSocket);
       
   390     QVERIFY(!socket.waitForConnected(10));
       
   391     QTest::ignoreMessage(QtWarningMsg, "QSslSocket::waitForDisconnected() is not allowed in UnconnectedState");
       
   392     QVERIFY(!socket.waitForDisconnected(10));
       
   393     QCOMPARE(socket.protocol(), QSsl::SslV3);
       
   394 
       
   395     QSslConfiguration savedDefault = QSslConfiguration::defaultConfiguration();
       
   396 
       
   397     // verify that changing the default config doesn't affect this socket
       
   398     QSslSocket::setDefaultCaCertificates(QList<QSslCertificate>());
       
   399     QSslSocket::setDefaultCiphers(QList<QSslCipher>());
       
   400     QVERIFY(!socket.caCertificates().isEmpty());
       
   401     QVERIFY(!socket.ciphers().isEmpty());
       
   402 
       
   403     // verify the default as well:
       
   404     QVERIFY(QSslConfiguration::defaultConfiguration().caCertificates().isEmpty());
       
   405     QVERIFY(QSslConfiguration::defaultConfiguration().ciphers().isEmpty());
       
   406 
       
   407     QSslConfiguration::setDefaultConfiguration(savedDefault);
       
   408 }
       
   409 
       
   410 void tst_QSslSocket::simpleConnect()
       
   411 {
       
   412     if (!QSslSocket::supportsSsl())
       
   413         return;
       
   414 
       
   415     QFETCH_GLOBAL(bool, setProxy);
       
   416     if (setProxy)
       
   417         return;
       
   418 
       
   419     QSslSocket socket;
       
   420     QSignalSpy connectedSpy(&socket, SIGNAL(connected()));
       
   421     QSignalSpy hostFoundSpy(&socket, SIGNAL(hostFound()));
       
   422     QSignalSpy disconnectedSpy(&socket, SIGNAL(disconnected()));
       
   423     QSignalSpy connectionEncryptedSpy(&socket, SIGNAL(encrypted()));
       
   424     QSignalSpy sslErrorsSpy(&socket, SIGNAL(sslErrors(const QList<QSslError> &)));
       
   425 
       
   426     connect(&socket, SIGNAL(connected()), this, SLOT(exitLoop()));
       
   427     connect(&socket, SIGNAL(disconnected()), this, SLOT(exitLoop()));
       
   428     connect(&socket, SIGNAL(modeChanged(QSslSocket::SslMode)), this, SLOT(exitLoop()));
       
   429     connect(&socket, SIGNAL(encrypted()), this, SLOT(exitLoop()));
       
   430     connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(exitLoop()));
       
   431     connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(exitLoop()));
       
   432 
       
   433     // Start connecting
       
   434     socket.connectToHost(QtNetworkSettings::serverName(), 993);
       
   435     QCOMPARE(socket.state(), QAbstractSocket::HostLookupState);
       
   436     enterLoop(10);
       
   437 
       
   438     // Entered connecting state
       
   439 #ifndef Q_OS_SYMBIAN
       
   440     QCOMPARE(socket.state(), QAbstractSocket::ConnectingState);
       
   441     QCOMPARE(connectedSpy.count(), 0);
       
   442 #endif
       
   443     QCOMPARE(hostFoundSpy.count(), 1);
       
   444     QCOMPARE(disconnectedSpy.count(), 0);
       
   445     enterLoop(10);
       
   446 
       
   447     // Entered connected state
       
   448     QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
       
   449     QCOMPARE(socket.mode(), QSslSocket::UnencryptedMode);
       
   450     QVERIFY(!socket.isEncrypted());
       
   451     QCOMPARE(connectedSpy.count(), 1);
       
   452     QCOMPARE(hostFoundSpy.count(), 1);
       
   453     QCOMPARE(disconnectedSpy.count(), 0);
       
   454 
       
   455     // Enter encrypted mode
       
   456     socket.startClientEncryption();
       
   457     QCOMPARE(socket.mode(), QSslSocket::SslClientMode);
       
   458     QVERIFY(!socket.isEncrypted());
       
   459     QCOMPARE(connectionEncryptedSpy.count(), 0);
       
   460     QCOMPARE(sslErrorsSpy.count(), 0);
       
   461 
       
   462     // Starting handshake
       
   463     enterLoop(10);
       
   464     QCOMPARE(sslErrorsSpy.count(), 1);
       
   465     QCOMPARE(connectionEncryptedSpy.count(), 0);
       
   466     QVERIFY(!socket.isEncrypted());
       
   467     QCOMPARE(socket.state(), QAbstractSocket::UnconnectedState);
       
   468 }
       
   469 
       
   470 void tst_QSslSocket::simpleConnectWithIgnore()
       
   471 {
       
   472     if (!QSslSocket::supportsSsl())
       
   473         return;
       
   474 
       
   475     QFETCH_GLOBAL(bool, setProxy);
       
   476     if (setProxy)
       
   477         return;
       
   478 
       
   479     QSslSocket socket;
       
   480     this->socket = &socket;
       
   481     QSignalSpy encryptedSpy(&socket, SIGNAL(encrypted()));
       
   482     QSignalSpy sslErrorsSpy(&socket, SIGNAL(sslErrors(const QList<QSslError> &)));
       
   483 
       
   484     connect(&socket, SIGNAL(readyRead()), this, SLOT(exitLoop()));
       
   485     connect(&socket, SIGNAL(encrypted()), this, SLOT(exitLoop()));
       
   486     connect(&socket, SIGNAL(connected()), this, SLOT(exitLoop()));
       
   487     connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
       
   488     connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(exitLoop()));
       
   489 
       
   490     // Start connecting
       
   491     socket.connectToHost(QtNetworkSettings::serverName(), 993);
       
   492     QCOMPARE(socket.state(), QAbstractSocket::HostLookupState);
       
   493     enterLoop(10);
       
   494 
       
   495     // Start handshake
       
   496     QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
       
   497     socket.startClientEncryption();
       
   498     enterLoop(10);
       
   499 
       
   500     // Done; encryption should be enabled.
       
   501     QCOMPARE(sslErrorsSpy.count(), 1);
       
   502     QVERIFY(socket.isEncrypted());
       
   503     QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
       
   504     QCOMPARE(encryptedSpy.count(), 1);
       
   505 
       
   506     // Wait for incoming data
       
   507     if (!socket.canReadLine())
       
   508         enterLoop(10);
       
   509 
       
   510     QCOMPARE(socket.readAll(), QtNetworkSettings::expectedReplySSL());
       
   511     socket.disconnectFromHost();
       
   512 }
       
   513 
       
   514 void tst_QSslSocket::sslErrors_data()
       
   515 {
       
   516     QTest::addColumn<QString>("host");
       
   517     QTest::addColumn<int>("port");
       
   518     QTest::addColumn<SslErrorList>("expected");
       
   519 
       
   520     QTest::newRow(qPrintable(QtNetworkSettings::serverLocalName()))
       
   521         << QtNetworkSettings::serverLocalName()
       
   522         << 993
       
   523         << (SslErrorList() << QSslError::HostNameMismatch
       
   524                            << QSslError::SelfSignedCertificate);
       
   525 
       
   526     QTest::newRow("imap.trolltech.com")
       
   527         << "imap.trolltech.com"
       
   528         << 993
       
   529         << (SslErrorList() << QSslError::SelfSignedCertificateInChain);
       
   530 }
       
   531 
       
   532 void tst_QSslSocket::sslErrors()
       
   533 {
       
   534     QFETCH(QString, host);
       
   535     QFETCH(int, port);
       
   536     QFETCH(SslErrorList, expected);
       
   537 
       
   538     QSslSocketPtr socket = newSocket();
       
   539     socket->connectToHostEncrypted(host, port);
       
   540     socket->waitForEncrypted(5000);
       
   541 
       
   542     SslErrorList output;
       
   543     foreach (QSslError error, socket->sslErrors()) {
       
   544         output << error.error();
       
   545     }
       
   546 
       
   547 #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
       
   548     if (output.last() == QSslError::CertificateUntrusted)
       
   549         output.takeLast();
       
   550 #endif
       
   551     QCOMPARE(output, expected);
       
   552 }
       
   553 
       
   554 void tst_QSslSocket::addCaCertificate()
       
   555 {
       
   556     if (!QSslSocket::supportsSsl())
       
   557         return;
       
   558 }
       
   559 
       
   560 void tst_QSslSocket::addCaCertificates()
       
   561 {
       
   562     if (!QSslSocket::supportsSsl())
       
   563         return;
       
   564 }
       
   565 
       
   566 void tst_QSslSocket::addCaCertificates2()
       
   567 {
       
   568     if (!QSslSocket::supportsSsl())
       
   569         return;
       
   570 }
       
   571 
       
   572 void tst_QSslSocket::ciphers()
       
   573 {
       
   574     if (!QSslSocket::supportsSsl())
       
   575         return;
       
   576 
       
   577     QSslSocket socket;
       
   578     QCOMPARE(socket.ciphers(), QSslSocket::supportedCiphers());
       
   579     socket.setCiphers(QList<QSslCipher>());
       
   580     QVERIFY(socket.ciphers().isEmpty());
       
   581     socket.setCiphers(socket.defaultCiphers());
       
   582     QCOMPARE(socket.ciphers(), QSslSocket::supportedCiphers());
       
   583     socket.setCiphers(socket.defaultCiphers());
       
   584     QCOMPARE(socket.ciphers(), QSslSocket::supportedCiphers());
       
   585 
       
   586     // Task 164356
       
   587     socket.setCiphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
       
   588 }
       
   589 
       
   590 void tst_QSslSocket::connectToHostEncrypted()
       
   591 {
       
   592     if (!QSslSocket::supportsSsl())
       
   593         return;
       
   594 
       
   595     QSslSocketPtr socket = newSocket();
       
   596     this->socket = socket;
       
   597     QVERIFY(socket->addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")));
       
   598 #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
       
   599     connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
       
   600             this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
       
   601 #endif
       
   602 
       
   603     socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
   604 
       
   605     // This should pass unconditionally when using fluke's CA certificate.
       
   606     // or use untrusted certificate workaround
       
   607     QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
       
   608 
       
   609     socket->disconnectFromHost();
       
   610     QVERIFY(socket->waitForDisconnected());
       
   611 
       
   612     QCOMPARE(socket->mode(), QSslSocket::SslClientMode);
       
   613 
       
   614     socket->connectToHost(QtNetworkSettings::serverName(), 13);
       
   615 
       
   616     QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
       
   617 
       
   618     QVERIFY(socket->waitForDisconnected());
       
   619 }
       
   620 
       
   621 void tst_QSslSocket::connectToHostEncryptedWithVerificationPeerName()
       
   622 {
       
   623     if (!QSslSocket::supportsSsl())
       
   624         return;
       
   625 
       
   626     QSslSocketPtr socket = newSocket();
       
   627     this->socket = socket;
       
   628 
       
   629     socket->addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
       
   630 #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
       
   631     connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
       
   632             this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
       
   633 #endif
       
   634 
       
   635     // connect to the server with its local name, but use the full name for verification.
       
   636     socket->connectToHostEncrypted(QtNetworkSettings::serverLocalName(), 443, QtNetworkSettings::serverName());
       
   637 
       
   638     // This should pass unconditionally when using fluke's CA certificate.
       
   639     QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
       
   640 
       
   641     socket->disconnectFromHost();
       
   642     QVERIFY(socket->waitForDisconnected());
       
   643 
       
   644     QCOMPARE(socket->mode(), QSslSocket::SslClientMode);
       
   645 }
       
   646 
       
   647 void tst_QSslSocket::sessionCipher()
       
   648 {
       
   649     if (!QSslSocket::supportsSsl())
       
   650         return;
       
   651 
       
   652     QSslSocketPtr socket = newSocket();
       
   653     this->socket = socket;
       
   654     connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
       
   655     QVERIFY(socket->sessionCipher().isNull());
       
   656     socket->connectToHost(QtNetworkSettings::serverName(), 443 /* https */);
       
   657     QVERIFY(socket->waitForConnected(5000));
       
   658     QVERIFY(socket->sessionCipher().isNull());
       
   659     socket->startClientEncryption();
       
   660     QVERIFY(socket->waitForEncrypted(5000));
       
   661     QVERIFY(!socket->sessionCipher().isNull());
       
   662     QVERIFY(QSslSocket::supportedCiphers().contains(socket->sessionCipher()));
       
   663     socket->disconnectFromHost();
       
   664     QVERIFY(socket->waitForDisconnected());
       
   665 }
       
   666 
       
   667 void tst_QSslSocket::flush()
       
   668 {
       
   669 }
       
   670 
       
   671 void tst_QSslSocket::isEncrypted()
       
   672 {
       
   673 }
       
   674 
       
   675 void tst_QSslSocket::localCertificate()
       
   676 {
       
   677 }
       
   678 
       
   679 void tst_QSslSocket::mode()
       
   680 {
       
   681 }
       
   682 
       
   683 void tst_QSslSocket::peerCertificate()
       
   684 {
       
   685 }
       
   686 
       
   687 void tst_QSslSocket::peerCertificateChain()
       
   688 {
       
   689     if (!QSslSocket::supportsSsl())
       
   690         return;
       
   691 
       
   692     QSslSocketPtr socket = newSocket();
       
   693     this->socket = socket;
       
   694 
       
   695     QList<QSslCertificate> caCertificates = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
       
   696     QVERIFY(caCertificates.count() == 1);
       
   697     socket->addCaCertificates(caCertificates);
       
   698 #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
       
   699     connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
       
   700             this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
       
   701 #endif
       
   702 
       
   703     socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
   704     QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
       
   705     QVERIFY(socket->peerCertificateChain().isEmpty());
       
   706     QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
       
   707 
       
   708     QList<QSslCertificate> certChain = socket->peerCertificateChain();
       
   709     QVERIFY(certChain.count() > 0);
       
   710     QCOMPARE(certChain.first(), socket->peerCertificate());
       
   711 
       
   712     socket->disconnectFromHost();
       
   713     QVERIFY(socket->waitForDisconnected());
       
   714 
       
   715     // connect again to a different server
       
   716     socket->connectToHostEncrypted("trolltech.com", 443);
       
   717     socket->ignoreSslErrors();
       
   718     QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
       
   719     QVERIFY(socket->peerCertificateChain().isEmpty());
       
   720     QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
       
   721 
       
   722     QCOMPARE(socket->peerCertificateChain().first(), socket->peerCertificate());
       
   723     QVERIFY(socket->peerCertificateChain() != certChain);
       
   724 
       
   725     socket->disconnectFromHost();
       
   726     QVERIFY(socket->waitForDisconnected());
       
   727 
       
   728     // now do it again back to the original server
       
   729     socket->connectToHost(QtNetworkSettings::serverName(), 443);
       
   730     QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
       
   731     QVERIFY(socket->peerCertificateChain().isEmpty());
       
   732     QVERIFY2(socket->waitForConnected(10000), "Network timeout");
       
   733 
       
   734     socket->startClientEncryption();
       
   735     QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
       
   736 
       
   737     QCOMPARE(socket->peerCertificateChain().first(), socket->peerCertificate());
       
   738     QVERIFY(socket->peerCertificateChain() == certChain);
       
   739 
       
   740     socket->disconnectFromHost();
       
   741     QVERIFY(socket->waitForDisconnected());
       
   742 }
       
   743 
       
   744 void tst_QSslSocket::privateKey()
       
   745 {
       
   746 }
       
   747 
       
   748 void tst_QSslSocket::protocol()
       
   749 {
       
   750     if (!QSslSocket::supportsSsl())
       
   751         return;
       
   752 
       
   753     QSslSocketPtr socket = newSocket();
       
   754     this->socket = socket;
       
   755     QList<QSslCertificate> certs = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem");
       
   756 
       
   757 //    qDebug() << "certs:" << certs.at(0).issuerInfo(QSslCertificate::CommonName);
       
   758     socket->setCaCertificates(certs);
       
   759 #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
       
   760     connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
       
   761             this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
       
   762 #endif
       
   763 
       
   764 //    qDebug() << "socket cert:" << socket->caCertificates().at(0).issuerInfo(QSslCertificate::CommonName);
       
   765     QCOMPARE(socket->protocol(), QSsl::SslV3);
       
   766     {
       
   767         // Fluke allows SSLv3.
       
   768         socket->setProtocol(QSsl::SslV3);
       
   769         QCOMPARE(socket->protocol(), QSsl::SslV3);
       
   770         socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
   771         QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
       
   772         QCOMPARE(socket->protocol(), QSsl::SslV3);
       
   773         socket->abort();
       
   774         QCOMPARE(socket->protocol(), QSsl::SslV3);
       
   775         socket->connectToHost(QtNetworkSettings::serverName(), 443);
       
   776         QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
       
   777         socket->startClientEncryption();
       
   778         QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
       
   779         QCOMPARE(socket->protocol(), QSsl::SslV3);
       
   780         socket->abort();
       
   781     }
       
   782     {
       
   783         // Fluke allows TLSV1.
       
   784         socket->setProtocol(QSsl::TlsV1);
       
   785         QCOMPARE(socket->protocol(), QSsl::TlsV1);
       
   786         socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
   787         QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
       
   788         QCOMPARE(socket->protocol(), QSsl::TlsV1);
       
   789         socket->abort();
       
   790         QCOMPARE(socket->protocol(), QSsl::TlsV1);
       
   791         socket->connectToHost(QtNetworkSettings::serverName(), 443);
       
   792         QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
       
   793         socket->startClientEncryption();
       
   794         QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
       
   795         QCOMPARE(socket->protocol(), QSsl::TlsV1);
       
   796         socket->abort();
       
   797     }
       
   798     {
       
   799         // Fluke allows SSLV2.
       
   800         socket->setProtocol(QSsl::SslV2);
       
   801         QCOMPARE(socket->protocol(), QSsl::SslV2);
       
   802         socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
   803         QVERIFY(socket->waitForEncrypted());
       
   804         QCOMPARE(socket->protocol(), QSsl::SslV2);
       
   805         socket->abort();
       
   806         QCOMPARE(socket->protocol(), QSsl::SslV2);
       
   807         socket->connectToHost(QtNetworkSettings::serverName(), 443);
       
   808         QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
       
   809         socket->startClientEncryption();
       
   810         QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
       
   811         socket->abort();
       
   812     }
       
   813     {
       
   814         // Fluke allows SSLV3, so it allows AnyProtocol.
       
   815         socket->setProtocol(QSsl::AnyProtocol);
       
   816         QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
       
   817         socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
   818         QVERIFY(socket->waitForEncrypted());
       
   819         QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
       
   820         socket->abort();
       
   821         QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
       
   822         socket->connectToHost(QtNetworkSettings::serverName(), 443);
       
   823         QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
       
   824         socket->startClientEncryption();
       
   825         QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
       
   826         QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
       
   827         socket->abort();
       
   828     }
       
   829 }
       
   830 
       
   831 void tst_QSslSocket::setCaCertificates()
       
   832 {
       
   833     if (!QSslSocket::supportsSsl())
       
   834         return;
       
   835 
       
   836     QSslSocket socket;
       
   837     QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates());
       
   838     socket.setCaCertificates(QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"));
       
   839     QCOMPARE(socket.caCertificates().size(), 1);
       
   840     socket.setCaCertificates(socket.defaultCaCertificates());
       
   841     QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates());
       
   842 }
       
   843 
       
   844 void tst_QSslSocket::setLocalCertificate()
       
   845 {
       
   846 }
       
   847 
       
   848 void tst_QSslSocket::setPrivateKey()
       
   849 {
       
   850 }
       
   851 
       
   852 void tst_QSslSocket::setProtocol()
       
   853 {
       
   854 }
       
   855 
       
   856 class SslServer : public QTcpServer
       
   857 {
       
   858     Q_OBJECT
       
   859 public:
       
   860     SslServer() : socket(0) { }
       
   861     QSslSocket *socket;
       
   862 
       
   863 protected:
       
   864     void incomingConnection(int socketDescriptor)
       
   865     {
       
   866         socket = new QSslSocket(this);
       
   867         connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
       
   868 
       
   869         QFile file(SRCDIR "certs/fluke.key");
       
   870         QVERIFY(file.open(QIODevice::ReadOnly));
       
   871         QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
       
   872         QVERIFY(!key.isNull());
       
   873         socket->setPrivateKey(key);
       
   874 
       
   875         QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert");
       
   876         QVERIFY(!localCert.isEmpty());
       
   877         QVERIFY(localCert.first().handle());
       
   878         socket->setLocalCertificate(localCert.first());
       
   879 
       
   880         QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState));
       
   881         QVERIFY(!socket->peerAddress().isNull());
       
   882         QVERIFY(socket->peerPort() != 0);
       
   883         QVERIFY(!socket->localAddress().isNull());
       
   884         QVERIFY(socket->localPort() != 0);
       
   885 
       
   886         socket->startServerEncryption();
       
   887     }
       
   888 
       
   889 protected slots:
       
   890     void ignoreErrorSlot()
       
   891     {
       
   892         socket->ignoreSslErrors();
       
   893     }
       
   894 };
       
   895 
       
   896 void tst_QSslSocket::setSocketDescriptor()
       
   897 {
       
   898     if (!QSslSocket::supportsSsl())
       
   899         return;
       
   900 
       
   901     QFETCH_GLOBAL(bool, setProxy);
       
   902     if (setProxy)
       
   903         return;
       
   904 
       
   905     SslServer server;
       
   906     QVERIFY(server.listen());
       
   907 
       
   908     QEventLoop loop;
       
   909     QTimer::singleShot(5000, &loop, SLOT(quit()));
       
   910 
       
   911     QSslSocketPtr client = new QSslSocket;
       
   912     socket = client;
       
   913     connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
       
   914     connect(client, SIGNAL(encrypted()), &loop, SLOT(quit()));
       
   915 
       
   916     client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort());
       
   917 
       
   918     loop.exec();
       
   919 
       
   920     QCOMPARE(client->state(), QAbstractSocket::ConnectedState);
       
   921     QVERIFY(client->isEncrypted());
       
   922     QVERIFY(!client->peerAddress().isNull());
       
   923     QVERIFY(client->peerPort() != 0);
       
   924     QVERIFY(!client->localAddress().isNull());
       
   925     QVERIFY(client->localPort() != 0);
       
   926 }
       
   927 
       
   928 void tst_QSslSocket::waitForEncrypted()
       
   929 {
       
   930     if (!QSslSocket::supportsSsl())
       
   931         return;
       
   932 
       
   933     QSslSocketPtr socket = newSocket();
       
   934     this->socket = socket;
       
   935 
       
   936     connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
       
   937     socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
   938 
       
   939     QVERIFY(socket->waitForEncrypted(10000));
       
   940 }
       
   941 
       
   942 void tst_QSslSocket::waitForConnectedEncryptedReadyRead()
       
   943 {
       
   944     if (!QSslSocket::supportsSsl())
       
   945         return;
       
   946 
       
   947     QSslSocketPtr socket = newSocket();
       
   948     this->socket = socket;
       
   949 
       
   950     connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
       
   951     socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
       
   952 
       
   953 #ifdef Q_OS_SYMBIAN
       
   954     QVERIFY(socket->waitForConnected(10000));
       
   955     QVERIFY(socket->waitForEncrypted(10000));
       
   956 
       
   957     // dont forget to login
       
   958     QCOMPARE((int) socket->write("USER ftptest\r\n"), 14);
       
   959     QCOMPARE((int) socket->write("PASS ftP2Ptf\r\n"), 14);
       
   960 
       
   961     QVERIFY(socket->waitForReadyRead(10000));
       
   962     QVERIFY(!socket->peerCertificate().isNull());
       
   963     QVERIFY(!socket->peerCertificateChain().isEmpty());
       
   964 #else
       
   965     QVERIFY(socket->waitForConnected(10000));
       
   966     QVERIFY(socket->waitForEncrypted(10000));
       
   967     QVERIFY(socket->waitForReadyRead(10000));
       
   968     QVERIFY(!socket->peerCertificate().isNull());
       
   969     QVERIFY(!socket->peerCertificateChain().isEmpty());
       
   970 #endif
       
   971 }
       
   972 
       
   973 void tst_QSslSocket::startClientEncryption()
       
   974 {
       
   975 }
       
   976 
       
   977 void tst_QSslSocket::startServerEncryption()
       
   978 {
       
   979 }
       
   980 
       
   981 void tst_QSslSocket::addDefaultCaCertificate()
       
   982 {
       
   983     if (!QSslSocket::supportsSsl())
       
   984         return;
       
   985 
       
   986     // Reset the global CA chain
       
   987     QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
       
   988 
       
   989     QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem");
       
   990     QCOMPARE(flukeCerts.size(), 1);
       
   991     QList<QSslCertificate> globalCerts = QSslSocket::defaultCaCertificates();
       
   992     QVERIFY(!globalCerts.contains(flukeCerts.first()));
       
   993     QSslSocket::addDefaultCaCertificate(flukeCerts.first());
       
   994     QCOMPARE(QSslSocket::defaultCaCertificates().size(), globalCerts.size() + 1);
       
   995     QVERIFY(QSslSocket::defaultCaCertificates().contains(flukeCerts.first()));
       
   996 
       
   997     // Restore the global CA chain
       
   998     QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
       
   999 }
       
  1000 
       
  1001 void tst_QSslSocket::addDefaultCaCertificates()
       
  1002 {
       
  1003 }
       
  1004 
       
  1005 void tst_QSslSocket::addDefaultCaCertificates2()
       
  1006 {
       
  1007 }
       
  1008 
       
  1009 void tst_QSslSocket::defaultCaCertificates()
       
  1010 {
       
  1011     if (!QSslSocket::supportsSsl())
       
  1012         return;
       
  1013 
       
  1014     QList<QSslCertificate> certs = QSslSocket::defaultCaCertificates();
       
  1015     QVERIFY(certs.size() > 1);
       
  1016     QCOMPARE(certs, QSslSocket::systemCaCertificates());
       
  1017 }
       
  1018 
       
  1019 void tst_QSslSocket::defaultCiphers()
       
  1020 {
       
  1021 }
       
  1022 
       
  1023 void tst_QSslSocket::resetDefaultCiphers()
       
  1024 {
       
  1025 }
       
  1026 
       
  1027 void tst_QSslSocket::setDefaultCaCertificates()
       
  1028 {
       
  1029 }
       
  1030 
       
  1031 void tst_QSslSocket::setDefaultCiphers()
       
  1032 {
       
  1033 }
       
  1034 
       
  1035 void tst_QSslSocket::supportedCiphers()
       
  1036 {
       
  1037     if (!QSslSocket::supportsSsl())
       
  1038         return;
       
  1039 
       
  1040     QList<QSslCipher> ciphers = QSslSocket::supportedCiphers();
       
  1041     QVERIFY(ciphers.size() > 1);
       
  1042 
       
  1043     QSslSocket socket;
       
  1044     QCOMPARE(socket.supportedCiphers(), ciphers);
       
  1045     QCOMPARE(socket.defaultCiphers(), ciphers);
       
  1046     QCOMPARE(socket.ciphers(), ciphers);
       
  1047 }
       
  1048 
       
  1049 void tst_QSslSocket::systemCaCertificates()
       
  1050 {
       
  1051     if (!QSslSocket::supportsSsl())
       
  1052         return;
       
  1053 
       
  1054     QList<QSslCertificate> certs = QSslSocket::systemCaCertificates();
       
  1055     QVERIFY(certs.size() > 1);
       
  1056     QCOMPARE(certs, QSslSocket::defaultCaCertificates());
       
  1057 }
       
  1058 
       
  1059 void tst_QSslSocket::wildcard()
       
  1060 {
       
  1061     QSKIP("TODO: solve wildcard problem", SkipAll);
       
  1062 
       
  1063     if (!QSslSocket::supportsSsl())
       
  1064         return;
       
  1065 
       
  1066     // Fluke runs an apache server listening on port 4443, serving the
       
  1067     // wildcard fluke.*.troll.no.  The DNS entry for
       
  1068     // fluke.wildcard.dev.troll.no, served by ares (root for dev.troll.no),
       
  1069     // returns the CNAME fluke.troll.no for this domain. The web server
       
  1070     // responds with the wildcard, and QSslSocket should accept that as a
       
  1071     // valid connection.  This was broken in 4.3.0.
       
  1072     QSslSocketPtr socket = newSocket();
       
  1073     socket->addCaCertificates(QLatin1String("certs/aspiriniks.ca.crt"));
       
  1074     this->socket = socket;
       
  1075 #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
       
  1076     connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
       
  1077             this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
       
  1078 #endif
       
  1079     socket->connectToHostEncrypted(QtNetworkSettings::wildcardServerName(), 4443);
       
  1080 
       
  1081     QVERIFY2(socket->waitForEncrypted(3000), qPrintable(socket->errorString()));
       
  1082 
       
  1083     QSslCertificate certificate = socket->peerCertificate();
       
  1084     QCOMPARE(certificate.subjectInfo(QSslCertificate::CommonName), QString(QtNetworkSettings::serverLocalName() + ".*." + QtNetworkSettings::serverDomainName()));
       
  1085     QCOMPARE(certificate.issuerInfo(QSslCertificate::CommonName), QtNetworkSettings::serverName());
       
  1086 
       
  1087     socket->close();
       
  1088 }
       
  1089 
       
  1090 class SslServer2 : public QTcpServer
       
  1091 {
       
  1092 protected:
       
  1093     void incomingConnection(int socketDescriptor)
       
  1094     {
       
  1095         QSslSocket *socket = new QSslSocket(this);
       
  1096         socket->ignoreSslErrors();
       
  1097 
       
  1098         // Only set the certificate
       
  1099         QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert");
       
  1100         QVERIFY(!localCert.isEmpty());
       
  1101         QVERIFY(localCert.first().handle());
       
  1102         socket->setLocalCertificate(localCert.first());
       
  1103 
       
  1104         QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState));
       
  1105 
       
  1106         socket->startServerEncryption();
       
  1107     }
       
  1108 };
       
  1109 
       
  1110 void tst_QSslSocket::setEmptyKey()
       
  1111 {
       
  1112     if (!QSslSocket::supportsSsl())
       
  1113         return;
       
  1114 
       
  1115     QFETCH_GLOBAL(bool, setProxy);
       
  1116     if (setProxy)
       
  1117         return;
       
  1118 
       
  1119     SslServer2 server;
       
  1120     server.listen();
       
  1121 
       
  1122     QSslSocket socket;
       
  1123     socket.connectToHostEncrypted("127.0.0.1", server.serverPort());
       
  1124 
       
  1125     QTestEventLoop::instance().enterLoop(2);
       
  1126 
       
  1127     QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
       
  1128     QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
       
  1129 }
       
  1130 
       
  1131 void tst_QSslSocket::spontaneousWrite()
       
  1132 {
       
  1133     QFETCH_GLOBAL(bool, setProxy);
       
  1134     if (setProxy)
       
  1135         return;
       
  1136 
       
  1137     SslServer server;
       
  1138     QSslSocket *receiver = new QSslSocket(this);
       
  1139     connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop()));
       
  1140 
       
  1141     // connect two sockets to each other:
       
  1142     QVERIFY(server.listen(QHostAddress::LocalHost));
       
  1143     receiver->connectToHost("127.0.0.1", server.serverPort());
       
  1144     QVERIFY(receiver->waitForConnected(5000));
       
  1145     QVERIFY(server.waitForNewConnection(0));
       
  1146 
       
  1147     QSslSocket *sender = server.socket;
       
  1148     QVERIFY(sender);
       
  1149     QVERIFY(sender->state() == QAbstractSocket::ConnectedState);
       
  1150     receiver->setObjectName("receiver");
       
  1151     sender->setObjectName("sender");
       
  1152     receiver->ignoreSslErrors();
       
  1153     receiver->startClientEncryption();
       
  1154 
       
  1155     // SSL handshake:
       
  1156     connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop()));
       
  1157     enterLoop(1);
       
  1158     QVERIFY(!timeout());
       
  1159     QVERIFY(sender->isEncrypted());
       
  1160     QVERIFY(receiver->isEncrypted());
       
  1161 
       
  1162     // make sure there's nothing to be received on the sender:
       
  1163     while (sender->waitForReadyRead(10) || receiver->waitForBytesWritten(10)) {}
       
  1164 
       
  1165     // spontaneously write something:
       
  1166     QByteArray data("Hello World");
       
  1167     sender->write(data);
       
  1168 
       
  1169     // check if the other side receives it:
       
  1170     enterLoop(1);
       
  1171     QVERIFY(!timeout());
       
  1172     QCOMPARE(receiver->bytesAvailable(), qint64(data.size()));
       
  1173     QCOMPARE(receiver->readAll(), data);
       
  1174 }
       
  1175 
       
  1176 void tst_QSslSocket::setReadBufferSize()
       
  1177 {
       
  1178     QFETCH_GLOBAL(bool, setProxy);
       
  1179     if (setProxy)
       
  1180         return;
       
  1181 
       
  1182     SslServer server;
       
  1183     QSslSocket *receiver = new QSslSocket(this);
       
  1184     connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop()));
       
  1185 
       
  1186     // connect two sockets to each other:
       
  1187     QVERIFY(server.listen(QHostAddress::LocalHost));
       
  1188     receiver->connectToHost("127.0.0.1", server.serverPort());
       
  1189     QVERIFY(receiver->waitForConnected(5000));
       
  1190     QVERIFY(server.waitForNewConnection(0));
       
  1191 
       
  1192     QSslSocket *sender = server.socket;
       
  1193     QVERIFY(sender);
       
  1194     QVERIFY(sender->state() == QAbstractSocket::ConnectedState);
       
  1195     receiver->setObjectName("receiver");
       
  1196     sender->setObjectName("sender");
       
  1197     receiver->ignoreSslErrors();
       
  1198     receiver->startClientEncryption();
       
  1199 
       
  1200     // SSL handshake:
       
  1201     connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop()));
       
  1202     enterLoop(1);
       
  1203     QVERIFY(!timeout());
       
  1204     QVERIFY(sender->isEncrypted());
       
  1205     QVERIFY(receiver->isEncrypted());
       
  1206 
       
  1207     QByteArray data(2048, 'b');
       
  1208     receiver->setReadBufferSize(39 * 1024); // make it a non-multiple of the data.size()
       
  1209 
       
  1210     // saturate the incoming buffer
       
  1211     while (sender->state() == QAbstractSocket::ConnectedState &&
       
  1212            receiver->state() == QAbstractSocket::ConnectedState &&
       
  1213            receiver->bytesAvailable() < receiver->readBufferSize()) {
       
  1214         sender->write(data);
       
  1215         //qDebug() << receiver->bytesAvailable() << "<" << receiver->readBufferSize() << (receiver->bytesAvailable() < receiver->readBufferSize());
       
  1216 
       
  1217         while (sender->bytesToWrite())
       
  1218             QVERIFY(sender->waitForBytesWritten(10));
       
  1219 
       
  1220         // drain it:
       
  1221         while (receiver->bytesAvailable() < receiver->readBufferSize() &&
       
  1222                receiver->waitForReadyRead(10)) {}
       
  1223     }
       
  1224 
       
  1225     //qDebug() << sender->bytesToWrite() << "bytes to write";
       
  1226     //qDebug() << receiver->bytesAvailable() << "bytes available";
       
  1227 
       
  1228     // send a bit more
       
  1229     sender->write(data);
       
  1230     sender->write(data);
       
  1231     sender->write(data);
       
  1232     sender->write(data);
       
  1233     QVERIFY(sender->waitForBytesWritten(10));
       
  1234 
       
  1235     qint64 oldBytesAvailable = receiver->bytesAvailable();
       
  1236 
       
  1237     // now unset the read buffer limit and iterate
       
  1238     receiver->setReadBufferSize(0);
       
  1239     enterLoop(1);
       
  1240     QVERIFY(!timeout());
       
  1241 
       
  1242     QVERIFY(receiver->bytesAvailable() > oldBytesAvailable);
       
  1243 }
       
  1244 
       
  1245 class SetReadBufferSize_task_250027_handler : public QObject {
       
  1246     Q_OBJECT
       
  1247 public slots:
       
  1248     void readyReadSlot() {
       
  1249         QTestEventLoop::instance().exitLoop();
       
  1250     }
       
  1251     void waitSomeMore(QSslSocket *socket) {
       
  1252         QTime t;
       
  1253         t.start();
       
  1254         while (!socket->encryptedBytesAvailable()) {
       
  1255             QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents, 250);
       
  1256             if (t.elapsed() > 1000 || socket->state() != QAbstractSocket::ConnectedState)
       
  1257                 return;
       
  1258         }
       
  1259     }
       
  1260 };
       
  1261 
       
  1262 void tst_QSslSocket::setReadBufferSize_task_250027()
       
  1263 {
       
  1264     // do not execute this when a proxy is set.
       
  1265     QFETCH_GLOBAL(bool, setProxy);
       
  1266     if (setProxy)
       
  1267         return;
       
  1268 
       
  1269     QSslSocketPtr socket = newSocket();
       
  1270     socket->setReadBufferSize(1000); // limit to 1 kb/sec
       
  1271     socket->ignoreSslErrors();
       
  1272     socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
  1273     socket->ignoreSslErrors();
       
  1274     QVERIFY(socket->waitForConnected(10*1000));
       
  1275     QVERIFY(socket->waitForEncrypted(10*1000));
       
  1276 
       
  1277     // exit the event loop as soon as we receive a readyRead()
       
  1278     SetReadBufferSize_task_250027_handler setReadBufferSize_task_250027_handler;
       
  1279     connect(socket, SIGNAL(readyRead()), &setReadBufferSize_task_250027_handler, SLOT(readyReadSlot()));
       
  1280 
       
  1281     // provoke a response by sending a request
       
  1282     socket->write("GET /gif/fluke.gif HTTP/1.0\n"); // this file is 27 KB
       
  1283     socket->write("Host: ");
       
  1284     socket->write(QtNetworkSettings::serverName().toLocal8Bit().constData());
       
  1285     socket->write("\n");
       
  1286     socket->write("Connection: close\n");
       
  1287     socket->write("\n");
       
  1288     socket->flush();
       
  1289 
       
  1290     QTestEventLoop::instance().enterLoop(10);
       
  1291     setReadBufferSize_task_250027_handler.waitSomeMore(socket);
       
  1292     QByteArray firstRead = socket->readAll();
       
  1293     // First read should be some data, but not the whole file
       
  1294     QVERIFY(firstRead.size() > 0 && firstRead.size() < 20*1024);
       
  1295 
       
  1296     QTestEventLoop::instance().enterLoop(10);
       
  1297     setReadBufferSize_task_250027_handler.waitSomeMore(socket);
       
  1298     QByteArray secondRead = socket->readAll();
       
  1299     // second read should be some more data
       
  1300     QVERIFY(secondRead.size() > 0);
       
  1301 
       
  1302     socket->close();
       
  1303 }
       
  1304 
       
  1305 class SslServer3 : public QTcpServer
       
  1306 {
       
  1307     Q_OBJECT
       
  1308 public:
       
  1309     SslServer3() : socket(0) { }
       
  1310     QSslSocket *socket;
       
  1311 
       
  1312 protected:
       
  1313     void incomingConnection(int socketDescriptor)
       
  1314     {
       
  1315         socket = new QSslSocket(this);
       
  1316         connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
       
  1317 
       
  1318         QFile file(SRCDIR "certs/fluke.key");
       
  1319         QVERIFY(file.open(QIODevice::ReadOnly));
       
  1320         QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
       
  1321         QVERIFY(!key.isNull());
       
  1322         socket->setPrivateKey(key);
       
  1323 
       
  1324         QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert");
       
  1325         QVERIFY(!localCert.isEmpty());
       
  1326         QVERIFY(localCert.first().handle());
       
  1327         socket->setLocalCertificate(localCert.first());
       
  1328 
       
  1329         QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState));
       
  1330         QVERIFY(!socket->peerAddress().isNull());
       
  1331         QVERIFY(socket->peerPort() != 0);
       
  1332         QVERIFY(!socket->localAddress().isNull());
       
  1333         QVERIFY(socket->localPort() != 0);
       
  1334     }
       
  1335 
       
  1336 protected slots:
       
  1337     void ignoreErrorSlot()
       
  1338     {
       
  1339         socket->ignoreSslErrors();
       
  1340     }
       
  1341 };
       
  1342 
       
  1343 class ThreadedSslServer: public QThread
       
  1344 {
       
  1345     Q_OBJECT
       
  1346 public:
       
  1347     QSemaphore dataReadSemaphore;
       
  1348     int serverPort;
       
  1349     bool ok;
       
  1350 
       
  1351     ThreadedSslServer() : serverPort(-1), ok(false)
       
  1352     { }
       
  1353 
       
  1354     ~ThreadedSslServer()
       
  1355     {
       
  1356         if (isRunning()) wait(2000);
       
  1357         QVERIFY(ok);
       
  1358     }
       
  1359 
       
  1360 signals:
       
  1361     void listening();
       
  1362 
       
  1363 protected:
       
  1364     void run()
       
  1365     {
       
  1366         // if all goes well (no timeouts), this thread will sleep for a total of 500 ms
       
  1367         // (i.e., 5 times 100 ms, one sleep for each operation)
       
  1368 
       
  1369         SslServer3 server;
       
  1370         server.listen(QHostAddress::LocalHost);
       
  1371         serverPort = server.serverPort();
       
  1372         emit listening();
       
  1373 
       
  1374         // delayed acceptance:
       
  1375         QTest::qSleep(100);
       
  1376 #ifndef Q_OS_SYMBIAN
       
  1377         bool ret = server.waitForNewConnection(2000);
       
  1378 #else
       
  1379         bool ret = server.waitForNewConnection(20000);
       
  1380 #endif
       
  1381 
       
  1382         // delayed start of encryption
       
  1383         QTest::qSleep(100);
       
  1384         QSslSocket *socket = server.socket;
       
  1385         Q_ASSERT(socket);
       
  1386         Q_ASSERT(socket->isValid());
       
  1387         socket->ignoreSslErrors();
       
  1388         socket->startServerEncryption();
       
  1389         if (!socket->waitForEncrypted(2000))
       
  1390             return;             // error
       
  1391 
       
  1392         // delayed reading data
       
  1393         QTest::qSleep(100);
       
  1394         if (!socket->waitForReadyRead(2000))
       
  1395             return;             // error
       
  1396         socket->readAll();
       
  1397         dataReadSemaphore.release();
       
  1398 
       
  1399         // delayed sending data
       
  1400         QTest::qSleep(100);
       
  1401         socket->write("Hello, World");
       
  1402         while (socket->bytesToWrite())
       
  1403             if (!socket->waitForBytesWritten(2000))
       
  1404                 return;         // error
       
  1405 
       
  1406         // delayed replying (reading then sending)
       
  1407         QTest::qSleep(100);
       
  1408         if (!socket->waitForReadyRead(2000))
       
  1409             return;             // error
       
  1410         socket->write("Hello, World");
       
  1411         while (socket->bytesToWrite())
       
  1412             if (!socket->waitForBytesWritten(2000))
       
  1413                 return;         // error
       
  1414 
       
  1415         // delayed disconnection:
       
  1416         QTest::qSleep(100);
       
  1417         socket->disconnectFromHost();
       
  1418         if (!socket->waitForDisconnected(2000))
       
  1419             return;             // error
       
  1420 
       
  1421         delete socket;
       
  1422         ok = true;
       
  1423     }
       
  1424 };
       
  1425 
       
  1426 void tst_QSslSocket::waitForMinusOne()
       
  1427 {
       
  1428     QFETCH_GLOBAL(bool, setProxy);
       
  1429     if (setProxy)
       
  1430         return;
       
  1431 
       
  1432     ThreadedSslServer server;
       
  1433     connect(&server, SIGNAL(listening()), SLOT(exitLoop()));
       
  1434 
       
  1435     // start the thread and wait for it to be ready
       
  1436     server.start();
       
  1437     enterLoop(1);
       
  1438     QVERIFY(!timeout());
       
  1439 
       
  1440     // connect to the server
       
  1441     QSslSocket socket;
       
  1442     QTest::qSleep(100);
       
  1443     socket.connectToHost("127.0.0.1", server.serverPort);
       
  1444     QVERIFY(socket.waitForConnected(-1));
       
  1445     socket.ignoreSslErrors();
       
  1446     socket.startClientEncryption();
       
  1447 
       
  1448     // first verification: this waiting should take 200 ms
       
  1449     QVERIFY2(socket.waitForEncrypted(-1), qPrintable(socket.errorString()));
       
  1450     QVERIFY(socket.isEncrypted());
       
  1451     QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
       
  1452     QCOMPARE(socket.bytesAvailable(), Q_INT64_C(0));
       
  1453 
       
  1454     // second verification: write and make sure the other side got it (100 ms)
       
  1455     socket.write("How are you doing?");
       
  1456     QVERIFY(socket.bytesToWrite() != 0);
       
  1457     QVERIFY(socket.waitForBytesWritten(-1));
       
  1458     QVERIFY(server.dataReadSemaphore.tryAcquire(1, 2000));
       
  1459 
       
  1460     // third verification: it should wait for 100 ms:
       
  1461     QVERIFY(socket.waitForReadyRead(-1));
       
  1462     QVERIFY(socket.isEncrypted());
       
  1463     QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
       
  1464     QVERIFY(socket.bytesAvailable() != 0);
       
  1465 
       
  1466     // fourth verification: deadlock prevention:
       
  1467     // we write and then wait for reading; the other side needs to receive before
       
  1468     // replying (100 ms delay)
       
  1469     socket.write("I'm doing just fine!");
       
  1470     QVERIFY(socket.bytesToWrite() != 0);
       
  1471     QVERIFY(socket.waitForReadyRead(-1));
       
  1472 
       
  1473     // fifth verification: it should wait for 200 ms more
       
  1474     QVERIFY(socket.waitForDisconnected(-1));
       
  1475 }
       
  1476 
       
  1477 class VerifyServer : public QTcpServer
       
  1478 {
       
  1479     Q_OBJECT
       
  1480 public:
       
  1481     VerifyServer() : socket(0) { }
       
  1482     QSslSocket *socket;
       
  1483 
       
  1484 protected:
       
  1485     void incomingConnection(int socketDescriptor)
       
  1486     {
       
  1487         socket = new QSslSocket(this);
       
  1488 
       
  1489         socket->setPrivateKey(SRCDIR "certs/fluke.key");
       
  1490         socket->setLocalCertificate(SRCDIR "certs/fluke.cert");
       
  1491         socket->setSocketDescriptor(socketDescriptor);
       
  1492         socket->startServerEncryption();
       
  1493     }
       
  1494 };
       
  1495 
       
  1496 void tst_QSslSocket::verifyMode()
       
  1497 {
       
  1498     QFETCH_GLOBAL(bool, setProxy);
       
  1499     if (setProxy)
       
  1500         return;
       
  1501 
       
  1502     QSslSocket socket;
       
  1503     QCOMPARE(socket.peerVerifyMode(), QSslSocket::AutoVerifyPeer);
       
  1504     socket.setPeerVerifyMode(QSslSocket::VerifyNone);
       
  1505     QCOMPARE(socket.peerVerifyMode(), QSslSocket::VerifyNone);
       
  1506     socket.setPeerVerifyMode(QSslSocket::VerifyNone);
       
  1507     socket.setPeerVerifyMode(QSslSocket::VerifyPeer);
       
  1508     QCOMPARE(socket.peerVerifyMode(), QSslSocket::VerifyPeer);
       
  1509 
       
  1510     socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
  1511     QVERIFY(!socket.waitForEncrypted());
       
  1512 
       
  1513     QList<QSslError> expectedErrors = QList<QSslError>()
       
  1514                                       << QSslError(QSslError::SelfSignedCertificate, socket.peerCertificate());
       
  1515     QCOMPARE(socket.sslErrors(), expectedErrors);
       
  1516     socket.abort();
       
  1517 
       
  1518     VerifyServer server;
       
  1519     server.listen();
       
  1520 
       
  1521     QSslSocket clientSocket;
       
  1522     clientSocket.connectToHostEncrypted("127.0.0.1", server.serverPort());
       
  1523     clientSocket.ignoreSslErrors();
       
  1524 
       
  1525     QEventLoop loop;
       
  1526     QTimer::singleShot(5000, &loop, SLOT(quit()));
       
  1527     connect(&clientSocket, SIGNAL(encrypted()), &loop, SLOT(quit()));
       
  1528     loop.exec();
       
  1529 
       
  1530     QVERIFY(clientSocket.isEncrypted());
       
  1531     QVERIFY(server.socket->sslErrors().isEmpty());
       
  1532 }
       
  1533 
       
  1534 void tst_QSslSocket::verifyDepth()
       
  1535 {
       
  1536     QSslSocket socket;
       
  1537     QCOMPARE(socket.peerVerifyDepth(), 0);
       
  1538     socket.setPeerVerifyDepth(1);
       
  1539     QCOMPARE(socket.peerVerifyDepth(), 1);
       
  1540     QTest::ignoreMessage(QtWarningMsg, "QSslSocket::setPeerVerifyDepth: cannot set negative depth of -1");
       
  1541     socket.setPeerVerifyDepth(-1);
       
  1542     QCOMPARE(socket.peerVerifyDepth(), 1);
       
  1543 }
       
  1544 
       
  1545 void tst_QSslSocket::peerVerifyError()
       
  1546 {
       
  1547     QSslSocketPtr socket = newSocket();
       
  1548     QSignalSpy sslErrorsSpy(socket, SIGNAL(sslErrors(QList<QSslError>)));
       
  1549     QSignalSpy peerVerifyErrorSpy(socket, SIGNAL(peerVerifyError(QSslError)));
       
  1550 
       
  1551     socket->connectToHostEncrypted(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(), 443);
       
  1552     QVERIFY(!socket->waitForEncrypted(10000));
       
  1553     QVERIFY(!peerVerifyErrorSpy.isEmpty());
       
  1554     QVERIFY(!sslErrorsSpy.isEmpty());
       
  1555     QCOMPARE(qVariantValue<QSslError>(peerVerifyErrorSpy.last().at(0)).error(), QSslError::HostNameMismatch);
       
  1556     QCOMPARE(qVariantValue<QList<QSslError> >(sslErrorsSpy.at(0).at(0)).size(), peerVerifyErrorSpy.size());
       
  1557 }
       
  1558 
       
  1559 void tst_QSslSocket::disconnectFromHostWhenConnecting()
       
  1560 {
       
  1561     QSslSocketPtr socket = newSocket();
       
  1562     socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
       
  1563     socket->ignoreSslErrors();
       
  1564     socket->write("XXXX LOGOUT\r\n");
       
  1565     QAbstractSocket::SocketState state = socket->state();
       
  1566     // without proxy, the state will be HostLookupState;
       
  1567     // with    proxy, the state will be ConnectingState.
       
  1568     QVERIFY(socket->state() == QAbstractSocket::HostLookupState ||
       
  1569             socket->state() == QAbstractSocket::ConnectingState);
       
  1570     socket->disconnectFromHost();
       
  1571     // the state of the socket must be the same before and after calling
       
  1572     // disconnectFromHost()
       
  1573     QCOMPARE(state, socket->state());
       
  1574     QVERIFY(socket->state() == QAbstractSocket::HostLookupState ||
       
  1575             socket->state() == QAbstractSocket::ConnectingState);
       
  1576     QVERIFY(socket->waitForDisconnected(5000));
       
  1577     QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
       
  1578     // we did not call close, so the socket must be still open
       
  1579     QVERIFY(socket->isOpen());
       
  1580     QCOMPARE(socket->bytesToWrite(), qint64(0));
       
  1581 
       
  1582     // dont forget to login
       
  1583     QCOMPARE((int) socket->write("USER ftptest\r\n"), 14);
       
  1584 
       
  1585 }
       
  1586 
       
  1587 void tst_QSslSocket::disconnectFromHostWhenConnected()
       
  1588 {
       
  1589     QSslSocketPtr socket = newSocket();
       
  1590     socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
       
  1591     socket->ignoreSslErrors();
       
  1592 #ifndef Q_OS_SYMBIAN
       
  1593     QVERIFY(socket->waitForEncrypted(5000));
       
  1594 #else
       
  1595     QVERIFY(socket->waitForEncrypted(10000));
       
  1596 #endif
       
  1597     socket->write("XXXX LOGOUT\r\n");
       
  1598     QCOMPARE(socket->state(), QAbstractSocket::ConnectedState);
       
  1599     socket->disconnectFromHost();
       
  1600     QCOMPARE(socket->state(), QAbstractSocket::ClosingState);
       
  1601 #ifdef Q_OS_SYMBIAN
       
  1602     // I don't understand how socket->waitForDisconnected can work on other platforms
       
  1603     // since socket->write will end to:
       
  1604     //   QMetaObject::invokeMethod(this, "_q_flushWriteBuffer", Qt::QueuedConnection);
       
  1605     // In order that _q_flushWriteBuffer will be called the eventloop need to run
       
  1606     // If we just call waitForDisconnected, which blocks the whole thread how that can happen?
       
  1607     connect(socket, SIGNAL(disconnected()), this, SLOT(exitLoop()));
       
  1608     enterLoop(5);
       
  1609     QVERIFY(!timeout());
       
  1610 #else
       
  1611     QVERIFY(socket->waitForDisconnected(5000));
       
  1612 #endif
       
  1613     QCOMPARE(socket->bytesToWrite(), qint64(0));
       
  1614 }
       
  1615 
       
  1616 void tst_QSslSocket::resetProxy()
       
  1617 {
       
  1618     QFETCH_GLOBAL(bool, setProxy);
       
  1619     if (setProxy)
       
  1620         return;
       
  1621 
       
  1622     // check fix for bug 199941
       
  1623 
       
  1624     QNetworkProxy goodProxy(QNetworkProxy::NoProxy);
       
  1625     QNetworkProxy badProxy(QNetworkProxy::HttpProxy, "thisCannotWorkAbsolutelyNotForSure", 333);
       
  1626 
       
  1627     // make sure the connection works, and then set a nonsense proxy, and then
       
  1628     // make sure it does not work anymore
       
  1629     QSslSocket socket;
       
  1630     socket.addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
       
  1631     socket.setProxy(goodProxy);
       
  1632     socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
  1633     QVERIFY2(socket.waitForConnected(10000), qPrintable(socket.errorString()));
       
  1634     socket.abort();
       
  1635     socket.setProxy(badProxy);
       
  1636     socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
  1637     QVERIFY(! socket.waitForConnected(10000));
       
  1638 
       
  1639     // dont forget to login
       
  1640     QCOMPARE((int) socket.write("USER ftptest\r\n"), 14);
       
  1641     QCOMPARE((int) socket.write("PASS password\r\n"), 15);
       
  1642 
       
  1643     enterLoop(10);
       
  1644 
       
  1645     // now the other way round:
       
  1646     // set the nonsense proxy and make sure the connection does not work,
       
  1647     // and then set the right proxy and make sure it works
       
  1648     QSslSocket socket2;
       
  1649     socket2.addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
       
  1650     socket2.setProxy(badProxy);
       
  1651     socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
  1652     QVERIFY(! socket2.waitForConnected(10000));
       
  1653     socket2.abort();
       
  1654     socket2.setProxy(goodProxy);
       
  1655     socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
  1656     QVERIFY2(socket2.waitForConnected(10000), qPrintable(socket.errorString()));
       
  1657 }
       
  1658 
       
  1659 void tst_QSslSocket::ignoreSslErrorsList_data()
       
  1660 {
       
  1661     QTest::addColumn<QList<QSslError> >("expectedSslErrors");
       
  1662     QTest::addColumn<int>("expectedSslErrorSignalCount");
       
  1663 
       
  1664     // construct the list of errors that we will get with the SSL handshake and that we will ignore
       
  1665     QList<QSslError> expectedSslErrors;
       
  1666     // fromPath gives us a list of certs, but it actually only contains one
       
  1667     QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
       
  1668     QSslError rightError(QSslError::SelfSignedCertificate, certs.at(0));
       
  1669     QSslError wrongError(QSslError::SelfSignedCertificate);
       
  1670 
       
  1671 
       
  1672     QTest::newRow("SSL-failure-empty-list") << expectedSslErrors << 1;
       
  1673     expectedSslErrors.append(wrongError);
       
  1674     QTest::newRow("SSL-failure-wrong-error") << expectedSslErrors << 1;
       
  1675     expectedSslErrors.append(rightError);
       
  1676     QTest::newRow("allErrorsInExpectedList1") << expectedSslErrors << 0;
       
  1677     expectedSslErrors.removeAll(wrongError);
       
  1678     QTest::newRow("allErrorsInExpectedList2") << expectedSslErrors << 0;
       
  1679     expectedSslErrors.removeAll(rightError);
       
  1680     QTest::newRow("SSL-failure-empty-list-again") << expectedSslErrors << 1;
       
  1681 }
       
  1682 
       
  1683 void tst_QSslSocket::ignoreSslErrorsList()
       
  1684 {
       
  1685     QSslSocket socket;
       
  1686     connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
       
  1687             this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
       
  1688 
       
  1689 //    this->socket = &socket;
       
  1690     QSslCertificate cert;
       
  1691 
       
  1692     QFETCH(QList<QSslError>, expectedSslErrors);
       
  1693     socket.ignoreSslErrors(expectedSslErrors);
       
  1694 
       
  1695     QFETCH(int, expectedSslErrorSignalCount);
       
  1696     QSignalSpy sslErrorsSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
       
  1697 
       
  1698     socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
  1699 
       
  1700     bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
       
  1701     QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess);
       
  1702     QCOMPARE(sslErrorsSpy.count(), expectedSslErrorSignalCount);
       
  1703 }
       
  1704 
       
  1705 void tst_QSslSocket::ignoreSslErrorsListWithSlot_data()
       
  1706 {
       
  1707     ignoreSslErrorsList_data();
       
  1708 }
       
  1709 
       
  1710 // this is not a test, just a slot called in the test below
       
  1711 void tst_QSslSocket::ignoreErrorListSlot(const QList<QSslError> &)
       
  1712 {
       
  1713     socket->ignoreSslErrors(storedExpectedSslErrors);
       
  1714 }
       
  1715 
       
  1716 void tst_QSslSocket::ignoreSslErrorsListWithSlot()
       
  1717 {
       
  1718     QSslSocket socket;
       
  1719     this->socket = &socket;
       
  1720 
       
  1721     QFETCH(QList<QSslError>, expectedSslErrors);
       
  1722     // store the errors to ignore them later in the slot connected below
       
  1723     storedExpectedSslErrors = expectedSslErrors;
       
  1724     connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
       
  1725             this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
       
  1726     connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)),
       
  1727             this, SLOT(ignoreErrorListSlot(const QList<QSslError> &)));
       
  1728     socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
  1729 
       
  1730     QFETCH(int, expectedSslErrorSignalCount);
       
  1731     bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
       
  1732     QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess);
       
  1733 }
       
  1734 
       
  1735 // make sure a closed socket has no bytesAvailable()
       
  1736 // related to https://bugs.webkit.org/show_bug.cgi?id=28016
       
  1737 void tst_QSslSocket::readFromClosedSocket()
       
  1738 {
       
  1739     QSslSocketPtr socket = newSocket();
       
  1740     socket->ignoreSslErrors();
       
  1741     socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
  1742     socket->ignoreSslErrors();
       
  1743     socket->waitForConnected();
       
  1744     socket->waitForEncrypted();
       
  1745     // provoke a response by sending a request
       
  1746     socket->write("GET /gif/fluke.gif HTTP/1.1\n");
       
  1747     socket->write("Host: ");
       
  1748     socket->write(QtNetworkSettings::serverName().toLocal8Bit().constData());
       
  1749     socket->write("\n");
       
  1750     socket->write("\n");
       
  1751     socket->waitForBytesWritten();
       
  1752     socket->waitForReadyRead();
       
  1753     QVERIFY(socket->state() == QAbstractSocket::ConnectedState);
       
  1754     QVERIFY(socket->bytesAvailable());
       
  1755     socket->close();
       
  1756     QVERIFY(!socket->bytesAvailable());
       
  1757     QVERIFY(!socket->bytesToWrite());
       
  1758     socket->waitForDisconnected();
       
  1759     QVERIFY(!socket->bytesAvailable());
       
  1760     QVERIFY(!socket->bytesToWrite());
       
  1761 }
       
  1762 
       
  1763 void tst_QSslSocket::writeBigChunk()
       
  1764 {
       
  1765     if (!QSslSocket::supportsSsl())
       
  1766         return;
       
  1767 
       
  1768     QSslSocketPtr socket = newSocket();
       
  1769     this->socket = socket;
       
  1770 
       
  1771     connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
       
  1772     socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
       
  1773 
       
  1774     QByteArray data;
       
  1775     data.resize(1024*1024*10); // 10 MB
       
  1776     // init with garbage. needed so ssl cannot compress it in an efficient way.
       
  1777     for (int i = 0; i < data.size() / sizeof(int); i++) {
       
  1778         int r = qrand();
       
  1779         data.data()[i*sizeof(int)] = r;
       
  1780     }
       
  1781 
       
  1782     QVERIFY(socket->waitForEncrypted(10000));
       
  1783     QString errorBefore = socket->errorString();
       
  1784 
       
  1785     int ret = socket->write(data.constData(), data.size());
       
  1786     QVERIFY(data.size() == ret);
       
  1787 
       
  1788     // spin the event loop once so QSslSocket::transmit() gets called
       
  1789     QCoreApplication::processEvents();
       
  1790     QString errorAfter = socket->errorString();
       
  1791 
       
  1792     // no better way to do this right now since the error is the same as the default error.
       
  1793     if (socket->errorString().startsWith(QLatin1String("Unable to write data")))
       
  1794     {
       
  1795         qWarning() << socket->error() << socket->errorString();
       
  1796         QFAIL("Error while writing! Check if the OpenSSL BIO size is limited?!");
       
  1797     }
       
  1798     // also check the error string. If another error (than UnknownError) occured, it should be different than before
       
  1799     QVERIFY(errorBefore == errorAfter);
       
  1800  
       
  1801     // check that everything has been written to OpenSSL
       
  1802     QVERIFY(socket->bytesToWrite() == 0);
       
  1803 
       
  1804     socket->close();
       
  1805 }
       
  1806 
       
  1807 #endif // QT_NO_OPENSSL
       
  1808 
       
  1809 QTEST_MAIN(tst_QSslSocket)
       
  1810 #include "tst_qsslsocket.moc"