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