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