1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
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
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.
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.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
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>
54 #include <QNetworkProxy>
55 #include <QAuthenticator>
57 #include "private/qhostinfo_p.h"
58 #include "private/qsslsocket_openssl_p.h"
60 #include "../network-settings.h"
62 Q_DECLARE_METATYPE(QAbstractSocket::SocketState)
63 Q_DECLARE_METATYPE(QAbstractSocket::SocketError)
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)
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
84 class QSslSocketPtr: public QSharedPointer<QSslSocket>
87 inline QSslSocketPtr(QSslSocket *ptr = 0)
88 : QSharedPointer<QSslSocket>(ptr)
91 inline operator QSslSocket *() const { return data(); }
95 class tst_QSslSocket : public QObject
103 virtual ~tst_QSslSocket();
105 static void enterLoop(int secs)
108 QTestEventLoop::instance().enterLoop(secs);
111 static bool timeout()
113 return QTestEventLoop::instance().timeout();
116 #ifndef QT_NO_OPENSSL
117 QSslSocketPtr newSocket();
121 void initTestCase_data();
124 void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth);
126 #ifndef QT_NO_OPENSSL
129 void simpleConnect();
130 void simpleConnectWithIgnore();
133 void sslErrors_data();
135 void addCaCertificate();
136 void addCaCertificates();
137 void addCaCertificates2();
139 void connectToHostEncrypted();
140 void connectToHostEncryptedWithVerificationPeerName();
141 void sessionCipher();
144 void localCertificate();
146 void peerCertificate();
147 void peerCertificateChain();
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();
175 void spontaneousWrite();
176 void setReadBufferSize();
177 void setReadBufferSize_task_250027();
178 void waitForMinusOne();
181 void peerVerifyError();
182 void disconnectFromHostWhenConnecting();
183 void disconnectFromHostWhenConnected();
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();
194 static void exitLoop()
196 // Safe exit - if we aren't in an event loop, don't
200 QTestEventLoop::instance().exitLoop();
205 void ignoreErrorSlot()
207 socket->ignoreSslErrors();
209 void untrustedWorkaroundSlot(const QList<QSslError> &errors)
211 if (errors.size() == 1 &&
212 (errors.first().error() == QSslError::CertificateUntrusted ||
213 errors.first().error() == QSslError::SelfSignedCertificate))
214 socket->ignoreSslErrors();
216 void ignoreErrorListSlot(const QList<QSslError> &errors);
220 QList<QSslError> storedExpectedSslErrors;
221 #endif // QT_NO_OPENSSL
223 static int loopLevel;
226 int tst_QSslSocket::loopLevel = 0;
228 tst_QSslSocket::tst_QSslSocket()
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");
240 tst_QSslSocket::~tst_QSslSocket()
256 void tst_QSslSocket::initTestCase_data()
258 QTest::addColumn<bool>("setProxy");
259 QTest::addColumn<int>("proxyType");
261 QTest::newRow("WithoutProxy") << false << 0;
262 QTest::newRow("WithSocks5Proxy") << true << int(Socks5Proxy);
263 QTest::newRow("WithSocks5ProxyAuth") << true << int(Socks5Proxy | AuthBasic);
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);
271 void tst_QSslSocket::init()
273 QFETCH_GLOBAL(bool, setProxy);
275 QFETCH_GLOBAL(int, proxyType);
276 QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
281 proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1080);
284 case Socks5Proxy | AuthBasic:
285 proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1081);
288 case HttpProxy | NoAuth:
289 proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3128);
292 case HttpProxy | AuthBasic:
293 proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3129);
296 case HttpProxy | AuthNtlm:
297 proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3130);
300 QNetworkProxy::setApplicationProxy(proxy);
303 qt_qhostinfo_clear_cache();
306 void tst_QSslSocket::cleanup()
308 QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
311 #ifndef QT_NO_OPENSSL
312 QSslSocketPtr tst_QSslSocket::newSocket()
314 QSslSocket *socket = new QSslSocket;
317 connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
318 SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
319 Qt::DirectConnection);
321 return QSslSocketPtr(socket);
325 void tst_QSslSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
328 auth->setUser("qsockstest");
329 auth->setPassword("password");
332 #ifndef QT_NO_OPENSSL
334 void tst_QSslSocket::constructing()
336 if (!QSslSocket::supportsSsl())
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"));
352 QVERIFY(!socket.getChar(&c));
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));
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);
396 QSslConfiguration savedDefault = QSslConfiguration::defaultConfiguration();
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());
407 // verify the default as well:
408 QVERIFY(QSslConfiguration::defaultConfiguration().caCertificates().isEmpty());
409 QVERIFY(QSslConfiguration::defaultConfiguration().ciphers().isEmpty());
411 QSslConfiguration::setDefaultConfiguration(savedDefault);
414 void tst_QSslSocket::simpleConnect()
416 if (!QSslSocket::supportsSsl())
419 QFETCH_GLOBAL(bool, setProxy);
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> &)));
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()));
438 socket.connectToHost(QtNetworkSettings::serverName(), 993);
439 QCOMPARE(socket.state(), QAbstractSocket::HostLookupState);
442 // Entered connecting state
444 QCOMPARE(socket.state(), QAbstractSocket::ConnectingState);
445 QCOMPARE(connectedSpy.count(), 0);
447 QCOMPARE(hostFoundSpy.count(), 1);
448 QCOMPARE(disconnectedSpy.count(), 0);
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);
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);
466 // Starting handshake
468 QCOMPARE(sslErrorsSpy.count(), 1);
469 QCOMPARE(connectionEncryptedSpy.count(), 0);
470 QVERIFY(!socket.isEncrypted());
471 QCOMPARE(socket.state(), QAbstractSocket::UnconnectedState);
474 void tst_QSslSocket::simpleConnectWithIgnore()
476 if (!QSslSocket::supportsSsl())
479 QFETCH_GLOBAL(bool, setProxy);
484 this->socket = &socket;
485 QSignalSpy encryptedSpy(&socket, SIGNAL(encrypted()));
486 QSignalSpy sslErrorsSpy(&socket, SIGNAL(sslErrors(const QList<QSslError> &)));
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()));
495 socket.connectToHost(QtNetworkSettings::serverName(), 993);
496 QVERIFY(socket.state() != QAbstractSocket::UnconnectedState); // something must be in progress
500 QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
501 socket.startClientEncryption();
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);
510 // Wait for incoming data
511 if (!socket.canReadLine())
514 QByteArray data = socket.readAll();
515 socket.disconnectFromHost();
516 QVERIFY2(QtNetworkSettings::compareReplyIMAPSSL(data), data.constData());
519 void tst_QSslSocket::sslErrors_data()
521 QTest::addColumn<QString>("host");
522 QTest::addColumn<int>("port");
523 QTest::addColumn<SslErrorList>("expected");
525 QTest::newRow(qPrintable(QtNetworkSettings::serverLocalName()))
526 << QtNetworkSettings::serverLocalName()
528 << (SslErrorList() << QSslError::HostNameMismatch
529 << QSslError::SelfSignedCertificate);
532 void tst_QSslSocket::sslErrors()
534 QFETCH(QString, host);
536 QFETCH(SslErrorList, expected);
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);
545 foreach (QSslError error, socket->sslErrors()) {
546 output << error.error();
549 #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
550 if (output.count() && output.last() == QSslError::CertificateUntrusted)
553 QCOMPARE(output, expected);
556 void tst_QSslSocket::addCaCertificate()
558 if (!QSslSocket::supportsSsl())
562 void tst_QSslSocket::addCaCertificates()
564 if (!QSslSocket::supportsSsl())
568 void tst_QSslSocket::addCaCertificates2()
570 if (!QSslSocket::supportsSsl())
574 void tst_QSslSocket::ciphers()
576 if (!QSslSocket::supportsSsl())
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());
589 socket.setCiphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
592 void tst_QSslSocket::connectToHostEncrypted()
594 if (!QSslSocket::supportsSsl())
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>)));
605 socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
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()));
611 socket->disconnectFromHost();
612 QVERIFY(socket->waitForDisconnected());
614 QCOMPARE(socket->mode(), QSslSocket::SslClientMode);
616 socket->connectToHost(QtNetworkSettings::serverName(), 13);
618 QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
620 QVERIFY(socket->waitForDisconnected());
623 void tst_QSslSocket::connectToHostEncryptedWithVerificationPeerName()
625 if (!QSslSocket::supportsSsl())
628 QSslSocketPtr socket = newSocket();
629 this->socket = socket;
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>)));
637 // connect to the server with its local name, but use the full name for verification.
638 socket->connectToHostEncrypted(QtNetworkSettings::serverLocalName(), 443, QtNetworkSettings::serverName());
640 // This should pass unconditionally when using fluke's CA certificate.
641 QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
643 socket->disconnectFromHost();
644 QVERIFY(socket->waitForDisconnected());
646 QCOMPARE(socket->mode(), QSslSocket::SslClientMode);
649 void tst_QSslSocket::sessionCipher()
651 if (!QSslSocket::supportsSsl())
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());
669 void tst_QSslSocket::flush()
673 void tst_QSslSocket::isEncrypted()
677 void tst_QSslSocket::localCertificate()
679 if (!QSslSocket::supportsSsl())
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
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"));
692 socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
693 QVERIFY(socket->waitForEncrypted(10000));
696 void tst_QSslSocket::mode()
700 void tst_QSslSocket::peerCertificate()
704 void tst_QSslSocket::peerCertificateChain()
706 if (!QSslSocket::supportsSsl())
709 QSslSocketPtr socket = newSocket();
710 this->socket = socket;
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>)));
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()));
725 QList<QSslCertificate> certChain = socket->peerCertificateChain();
726 QVERIFY(certChain.count() > 0);
727 QCOMPARE(certChain.first(), socket->peerCertificate());
729 socket->disconnectFromHost();
730 QVERIFY(socket->waitForDisconnected());
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()));
739 QCOMPARE(socket->peerCertificateChain().first(), socket->peerCertificate());
740 QVERIFY(socket->peerCertificateChain() != certChain);
742 socket->disconnectFromHost();
743 QVERIFY(socket->waitForDisconnected());
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");
751 socket->startClientEncryption();
752 QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
754 QCOMPARE(socket->peerCertificateChain().first(), socket->peerCertificate());
755 QVERIFY(socket->peerCertificateChain() == certChain);
757 socket->disconnectFromHost();
758 QVERIFY(socket->waitForDisconnected());
761 void tst_QSslSocket::privateKey()
765 void tst_QSslSocket::protocol()
767 if (!QSslSocket::supportsSsl())
770 QSslSocketPtr socket = newSocket();
771 this->socket = socket;
772 QList<QSslCertificate> certs = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem");
774 socket->setCaCertificates(certs);
775 #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
776 connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
777 this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
780 QCOMPARE(socket->protocol(), QSsl::SecureProtocols);
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);
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);
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);
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);
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);
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()));
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);
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);
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);
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);
862 class SslServer : public QTcpServer
866 SslServer(const QString &keyFile = SRCDIR "certs/fluke.key", const QString &certFile = SRCDIR "certs/fluke.cert")
868 protocol(QSsl::TlsV1),
870 m_certFile(certFile) { }
872 QSsl::SslProtocol protocol;
877 void incomingConnection(int socketDescriptor)
879 socket = new QSslSocket(this);
880 socket->setProtocol(protocol);
881 connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
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);
889 QList<QSslCertificate> localCert = QSslCertificate::fromPath(m_certFile);
890 QVERIFY(!localCert.isEmpty());
891 QVERIFY(localCert.first().handle());
892 socket->setLocalCertificate(localCert.first());
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);
900 socket->startServerEncryption();
904 void ignoreErrorSlot()
906 socket->ignoreSslErrors();
910 void tst_QSslSocket::protocolServerSide_data()
913 QTest::addColumn<QSsl::SslProtocol>("serverProtocol");
914 QTest::addColumn<QSsl::SslProtocol>("clientProtocol");
915 QTest::addColumn<bool>("works");
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;
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
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
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
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;
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;
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;
963 void tst_QSslSocket::protocolServerSide()
965 if (!QSslSocket::supportsSsl()) {
966 qWarning("SSL not supported, skipping test");
970 QFETCH_GLOBAL(bool, setProxy);
974 QFETCH(QSsl::SslProtocol, serverProtocol);
976 server.protocol = serverProtocol;
977 QVERIFY(server.listen());
980 QTimer::singleShot(5000, &loop, SLOT(quit()));
982 QSslSocketPtr client = new QSslSocket;
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()));
991 client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort());
996 QAbstractSocket::SocketState expectedState = (works) ? QAbstractSocket::ConnectedState : QAbstractSocket::UnconnectedState;
997 QCOMPARE(client->state(), expectedState);
998 QCOMPARE(client->isEncrypted(), works);
1001 void tst_QSslSocket::setCaCertificates()
1003 if (!QSslSocket::supportsSsl())
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());
1014 void tst_QSslSocket::setLocalCertificate()
1018 void tst_QSslSocket::setPrivateKey()
1022 void tst_QSslSocket::setSocketDescriptor()
1024 if (!QSslSocket::supportsSsl())
1027 QFETCH_GLOBAL(bool, setProxy);
1032 QVERIFY(server.listen());
1035 QTimer::singleShot(5000, &loop, SLOT(quit()));
1037 QSslSocketPtr client = new QSslSocket;
1039 connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
1040 connect(client, SIGNAL(encrypted()), &loop, SLOT(quit()));
1042 client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort());
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);
1054 void tst_QSslSocket::setSslConfiguration_data()
1056 QTest::addColumn<QSslConfiguration>("configuration");
1057 QTest::addColumn<bool>("works");
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;
1069 void tst_QSslSocket::setSslConfiguration()
1071 if (!QSslSocket::supportsSsl())
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);
1082 socket->disconnectFromHost();
1083 QVERIFY2(socket->waitForDisconnected(), qPrintable(socket->errorString()));
1087 void tst_QSslSocket::waitForEncrypted()
1089 if (!QSslSocket::supportsSsl())
1092 QSslSocketPtr socket = newSocket();
1093 this->socket = socket;
1095 connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
1096 socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
1098 QVERIFY(socket->waitForEncrypted(10000));
1101 void tst_QSslSocket::waitForConnectedEncryptedReadyRead()
1103 if (!QSslSocket::supportsSsl())
1106 QSslSocketPtr socket = newSocket();
1107 this->socket = socket;
1109 connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
1110 socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
1113 QVERIFY(socket->waitForConnected(10000));
1114 QVERIFY(socket->waitForEncrypted(10000));
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);
1120 QVERIFY(socket->waitForReadyRead(10000));
1121 QVERIFY(!socket->peerCertificate().isNull());
1122 QVERIFY(!socket->peerCertificateChain().isEmpty());
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());
1132 void tst_QSslSocket::startClientEncryption()
1136 void tst_QSslSocket::startServerEncryption()
1140 void tst_QSslSocket::addDefaultCaCertificate()
1142 if (!QSslSocket::supportsSsl())
1145 // Reset the global CA chain
1146 QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
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()));
1156 // Restore the global CA chain
1157 QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
1160 void tst_QSslSocket::addDefaultCaCertificates()
1164 void tst_QSslSocket::addDefaultCaCertificates2()
1168 void tst_QSslSocket::defaultCaCertificates()
1170 if (!QSslSocket::supportsSsl())
1173 QList<QSslCertificate> certs = QSslSocket::defaultCaCertificates();
1174 QVERIFY(certs.size() > 1);
1175 QCOMPARE(certs, QSslSocket::systemCaCertificates());
1178 void tst_QSslSocket::defaultCiphers()
1182 void tst_QSslSocket::resetDefaultCiphers()
1186 void tst_QSslSocket::setDefaultCaCertificates()
1190 void tst_QSslSocket::setDefaultCiphers()
1194 void tst_QSslSocket::supportedCiphers()
1196 if (!QSslSocket::supportsSsl())
1199 QList<QSslCipher> ciphers = QSslSocket::supportedCiphers();
1200 QVERIFY(ciphers.size() > 1);
1203 QCOMPARE(socket.supportedCiphers(), ciphers);
1204 QCOMPARE(socket.defaultCiphers(), ciphers);
1205 QCOMPARE(socket.ciphers(), ciphers);
1208 void tst_QSslSocket::systemCaCertificates()
1210 if (!QSslSocket::supportsSsl())
1213 QList<QSslCertificate> certs = QSslSocket::systemCaCertificates();
1214 QVERIFY(certs.size() > 1);
1215 QCOMPARE(certs, QSslSocket::defaultCaCertificates());
1218 void tst_QSslSocket::wildcardCertificateNames()
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 );
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 );
1242 void tst_QSslSocket::wildcard()
1244 QSKIP("TODO: solve wildcard problem", SkipAll);
1246 if (!QSslSocket::supportsSsl())
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>)));
1262 socket->connectToHostEncrypted(QtNetworkSettings::wildcardServerName(), 4443);
1264 QVERIFY2(socket->waitForEncrypted(3000), qPrintable(socket->errorString()));
1266 QSslCertificate certificate = socket->peerCertificate();
1267 QCOMPARE(certificate.subjectInfo(QSslCertificate::CommonName), QString(QtNetworkSettings::serverLocalName() + ".*." + QtNetworkSettings::serverDomainName()));
1268 QCOMPARE(certificate.issuerInfo(QSslCertificate::CommonName), QtNetworkSettings::serverName());
1273 class SslServer2 : public QTcpServer
1276 void incomingConnection(int socketDescriptor)
1278 QSslSocket *socket = new QSslSocket(this);
1279 socket->ignoreSslErrors();
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());
1287 QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState));
1289 socket->startServerEncryption();
1293 void tst_QSslSocket::setEmptyKey()
1295 if (!QSslSocket::supportsSsl())
1298 QFETCH_GLOBAL(bool, setProxy);
1306 socket.connectToHostEncrypted("127.0.0.1", server.serverPort());
1308 QTestEventLoop::instance().enterLoop(2);
1310 QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
1311 QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
1314 void tst_QSslSocket::spontaneousWrite()
1316 QFETCH_GLOBAL(bool, setProxy);
1321 QSslSocket *receiver = new QSslSocket(this);
1322 connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop()));
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));
1330 QSslSocket *sender = server.socket;
1332 QVERIFY(sender->state() == QAbstractSocket::ConnectedState);
1333 receiver->setObjectName("receiver");
1334 sender->setObjectName("sender");
1335 receiver->ignoreSslErrors();
1336 receiver->startClientEncryption();
1339 connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop()));
1341 QVERIFY(!timeout());
1342 QVERIFY(sender->isEncrypted());
1343 QVERIFY(receiver->isEncrypted());
1345 // make sure there's nothing to be received on the sender:
1346 while (sender->waitForReadyRead(10) || receiver->waitForBytesWritten(10)) {}
1348 // spontaneously write something:
1349 QByteArray data("Hello World");
1350 sender->write(data);
1352 // check if the other side receives it:
1354 QVERIFY(!timeout());
1355 QCOMPARE(receiver->bytesAvailable(), qint64(data.size()));
1356 QCOMPARE(receiver->readAll(), data);
1359 void tst_QSslSocket::setReadBufferSize()
1361 QFETCH_GLOBAL(bool, setProxy);
1366 QSslSocket *receiver = new QSslSocket(this);
1367 connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop()));
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));
1375 QSslSocket *sender = server.socket;
1377 QVERIFY(sender->state() == QAbstractSocket::ConnectedState);
1378 receiver->setObjectName("receiver");
1379 sender->setObjectName("sender");
1380 receiver->ignoreSslErrors();
1381 receiver->startClientEncryption();
1384 connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop()));
1386 QVERIFY(!timeout());
1387 QVERIFY(sender->isEncrypted());
1388 QVERIFY(receiver->isEncrypted());
1390 QByteArray data(2048, 'b');
1391 receiver->setReadBufferSize(39 * 1024); // make it a non-multiple of the data.size()
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());
1400 while (sender->bytesToWrite())
1401 QVERIFY(sender->waitForBytesWritten(10));
1404 while (receiver->bytesAvailable() < receiver->readBufferSize() &&
1405 receiver->waitForReadyRead(10)) {}
1408 //qDebug() << sender->bytesToWrite() << "bytes to write";
1409 //qDebug() << receiver->bytesAvailable() << "bytes available";
1412 sender->write(data);
1413 sender->write(data);
1414 sender->write(data);
1415 sender->write(data);
1416 QVERIFY(sender->waitForBytesWritten(10));
1418 qint64 oldBytesAvailable = receiver->bytesAvailable();
1420 // now unset the read buffer limit and iterate
1421 receiver->setReadBufferSize(0);
1423 QVERIFY(!timeout());
1425 QVERIFY(receiver->bytesAvailable() > oldBytesAvailable);
1428 class SetReadBufferSize_task_250027_handler : public QObject {
1431 void readyReadSlot() {
1432 QTestEventLoop::instance().exitLoop();
1434 void waitSomeMore(QSslSocket *socket) {
1437 while (!socket->encryptedBytesAvailable()) {
1438 QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents, 250);
1439 if (t.elapsed() > 1000 || socket->state() != QAbstractSocket::ConnectedState)
1445 void tst_QSslSocket::setReadBufferSize_task_250027()
1447 // do not execute this when a proxy is set.
1448 QFETCH_GLOBAL(bool, setProxy);
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));
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()));
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");
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);
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);
1488 class SslServer3 : public QTcpServer
1492 SslServer3() : socket(0) { }
1496 void incomingConnection(int socketDescriptor)
1498 socket = new QSslSocket(this);
1499 connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
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);
1507 QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert");
1508 QVERIFY(!localCert.isEmpty());
1509 QVERIFY(localCert.first().handle());
1510 socket->setLocalCertificate(localCert.first());
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);
1520 void ignoreErrorSlot()
1522 socket->ignoreSslErrors();
1526 class ThreadedSslServer: public QThread
1530 QSemaphore dataReadSemaphore;
1534 ThreadedSslServer() : serverPort(-1), ok(false)
1537 ~ThreadedSslServer()
1539 if (isRunning()) wait(2000);
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)
1553 server.listen(QHostAddress::LocalHost);
1554 serverPort = server.serverPort();
1557 // delayed acceptance:
1559 #ifndef Q_OS_SYMBIAN
1560 bool ret = server.waitForNewConnection(2000);
1562 bool ret = server.waitForNewConnection(20000);
1566 // delayed start of encryption
1568 QSslSocket *socket = server.socket;
1569 if (!socket || !socket->isValid())
1571 socket->ignoreSslErrors();
1572 socket->startServerEncryption();
1573 if (!socket->waitForEncrypted(2000))
1576 // delayed reading data
1578 if (!socket->waitForReadyRead(2000))
1581 dataReadSemaphore.release();
1583 // delayed sending data
1585 socket->write("Hello, World");
1586 while (socket->bytesToWrite())
1587 if (!socket->waitForBytesWritten(2000))
1590 // delayed replying (reading then sending)
1592 if (!socket->waitForReadyRead(2000))
1594 socket->write("Hello, World");
1595 while (socket->bytesToWrite())
1596 if (!socket->waitForBytesWritten(2000))
1599 // delayed disconnection:
1601 socket->disconnectFromHost();
1602 if (!socket->waitForDisconnected(2000))
1610 void tst_QSslSocket::waitForMinusOne()
1612 QFETCH_GLOBAL(bool, setProxy);
1616 ThreadedSslServer server;
1617 connect(&server, SIGNAL(listening()), SLOT(exitLoop()));
1619 // start the thread and wait for it to be ready
1622 QVERIFY(!timeout());
1624 // connect to the server
1627 socket.connectToHost("127.0.0.1", server.serverPort);
1628 QVERIFY(socket.waitForConnected(-1));
1629 socket.ignoreSslErrors();
1630 socket.startClientEncryption();
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));
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));
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);
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));
1657 // fifth verification: it should wait for 200 ms more
1658 QVERIFY(socket.waitForDisconnected(-1));
1661 class VerifyServer : public QTcpServer
1665 VerifyServer() : socket(0) { }
1669 void incomingConnection(int socketDescriptor)
1671 socket = new QSslSocket(this);
1673 socket->setPrivateKey(SRCDIR "certs/fluke.key");
1674 socket->setLocalCertificate(SRCDIR "certs/fluke.cert");
1675 socket->setSocketDescriptor(socketDescriptor);
1676 socket->startServerEncryption();
1680 void tst_QSslSocket::verifyMode()
1682 QFETCH_GLOBAL(bool, setProxy);
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);
1694 socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
1695 QVERIFY(!socket.waitForEncrypted());
1697 QList<QSslError> expectedErrors = QList<QSslError>()
1698 << QSslError(QSslError::SelfSignedCertificate, socket.peerCertificate());
1699 QCOMPARE(socket.sslErrors(), expectedErrors);
1702 VerifyServer server;
1705 QSslSocket clientSocket;
1706 clientSocket.connectToHostEncrypted("127.0.0.1", server.serverPort());
1707 clientSocket.ignoreSslErrors();
1710 QTimer::singleShot(5000, &loop, SLOT(quit()));
1711 connect(&clientSocket, SIGNAL(encrypted()), &loop, SLOT(quit()));
1714 QVERIFY(clientSocket.isEncrypted());
1715 QVERIFY(server.socket->sslErrors().isEmpty());
1718 void tst_QSslSocket::verifyDepth()
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);
1729 void tst_QSslSocket::peerVerifyError()
1731 QSslSocketPtr socket = newSocket();
1732 QSignalSpy sslErrorsSpy(socket, SIGNAL(sslErrors(QList<QSslError>)));
1733 QSignalSpy peerVerifyErrorSpy(socket, SIGNAL(peerVerifyError(QSslError)));
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());
1743 void tst_QSslSocket::disconnectFromHostWhenConnecting()
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));
1766 // dont forget to login
1767 QCOMPARE((int) socket->write("USER ftptest\r\n"), 14);
1771 void tst_QSslSocket::disconnectFromHostWhenConnected()
1773 QSslSocketPtr socket = newSocket();
1774 socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
1775 socket->ignoreSslErrors();
1776 #ifndef Q_OS_SYMBIAN
1777 QVERIFY(socket->waitForEncrypted(5000));
1779 QVERIFY(socket->waitForEncrypted(10000));
1781 socket->write("XXXX LOGOUT\r\n");
1782 QCOMPARE(socket->state(), QAbstractSocket::ConnectedState);
1783 socket->disconnectFromHost();
1784 QCOMPARE(socket->state(), QAbstractSocket::ClosingState);
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()));
1793 QVERIFY(!timeout());
1795 QVERIFY(socket->waitForDisconnected(5000));
1797 QCOMPARE(socket->bytesToWrite(), qint64(0));
1800 void tst_QSslSocket::resetProxy()
1802 QFETCH_GLOBAL(bool, setProxy);
1806 // check fix for bug 199941
1808 QNetworkProxy goodProxy(QNetworkProxy::NoProxy);
1809 QNetworkProxy badProxy(QNetworkProxy::HttpProxy, "thisCannotWorkAbsolutelyNotForSure", 333);
1811 // make sure the connection works, and then set a nonsense proxy, and then
1812 // make sure it does not work anymore
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()));
1819 socket.setProxy(badProxy);
1820 socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
1821 QVERIFY(! socket.waitForConnected(10000));
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);
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
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));
1838 socket2.setProxy(goodProxy);
1839 socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
1840 QVERIFY2(socket2.waitForConnected(10000), qPrintable(socket.errorString()));
1843 void tst_QSslSocket::ignoreSslErrorsList_data()
1845 QTest::addColumn<QList<QSslError> >("expectedSslErrors");
1846 QTest::addColumn<int>("expectedSslErrorSignalCount");
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);
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;
1867 void tst_QSslSocket::ignoreSslErrorsList()
1870 connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
1871 this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
1873 // this->socket = &socket;
1874 QSslCertificate cert;
1876 QFETCH(QList<QSslError>, expectedSslErrors);
1877 socket.ignoreSslErrors(expectedSslErrors);
1879 QFETCH(int, expectedSslErrorSignalCount);
1880 QSignalSpy sslErrorsSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
1882 socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
1884 bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
1885 QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess);
1886 QCOMPARE(sslErrorsSpy.count(), expectedSslErrorSignalCount);
1889 void tst_QSslSocket::ignoreSslErrorsListWithSlot_data()
1891 ignoreSslErrorsList_data();
1894 // this is not a test, just a slot called in the test below
1895 void tst_QSslSocket::ignoreErrorListSlot(const QList<QSslError> &)
1897 socket->ignoreSslErrors(storedExpectedSslErrors);
1900 void tst_QSslSocket::ignoreSslErrorsListWithSlot()
1903 this->socket = &socket;
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);
1914 QFETCH(int, expectedSslErrorSignalCount);
1915 bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
1916 QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess);
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()
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());
1940 QVERIFY(!socket->bytesAvailable());
1941 QVERIFY(!socket->bytesToWrite());
1942 QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
1945 void tst_QSslSocket::writeBigChunk()
1947 if (!QSslSocket::supportsSsl())
1950 QSslSocketPtr socket = newSocket();
1951 this->socket = socket;
1953 connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
1954 socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
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++) {
1961 data.data()[i*sizeof(int)] = r;
1964 QVERIFY(socket->waitForEncrypted(10000));
1965 QString errorBefore = socket->errorString();
1967 int ret = socket->write(data.constData(), data.size());
1968 QVERIFY(data.size() == ret);
1970 // spin the event loop once so QSslSocket::transmit() gets called
1971 QCoreApplication::processEvents();
1972 QString errorAfter = socket->errorString();
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")))
1977 qWarning() << socket->error() << socket->errorString();
1978 QFAIL("Error while writing! Check if the OpenSSL BIO size is limited?!");
1980 // also check the error string. If another error (than UnknownError) occured, it should be different than before
1981 QVERIFY(errorBefore == errorAfter);
1983 // check that everything has been written to OpenSSL
1984 QVERIFY(socket->bytesToWrite() == 0);
1989 void tst_QSslSocket::blacklistedCertificates()
1991 QFETCH_GLOBAL(bool, setProxy);
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()));
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));
2005 QSslSocket *sender = server.socket;
2007 QVERIFY(sender->state() == QAbstractSocket::ConnectedState);
2008 receiver->setObjectName("receiver");
2009 sender->setObjectName("sender");
2010 receiver->startClientEncryption();
2012 connect(receiver, SIGNAL(sslErrors(QList<QSslError>)), SLOT(exitLoop()));
2013 connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop()));
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);
2021 void tst_QSslSocket::setEmptyDefaultConfiguration()
2023 // used to produce a crash in QSslConfigurationPrivate::deepCopyDefaultConfiguration, QTBUG-13265
2025 if (!QSslSocket::supportsSsl())
2028 QSslConfiguration emptyConf;
2029 QSslConfiguration::setDefaultConfiguration(emptyConf);
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()));
2037 #endif // QT_NO_OPENSSL
2039 QTEST_MAIN(tst_QSslSocket)
2040 #include "tst_qsslsocket.moc"