~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the test suite of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
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
#ifndef QT_NO_SSL
 
59
#include "private/qsslsocket_openssl_p.h"
 
60
#include "private/qsslsocket_openssl_symbols_p.h"
 
61
#include "private/qsslconfiguration_p.h"
 
62
#endif
 
63
 
 
64
#include "../../../network-settings.h"
 
65
 
 
66
#ifndef QT_NO_SSL
 
67
Q_DECLARE_METATYPE(QSslSocket::SslMode)
 
68
typedef QList<QSslError::SslError> SslErrorList;
 
69
Q_DECLARE_METATYPE(SslErrorList)
 
70
Q_DECLARE_METATYPE(QSslError)
 
71
Q_DECLARE_METATYPE(QSsl::SslProtocol)
 
72
#endif
 
73
 
 
74
#if defined Q_OS_HPUX && defined Q_CC_GNU
 
75
// This error is delivered every time we try to use the fluke CA
 
76
// certificate. For now we work around this bug. Task 202317.
 
77
#define QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
 
78
#endif
 
79
 
 
80
#ifndef QT_NO_SSL
 
81
typedef QSharedPointer<QSslSocket> QSslSocketPtr;
 
82
#endif
 
83
 
 
84
class tst_QSslSocket : public QObject
 
85
{
 
86
    Q_OBJECT
 
87
 
 
88
    int proxyAuthCalled;
 
89
 
 
90
public:
 
91
    tst_QSslSocket();
 
92
    virtual ~tst_QSslSocket();
 
93
 
 
94
    static void enterLoop(int secs)
 
95
    {
 
96
        ++loopLevel;
 
97
        QTestEventLoop::instance().enterLoop(secs);
 
98
    }
 
99
 
 
100
    static bool timeout()
 
101
    {
 
102
        return QTestEventLoop::instance().timeout();
 
103
    }
 
104
 
 
105
#ifndef QT_NO_SSL
 
106
    QSslSocketPtr newSocket();
 
107
#endif
 
108
 
 
109
public slots:
 
110
    void initTestCase_data();
 
111
    void initTestCase();
 
112
    void init();
 
113
    void cleanup();
 
114
    void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth);
 
115
 
 
116
#ifndef QT_NO_SSL
 
117
private slots:
 
118
    void constructing();
 
119
    void simpleConnect();
 
120
    void simpleConnectWithIgnore();
 
121
 
 
122
    // API tests
 
123
    void sslErrors_data();
 
124
    void sslErrors();
 
125
    void addCaCertificate();
 
126
    void addCaCertificates();
 
127
    void addCaCertificates2();
 
128
    void ciphers();
 
129
    void connectToHostEncrypted();
 
130
    void connectToHostEncryptedWithVerificationPeerName();
 
131
    void sessionCipher();
 
132
    void flush();
 
133
    void isEncrypted();
 
134
    void localCertificate();
 
135
    void mode();
 
136
    void peerCertificate();
 
137
    void peerCertificateChain();
 
138
    void privateKey();
 
139
    void privateKeyOpaque();
 
140
    void protocol();
 
141
    void protocolServerSide_data();
 
142
    void protocolServerSide();
 
143
    void setCaCertificates();
 
144
    void setLocalCertificate();
 
145
    void setPrivateKey();
 
146
    void setSocketDescriptor();
 
147
    void setSslConfiguration_data();
 
148
    void setSslConfiguration();
 
149
    void waitForEncrypted();
 
150
    void waitForEncryptedMinusOne();
 
151
    void waitForConnectedEncryptedReadyRead();
 
152
    void startClientEncryption();
 
153
    void startServerEncryption();
 
154
    void addDefaultCaCertificate();
 
155
    void addDefaultCaCertificates();
 
156
    void addDefaultCaCertificates2();
 
157
    void defaultCaCertificates();
 
158
    void defaultCiphers();
 
159
    void resetDefaultCiphers();
 
160
    void setDefaultCaCertificates();
 
161
    void setDefaultCiphers();
 
162
    void supportedCiphers();
 
163
    void systemCaCertificates();
 
164
    void wildcardCertificateNames();
 
165
    void wildcard();
 
166
    void setEmptyKey();
 
167
    void spontaneousWrite();
 
168
    void setReadBufferSize();
 
169
    void setReadBufferSize_task_250027();
 
170
    void waitForMinusOne();
 
171
    void verifyMode();
 
172
    void verifyDepth();
 
173
    void peerVerifyError();
 
174
    void disconnectFromHostWhenConnecting();
 
175
    void disconnectFromHostWhenConnected();
 
176
    void resetProxy();
 
177
    void ignoreSslErrorsList_data();
 
178
    void ignoreSslErrorsList();
 
179
    void ignoreSslErrorsListWithSlot_data();
 
180
    void ignoreSslErrorsListWithSlot();
 
181
    void readFromClosedSocket();
 
182
    void writeBigChunk();
 
183
    void blacklistedCertificates();
 
184
    void versionAccessors();
 
185
    void sslOptions();
 
186
    void encryptWithoutConnecting();
 
187
    void resume_data();
 
188
    void resume();
 
189
    void qtbug18498_peek();
 
190
    void qtbug18498_peek2();
 
191
    void setEmptyDefaultConfiguration(); // this test should be last
 
192
 
 
193
    static void exitLoop()
 
194
    {
 
195
        // Safe exit - if we aren't in an event loop, don't
 
196
        // exit one.
 
197
        if (loopLevel > 0) {
 
198
            --loopLevel;
 
199
            QTestEventLoop::instance().exitLoop();
 
200
        }
 
201
    }
 
202
 
 
203
protected slots:
 
204
    void ignoreErrorSlot()
 
205
    {
 
206
        socket->ignoreSslErrors();
 
207
    }
 
208
    void untrustedWorkaroundSlot(const QList<QSslError> &errors)
 
209
    {
 
210
        if (errors.size() == 1 &&
 
211
                (errors.first().error() == QSslError::CertificateUntrusted ||
 
212
                        errors.first().error() == QSslError::SelfSignedCertificate))
 
213
            socket->ignoreSslErrors();
 
214
    }
 
215
    void ignoreErrorListSlot(const QList<QSslError> &errors);
 
216
 
 
217
private:
 
218
    QSslSocket *socket;
 
219
    QList<QSslError> storedExpectedSslErrors;
 
220
#endif // QT_NO_SSL
 
221
private:
 
222
    static int loopLevel;
 
223
};
 
224
 
 
225
int tst_QSslSocket::loopLevel = 0;
 
226
 
 
227
tst_QSslSocket::tst_QSslSocket()
 
228
{
 
229
#ifndef QT_NO_SSL
 
230
    qRegisterMetaType<QList<QSslError> >("QList<QSslError>");
 
231
    qRegisterMetaType<QSslError>("QSslError");
 
232
    qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
 
233
    qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
 
234
#endif
 
235
}
 
236
 
 
237
tst_QSslSocket::~tst_QSslSocket()
 
238
{
 
239
}
 
240
 
 
241
enum ProxyTests {
 
242
    NoProxy = 0x00,
 
243
    Socks5Proxy = 0x01,
 
244
    HttpProxy = 0x02,
 
245
    TypeMask = 0x0f,
 
246
 
 
247
    NoAuth = 0x00,
 
248
    AuthBasic = 0x10,
 
249
    AuthNtlm = 0x20,
 
250
    AuthMask = 0xf0
 
251
};
 
252
 
 
253
void tst_QSslSocket::initTestCase_data()
 
254
{
 
255
    QTest::addColumn<bool>("setProxy");
 
256
    QTest::addColumn<int>("proxyType");
 
257
 
 
258
    QTest::newRow("WithoutProxy") << false << 0;
 
259
    QTest::newRow("WithSocks5Proxy") << true << int(Socks5Proxy);
 
260
    QTest::newRow("WithSocks5ProxyAuth") << true << int(Socks5Proxy | AuthBasic);
 
261
 
 
262
    QTest::newRow("WithHttpProxy") << true << int(HttpProxy);
 
263
    QTest::newRow("WithHttpProxyBasicAuth") << true << int(HttpProxy | AuthBasic);
 
264
    // uncomment the line below when NTLM works
 
265
//    QTest::newRow("WithHttpProxyNtlmAuth") << true << int(HttpProxy | AuthNtlm);
 
266
}
 
267
 
 
268
void tst_QSslSocket::initTestCase()
 
269
{
 
270
    QVERIFY(QtNetworkSettings::verifyTestNetworkSettings());
 
271
}
 
272
 
 
273
void tst_QSslSocket::init()
 
274
{
 
275
    QFETCH_GLOBAL(bool, setProxy);
 
276
    if (setProxy) {
 
277
        QFETCH_GLOBAL(int, proxyType);
 
278
        QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
 
279
        QNetworkProxy proxy;
 
280
 
 
281
        switch (proxyType) {
 
282
        case Socks5Proxy:
 
283
            proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1080);
 
284
            break;
 
285
 
 
286
        case Socks5Proxy | AuthBasic:
 
287
            proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1081);
 
288
            break;
 
289
 
 
290
        case HttpProxy | NoAuth:
 
291
            proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3128);
 
292
            break;
 
293
 
 
294
        case HttpProxy | AuthBasic:
 
295
            proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3129);
 
296
            break;
 
297
 
 
298
        case HttpProxy | AuthNtlm:
 
299
            proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3130);
 
300
            break;
 
301
        }
 
302
        QNetworkProxy::setApplicationProxy(proxy);
 
303
    }
 
304
 
 
305
    qt_qhostinfo_clear_cache();
 
306
}
 
307
 
 
308
void tst_QSslSocket::cleanup()
 
309
{
 
310
    QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
 
311
}
 
312
 
 
313
#ifndef QT_NO_SSL
 
314
QSslSocketPtr tst_QSslSocket::newSocket()
 
315
{
 
316
    QSslSocket *socket = new QSslSocket;
 
317
 
 
318
    proxyAuthCalled = 0;
 
319
    connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
 
320
            SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
 
321
            Qt::DirectConnection);
 
322
 
 
323
    return QSslSocketPtr(socket);
 
324
}
 
325
#endif
 
326
 
 
327
void tst_QSslSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
 
328
{
 
329
    ++proxyAuthCalled;
 
330
    auth->setUser("qsockstest");
 
331
    auth->setPassword("password");
 
332
}
 
333
 
 
334
#ifndef QT_NO_SSL
 
335
 
 
336
void tst_QSslSocket::constructing()
 
337
{
 
338
    if (!QSslSocket::supportsSsl())
 
339
        return;
 
340
 
 
341
    QSslSocket socket;
 
342
 
 
343
    QCOMPARE(socket.state(), QSslSocket::UnconnectedState);
 
344
    QCOMPARE(socket.mode(), QSslSocket::UnencryptedMode);
 
345
    QVERIFY(!socket.isEncrypted());
 
346
    QCOMPARE(socket.bytesAvailable(), qint64(0));
 
347
    QCOMPARE(socket.bytesToWrite(), qint64(0));
 
348
    QVERIFY(!socket.canReadLine());
 
349
    QVERIFY(socket.atEnd());
 
350
    QCOMPARE(socket.localCertificate(), QSslCertificate());
 
351
    QCOMPARE(socket.sslConfiguration(), QSslConfiguration::defaultConfiguration());
 
352
    QCOMPARE(socket.errorString(), QString("Unknown error"));
 
353
    char c = '\0';
 
354
    QVERIFY(!socket.getChar(&c));
 
355
    QCOMPARE(c, '\0');
 
356
    QVERIFY(!socket.isOpen());
 
357
    QVERIFY(!socket.isReadable());
 
358
    QVERIFY(socket.isSequential());
 
359
    QVERIFY(!socket.isTextModeEnabled());
 
360
    QVERIFY(!socket.isWritable());
 
361
    QCOMPARE(socket.openMode(), QIODevice::NotOpen);
 
362
    QVERIFY(socket.peek(2).isEmpty());
 
363
    QCOMPARE(socket.pos(), qint64(0));
 
364
    QVERIFY(!socket.putChar('c'));
 
365
    QVERIFY(socket.read(2).isEmpty());
 
366
    QCOMPARE(socket.read(0, 0), qint64(-1));
 
367
    QVERIFY(socket.readAll().isEmpty());
 
368
    QTest::ignoreMessage(QtWarningMsg, "QIODevice::readLine: Called with maxSize < 2");
 
369
    QCOMPARE(socket.readLine(0, 0), qint64(-1));
 
370
    char buf[10];
 
371
    QCOMPARE(socket.readLine(buf, sizeof(buf)), qint64(-1));
 
372
    QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek: Cannot call seek on a sequential device");
 
373
    QVERIFY(!socket.reset());
 
374
    QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek: Cannot call seek on a sequential device");
 
375
    QVERIFY(!socket.seek(2));
 
376
    QCOMPARE(socket.size(), qint64(0));
 
377
    QVERIFY(!socket.waitForBytesWritten(10));
 
378
    QVERIFY(!socket.waitForReadyRead(10));
 
379
    QCOMPARE(socket.write(0, 0), qint64(-1));
 
380
    QCOMPARE(socket.write(QByteArray()), qint64(-1));
 
381
    QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
 
382
    QVERIFY(!socket.flush());
 
383
    QVERIFY(!socket.isValid());
 
384
    QCOMPARE(socket.localAddress(), QHostAddress());
 
385
    QCOMPARE(socket.localPort(), quint16(0));
 
386
    QCOMPARE(socket.peerAddress(), QHostAddress());
 
387
    QVERIFY(socket.peerName().isEmpty());
 
388
    QCOMPARE(socket.peerPort(), quint16(0));
 
389
    QCOMPARE(socket.proxy().type(), QNetworkProxy::DefaultProxy);
 
390
    QCOMPARE(socket.readBufferSize(), qint64(0));
 
391
    QCOMPARE(socket.socketDescriptor(), (qintptr)-1);
 
392
    QCOMPARE(socket.socketType(), QAbstractSocket::TcpSocket);
 
393
    QVERIFY(!socket.waitForConnected(10));
 
394
    QTest::ignoreMessage(QtWarningMsg, "QSslSocket::waitForDisconnected() is not allowed in UnconnectedState");
 
395
    QVERIFY(!socket.waitForDisconnected(10));
 
396
    QCOMPARE(socket.protocol(), QSsl::SecureProtocols);
 
397
 
 
398
    QSslConfiguration savedDefault = QSslConfiguration::defaultConfiguration();
 
399
 
 
400
    // verify that changing the default config doesn't affect this socket
 
401
    // (on Unix, the ca certs might be empty, depending on whether we load
 
402
    // them on demand or not, so set them explicitly)
 
403
    socket.setCaCertificates(QSslSocket::systemCaCertificates());
 
404
    QSslSocket::setDefaultCaCertificates(QList<QSslCertificate>());
 
405
    QSslSocket::setDefaultCiphers(QList<QSslCipher>());
 
406
    QVERIFY(!socket.caCertificates().isEmpty());
 
407
    QVERIFY(!socket.ciphers().isEmpty());
 
408
 
 
409
    // verify the default as well:
 
410
    QVERIFY(QSslConfiguration::defaultConfiguration().caCertificates().isEmpty());
 
411
    QVERIFY(QSslConfiguration::defaultConfiguration().ciphers().isEmpty());
 
412
 
 
413
    QSslConfiguration::setDefaultConfiguration(savedDefault);
 
414
}
 
415
 
 
416
void tst_QSslSocket::simpleConnect()
 
417
{
 
418
    if (!QSslSocket::supportsSsl())
 
419
        return;
 
420
 
 
421
    QFETCH_GLOBAL(bool, setProxy);
 
422
    if (setProxy)
 
423
        return;
 
424
 
 
425
    QSslSocket socket;
 
426
    QSignalSpy connectedSpy(&socket, SIGNAL(connected()));
 
427
    QSignalSpy hostFoundSpy(&socket, SIGNAL(hostFound()));
 
428
    QSignalSpy disconnectedSpy(&socket, SIGNAL(disconnected()));
 
429
    QSignalSpy connectionEncryptedSpy(&socket, SIGNAL(encrypted()));
 
430
    QSignalSpy sslErrorsSpy(&socket, SIGNAL(sslErrors(QList<QSslError>)));
 
431
 
 
432
    connect(&socket, SIGNAL(connected()), this, SLOT(exitLoop()));
 
433
    connect(&socket, SIGNAL(disconnected()), this, SLOT(exitLoop()));
 
434
    connect(&socket, SIGNAL(modeChanged(QSslSocket::SslMode)), this, SLOT(exitLoop()));
 
435
    connect(&socket, SIGNAL(encrypted()), this, SLOT(exitLoop()));
 
436
    connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(exitLoop()));
 
437
    connect(&socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(exitLoop()));
 
438
 
 
439
    // Start connecting
 
440
    socket.connectToHost(QtNetworkSettings::serverName(), 993);
 
441
    QCOMPARE(socket.state(), QAbstractSocket::HostLookupState);
 
442
    enterLoop(10);
 
443
 
 
444
    // Entered connecting state
 
445
    QCOMPARE(socket.state(), QAbstractSocket::ConnectingState);
 
446
    QCOMPARE(connectedSpy.count(), 0);
 
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(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(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
 
492
    connect(&socket, SIGNAL(sslErrors(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.data();
 
599
    QVERIFY(socket->addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")));
 
600
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
 
601
    connect(socket.data(), 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.data();
 
630
 
 
631
    socket->addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
 
632
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
 
633
    connect(socket.data(), 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.data();
 
656
    connect(socket.data(), 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.data();
 
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.data(), 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("qt-project.org", 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::privateKeyOpaque()
 
766
{
 
767
    if (!QSslSocket::supportsSsl())
 
768
        return;
 
769
 
 
770
    QFile file(SRCDIR "certs/fluke.key");
 
771
    QVERIFY(file.open(QIODevice::ReadOnly));
 
772
    QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
 
773
    QVERIFY(!key.isNull());
 
774
 
 
775
    EVP_PKEY *pkey = q_EVP_PKEY_new();
 
776
    q_EVP_PKEY_set1_RSA(pkey, reinterpret_cast<RSA *>(key.handle()));
 
777
 
 
778
    // This test does not make 100% sense yet. We just set some local CA/cert/key and use it
 
779
    // to authenticate ourselves against the server. The server does not actually check this
 
780
    // values. This test should just run the codepath inside qsslsocket_openssl.cpp
 
781
 
 
782
    QSslSocketPtr socket = newSocket();
 
783
    QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem");
 
784
    socket->setCaCertificates(localCert);
 
785
    socket->setLocalCertificate(QLatin1String(SRCDIR "certs/fluke.cert"));
 
786
    socket->setPrivateKey(QSslKey(reinterpret_cast<Qt::HANDLE>(pkey)));
 
787
 
 
788
    socket->setPeerVerifyMode(QSslSocket::QueryPeer);
 
789
    socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
790
    QVERIFY(socket->waitForEncrypted(10000));
 
791
}
 
792
 
 
793
void tst_QSslSocket::protocol()
 
794
{
 
795
    if (!QSslSocket::supportsSsl())
 
796
        return;
 
797
 
 
798
    QSslSocketPtr socket = newSocket();
 
799
    this->socket = socket.data();
 
800
    QList<QSslCertificate> certs = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem");
 
801
 
 
802
    socket->setCaCertificates(certs);
 
803
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
 
804
    connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
 
805
            this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
 
806
#endif
 
807
 
 
808
    QCOMPARE(socket->protocol(), QSsl::SecureProtocols);
 
809
    {
 
810
        // qt-test-server allows SSLv3.
 
811
        socket->setProtocol(QSsl::SslV3);
 
812
        QCOMPARE(socket->protocol(), QSsl::SslV3);
 
813
        socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
814
        QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
 
815
        QCOMPARE(socket->protocol(), QSsl::SslV3);
 
816
        socket->abort();
 
817
        QCOMPARE(socket->protocol(), QSsl::SslV3);
 
818
        socket->connectToHost(QtNetworkSettings::serverName(), 443);
 
819
        QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
 
820
        socket->startClientEncryption();
 
821
        QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
 
822
        QCOMPARE(socket->protocol(), QSsl::SslV3);
 
823
        socket->abort();
 
824
    }
 
825
    {
 
826
        // qt-test-server allows TLSV1.
 
827
        socket->setProtocol(QSsl::TlsV1_0);
 
828
        QCOMPARE(socket->protocol(), QSsl::TlsV1_0);
 
829
        socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
830
        QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
 
831
        QCOMPARE(socket->protocol(), QSsl::TlsV1_0);
 
832
        socket->abort();
 
833
        QCOMPARE(socket->protocol(), QSsl::TlsV1_0);
 
834
        socket->connectToHost(QtNetworkSettings::serverName(), 443);
 
835
        QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
 
836
        socket->startClientEncryption();
 
837
        QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
 
838
        QCOMPARE(socket->protocol(), QSsl::TlsV1_0);
 
839
        socket->abort();
 
840
    }
 
841
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
 
842
    {
 
843
        // qt-test-server probably doesn't allow TLSV1.1
 
844
        socket->setProtocol(QSsl::TlsV1_1);
 
845
        QCOMPARE(socket->protocol(), QSsl::TlsV1_1);
 
846
        socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
847
        QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
 
848
        QCOMPARE(socket->protocol(), QSsl::TlsV1_1);
 
849
        socket->abort();
 
850
        QCOMPARE(socket->protocol(), QSsl::TlsV1_1);
 
851
        socket->connectToHost(QtNetworkSettings::serverName(), 443);
 
852
        QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
 
853
        socket->startClientEncryption();
 
854
        QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
 
855
        QCOMPARE(socket->protocol(), QSsl::TlsV1_1);
 
856
        socket->abort();
 
857
    }
 
858
    {
 
859
        // qt-test-server probably doesn't allows TLSV1.2
 
860
        socket->setProtocol(QSsl::TlsV1_2);
 
861
        QCOMPARE(socket->protocol(), QSsl::TlsV1_2);
 
862
        socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
863
        QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
 
864
        QCOMPARE(socket->protocol(), QSsl::TlsV1_2);
 
865
        socket->abort();
 
866
        QCOMPARE(socket->protocol(), QSsl::TlsV1_2);
 
867
        socket->connectToHost(QtNetworkSettings::serverName(), 443);
 
868
        QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
 
869
        socket->startClientEncryption();
 
870
        QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
 
871
        QCOMPARE(socket->protocol(), QSsl::TlsV1_2);
 
872
        socket->abort();
 
873
    }
 
874
#endif
 
875
#ifndef OPENSSL_NO_SSL2
 
876
    {
 
877
        // qt-test-server allows SSLV2.
 
878
        socket->setProtocol(QSsl::SslV2);
 
879
        QCOMPARE(socket->protocol(), QSsl::SslV2);
 
880
        socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
881
        QVERIFY(socket->waitForEncrypted());
 
882
        QCOMPARE(socket->protocol(), QSsl::SslV2);
 
883
        socket->abort();
 
884
        QCOMPARE(socket->protocol(), QSsl::SslV2);
 
885
        socket->connectToHost(QtNetworkSettings::serverName(), 443);
 
886
        QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
 
887
        socket->startClientEncryption();
 
888
        QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
 
889
        socket->abort();
 
890
    }
 
891
#endif
 
892
    {
 
893
        // qt-test-server allows SSLV3, so it allows AnyProtocol.
 
894
        socket->setProtocol(QSsl::AnyProtocol);
 
895
        QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
 
896
        socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
897
        QVERIFY(socket->waitForEncrypted());
 
898
        QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
 
899
        socket->abort();
 
900
        QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
 
901
        socket->connectToHost(QtNetworkSettings::serverName(), 443);
 
902
        QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
 
903
        socket->startClientEncryption();
 
904
        QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
 
905
        QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
 
906
        socket->abort();
 
907
    }
 
908
    {
 
909
        // qt-test-server allows SSLV3, so it allows NoSslV2
 
910
        socket->setProtocol(QSsl::TlsV1SslV3);
 
911
        QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
 
912
        socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
913
        QVERIFY(socket->waitForEncrypted());
 
914
        QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
 
915
        socket->abort();
 
916
        QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
 
917
        socket->connectToHost(QtNetworkSettings::serverName(), 443);
 
918
        QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
 
919
        socket->startClientEncryption();
 
920
        QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
 
921
        QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
 
922
        socket->abort();
 
923
    }
 
924
}
 
925
 
 
926
class SslServer : public QTcpServer
 
927
{
 
928
    Q_OBJECT
 
929
public:
 
930
    SslServer(const QString &keyFile = SRCDIR "certs/fluke.key", const QString &certFile = SRCDIR "certs/fluke.cert")
 
931
        : socket(0),
 
932
          protocol(QSsl::TlsV1_0),
 
933
          m_keyFile(keyFile),
 
934
          m_certFile(certFile) { }
 
935
    QSslSocket *socket;
 
936
    QSsl::SslProtocol protocol;
 
937
    QString m_keyFile;
 
938
    QString m_certFile;
 
939
 
 
940
protected:
 
941
    void incomingConnection(qintptr socketDescriptor)
 
942
    {
 
943
        socket = new QSslSocket(this);
 
944
        socket->setProtocol(protocol);
 
945
        connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
 
946
 
 
947
        QFile file(m_keyFile);
 
948
        QVERIFY(file.open(QIODevice::ReadOnly));
 
949
        QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
 
950
        QVERIFY(!key.isNull());
 
951
        socket->setPrivateKey(key);
 
952
 
 
953
        QList<QSslCertificate> localCert = QSslCertificate::fromPath(m_certFile);
 
954
        QVERIFY(!localCert.isEmpty());
 
955
        QVERIFY(localCert.first().handle());
 
956
        socket->setLocalCertificate(localCert.first());
 
957
 
 
958
        QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState));
 
959
        QVERIFY(!socket->peerAddress().isNull());
 
960
        QVERIFY(socket->peerPort() != 0);
 
961
        QVERIFY(!socket->localAddress().isNull());
 
962
        QVERIFY(socket->localPort() != 0);
 
963
 
 
964
        socket->startServerEncryption();
 
965
    }
 
966
 
 
967
protected slots:
 
968
    void ignoreErrorSlot()
 
969
    {
 
970
        socket->ignoreSslErrors();
 
971
    }
 
972
};
 
973
 
 
974
void tst_QSslSocket::protocolServerSide_data()
 
975
{
 
976
    QTest::addColumn<QSsl::SslProtocol>("serverProtocol");
 
977
    QTest::addColumn<QSsl::SslProtocol>("clientProtocol");
 
978
    QTest::addColumn<bool>("works");
 
979
 
 
980
#ifndef OPENSSL_NO_SSL2
 
981
    QTest::newRow("ssl2-ssl2") << QSsl::SslV2 << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2
 
982
#endif
 
983
    QTest::newRow("ssl3-ssl3") << QSsl::SslV3 << QSsl::SslV3 << true;
 
984
    QTest::newRow("tls1.0-tls1.0") << QSsl::TlsV1_0 << QSsl::TlsV1_0 << true;
 
985
    QTest::newRow("tls1ssl3-tls1ssl3") << QSsl::TlsV1SslV3 << QSsl::TlsV1SslV3 << true;
 
986
    QTest::newRow("any-any") << QSsl::AnyProtocol << QSsl::AnyProtocol << true;
 
987
    QTest::newRow("secure-secure") << QSsl::SecureProtocols << QSsl::SecureProtocols << true;
 
988
 
 
989
#ifndef OPENSSL_NO_SSL2
 
990
    QTest::newRow("ssl2-ssl3") << QSsl::SslV2 << QSsl::SslV3 << false;
 
991
    QTest::newRow("ssl2-tls1.0") << QSsl::SslV2 << QSsl::TlsV1_0 << false;
 
992
    QTest::newRow("ssl2-tls1ssl3") << QSsl::SslV2 << QSsl::TlsV1SslV3 << false;
 
993
    QTest::newRow("ssl2-secure") << QSsl::SslV2 << QSsl::SecureProtocols << false;
 
994
    QTest::newRow("ssl2-any") << QSsl::SslV2 << QSsl::AnyProtocol << false; // no idea why it does not work, but we don't care about SSL 2
 
995
#endif
 
996
 
 
997
#ifndef OPENSSL_NO_SSL2
 
998
    QTest::newRow("ssl3-ssl2") << QSsl::SslV3 << QSsl::SslV2 << false;
 
999
#endif
 
1000
    QTest::newRow("ssl3-tls1.0") << QSsl::SslV3 << QSsl::TlsV1_0 << false;
 
1001
    QTest::newRow("ssl3-tls1ssl3") << QSsl::SslV3 << QSsl::TlsV1SslV3 << true;
 
1002
    QTest::newRow("ssl3-secure") << QSsl::SslV3 << QSsl::SecureProtocols << true;
 
1003
#ifndef OPENSSL_NO_SSL2
 
1004
    QTest::newRow("ssl3-any") << QSsl::SslV3 << QSsl::AnyProtocol << false; // we wont set a SNI header here because we connect to a
 
1005
                                                                            // numerical IP, so OpenSSL will send a SSL 2 handshake
 
1006
#else
 
1007
    QTest::newRow("ssl3-any") << QSsl::SslV3 << QSsl::AnyProtocol << true;
 
1008
#endif
 
1009
 
 
1010
#ifndef OPENSSL_NO_SSL2
 
1011
    QTest::newRow("tls1.0-ssl2") << QSsl::TlsV1_0 << QSsl::SslV2 << false;
 
1012
#endif
 
1013
    QTest::newRow("tls1.0-ssl3") << QSsl::TlsV1_0 << QSsl::SslV3 << false;
 
1014
    QTest::newRow("tls1-tls1ssl3") << QSsl::TlsV1_0 << QSsl::TlsV1SslV3 << true;
 
1015
    QTest::newRow("tls1.0-secure") << QSsl::TlsV1_0 << QSsl::SecureProtocols << true;
 
1016
#ifndef OPENSSL_NO_SSL2
 
1017
    QTest::newRow("tls1.0-any") << QSsl::TlsV1_0 << QSsl::AnyProtocol << false; // we wont set a SNI header here because we connect to a
 
1018
                                                                            // numerical IP, so OpenSSL will send a SSL 2 handshake
 
1019
#else
 
1020
    QTest::newRow("tls1.0-any") << QSsl::TlsV1_0 << QSsl::AnyProtocol << true;
 
1021
#endif
 
1022
 
 
1023
#ifndef OPENSSL_NO_SSL2
 
1024
    QTest::newRow("tls1ssl3-ssl2") << QSsl::TlsV1SslV3 << QSsl::SslV2 << false;
 
1025
#endif
 
1026
    QTest::newRow("tls1ssl3-ssl3") << QSsl::TlsV1SslV3 << QSsl::SslV3 << true;
 
1027
    QTest::newRow("tls1ssl3-tls1.0") << QSsl::TlsV1SslV3 << QSsl::TlsV1_0 << true;
 
1028
    QTest::newRow("tls1ssl3-secure") << QSsl::TlsV1SslV3 << QSsl::SecureProtocols << true;
 
1029
    QTest::newRow("tls1ssl3-any") << QSsl::TlsV1SslV3 << QSsl::AnyProtocol << true;
 
1030
 
 
1031
#ifndef OPENSSL_NO_SSL2
 
1032
    QTest::newRow("secure-ssl2") << QSsl::SecureProtocols << QSsl::SslV2 << false;
 
1033
#endif
 
1034
    QTest::newRow("secure-ssl3") << QSsl::SecureProtocols << QSsl::SslV3 << true;
 
1035
    QTest::newRow("secure-tls1.0") << QSsl::SecureProtocols << QSsl::TlsV1_0 << true;
 
1036
    QTest::newRow("secure-tls1ssl3") << QSsl::SecureProtocols << QSsl::TlsV1SslV3 << true;
 
1037
    QTest::newRow("secure-any") << QSsl::SecureProtocols << QSsl::AnyProtocol << true;
 
1038
 
 
1039
#ifndef OPENSSL_NO_SSL2
 
1040
    QTest::newRow("any-ssl2") << QSsl::AnyProtocol << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2
 
1041
#endif
 
1042
    QTest::newRow("any-ssl3") << QSsl::AnyProtocol << QSsl::SslV3 << true;
 
1043
    QTest::newRow("any-tls1.0") << QSsl::AnyProtocol << QSsl::TlsV1_0 << true;
 
1044
    QTest::newRow("any-tls1ssl3") << QSsl::AnyProtocol << QSsl::TlsV1SslV3 << true;
 
1045
    QTest::newRow("any-secure") << QSsl::AnyProtocol << QSsl::SecureProtocols << true;
 
1046
}
 
1047
 
 
1048
void tst_QSslSocket::protocolServerSide()
 
1049
{
 
1050
    if (!QSslSocket::supportsSsl()) {
 
1051
        qWarning("SSL not supported, skipping test");
 
1052
        return;
 
1053
    }
 
1054
 
 
1055
    QFETCH_GLOBAL(bool, setProxy);
 
1056
    if (setProxy)
 
1057
        return;
 
1058
 
 
1059
    QFETCH(QSsl::SslProtocol, serverProtocol);
 
1060
    SslServer server;
 
1061
    server.protocol = serverProtocol;
 
1062
    QVERIFY(server.listen());
 
1063
 
 
1064
    QEventLoop loop;
 
1065
    QTimer::singleShot(5000, &loop, SLOT(quit()));
 
1066
 
 
1067
    QSslSocketPtr client(new QSslSocket);
 
1068
    socket = client.data();
 
1069
    QFETCH(QSsl::SslProtocol, clientProtocol);
 
1070
    socket->setProtocol(clientProtocol);
 
1071
    // upon SSL wrong version error, error will be triggered, not sslErrors
 
1072
    connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit()));
 
1073
    connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
 
1074
    connect(socket, SIGNAL(encrypted()), &loop, SLOT(quit()));
 
1075
 
 
1076
    client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort());
 
1077
 
 
1078
    loop.exec();
 
1079
 
 
1080
    QFETCH(bool, works);
 
1081
    QAbstractSocket::SocketState expectedState = (works) ? QAbstractSocket::ConnectedState : QAbstractSocket::UnconnectedState;
 
1082
    QCOMPARE(int(client->state()), int(expectedState));
 
1083
    QCOMPARE(client->isEncrypted(), works);
 
1084
}
 
1085
 
 
1086
void tst_QSslSocket::setCaCertificates()
 
1087
{
 
1088
    if (!QSslSocket::supportsSsl())
 
1089
        return;
 
1090
 
 
1091
    QSslSocket socket;
 
1092
    QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates());
 
1093
    socket.setCaCertificates(QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"));
 
1094
    QCOMPARE(socket.caCertificates().size(), 1);
 
1095
    socket.setCaCertificates(socket.defaultCaCertificates());
 
1096
    QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates());
 
1097
}
 
1098
 
 
1099
void tst_QSslSocket::setLocalCertificate()
 
1100
{
 
1101
}
 
1102
 
 
1103
void tst_QSslSocket::setPrivateKey()
 
1104
{
 
1105
}
 
1106
 
 
1107
void tst_QSslSocket::setSocketDescriptor()
 
1108
{
 
1109
    if (!QSslSocket::supportsSsl())
 
1110
        return;
 
1111
 
 
1112
    QFETCH_GLOBAL(bool, setProxy);
 
1113
    if (setProxy)
 
1114
        return;
 
1115
 
 
1116
    SslServer server;
 
1117
    QVERIFY(server.listen());
 
1118
 
 
1119
    QEventLoop loop;
 
1120
    QTimer::singleShot(5000, &loop, SLOT(quit()));
 
1121
 
 
1122
    QSslSocketPtr client(new QSslSocket);
 
1123
    socket = client.data();;
 
1124
    connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
 
1125
    connect(socket, SIGNAL(encrypted()), &loop, SLOT(quit()));
 
1126
 
 
1127
    client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort());
 
1128
 
 
1129
    loop.exec();
 
1130
 
 
1131
    QCOMPARE(client->state(), QAbstractSocket::ConnectedState);
 
1132
    QVERIFY(client->isEncrypted());
 
1133
    QVERIFY(!client->peerAddress().isNull());
 
1134
    QVERIFY(client->peerPort() != 0);
 
1135
    QVERIFY(!client->localAddress().isNull());
 
1136
    QVERIFY(client->localPort() != 0);
 
1137
}
 
1138
 
 
1139
void tst_QSslSocket::setSslConfiguration_data()
 
1140
{
 
1141
    QTest::addColumn<QSslConfiguration>("configuration");
 
1142
    QTest::addColumn<bool>("works");
 
1143
 
 
1144
    QTest::newRow("empty") << QSslConfiguration() << false;
 
1145
    QSslConfiguration conf = QSslConfiguration::defaultConfiguration();
 
1146
    QTest::newRow("default") << conf << false; // does not contain test server cert
 
1147
    QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem");
 
1148
    conf.setCaCertificates(testServerCert);
 
1149
    QTest::newRow("set-root-cert") << conf << true;
 
1150
    conf.setProtocol(QSsl::SecureProtocols);
 
1151
    QTest::newRow("secure") << conf << true;
 
1152
}
 
1153
 
 
1154
void tst_QSslSocket::setSslConfiguration()
 
1155
{
 
1156
    if (!QSslSocket::supportsSsl())
 
1157
        return;
 
1158
 
 
1159
    QSslSocketPtr socket = newSocket();
 
1160
    QFETCH(QSslConfiguration, configuration);
 
1161
    socket->setSslConfiguration(configuration);
 
1162
    this->socket = socket.data();
 
1163
    socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
1164
    QFETCH(bool, works);
 
1165
    QCOMPARE(socket->waitForEncrypted(10000), works);
 
1166
    if (works) {
 
1167
        socket->disconnectFromHost();
 
1168
        QVERIFY2(socket->waitForDisconnected(), qPrintable(socket->errorString()));
 
1169
    }
 
1170
}
 
1171
 
 
1172
void tst_QSslSocket::waitForEncrypted()
 
1173
{
 
1174
    if (!QSslSocket::supportsSsl())
 
1175
        return;
 
1176
 
 
1177
    QSslSocketPtr socket = newSocket();
 
1178
    this->socket = socket.data();
 
1179
 
 
1180
    connect(this->socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
 
1181
    socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
1182
 
 
1183
    QVERIFY(socket->waitForEncrypted(10000));
 
1184
}
 
1185
 
 
1186
void tst_QSslSocket::waitForEncryptedMinusOne()
 
1187
{
 
1188
#ifdef Q_OS_WIN
 
1189
    QSKIP("QTBUG-24451 - indefinite wait may hang");
 
1190
#endif
 
1191
    if (!QSslSocket::supportsSsl())
 
1192
        return;
 
1193
 
 
1194
    QSslSocketPtr socket = newSocket();
 
1195
    this->socket = socket.data();
 
1196
 
 
1197
    connect(this->socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
 
1198
    socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
1199
 
 
1200
    QVERIFY(socket->waitForEncrypted(-1));
 
1201
}
 
1202
 
 
1203
void tst_QSslSocket::waitForConnectedEncryptedReadyRead()
 
1204
{
 
1205
    if (!QSslSocket::supportsSsl())
 
1206
        return;
 
1207
 
 
1208
    QSslSocketPtr socket = newSocket();
 
1209
    this->socket = socket.data();
 
1210
 
 
1211
    connect(this->socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
 
1212
    socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
 
1213
 
 
1214
    QVERIFY(socket->waitForConnected(10000));
 
1215
    QVERIFY(socket->waitForEncrypted(10000));
 
1216
    QVERIFY(socket->waitForReadyRead(10000));
 
1217
    QVERIFY(!socket->peerCertificate().isNull());
 
1218
    QVERIFY(!socket->peerCertificateChain().isEmpty());
 
1219
}
 
1220
 
 
1221
void tst_QSslSocket::startClientEncryption()
 
1222
{
 
1223
}
 
1224
 
 
1225
void tst_QSslSocket::startServerEncryption()
 
1226
{
 
1227
}
 
1228
 
 
1229
void tst_QSslSocket::addDefaultCaCertificate()
 
1230
{
 
1231
    if (!QSslSocket::supportsSsl())
 
1232
        return;
 
1233
 
 
1234
    // Reset the global CA chain
 
1235
    QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
 
1236
 
 
1237
    QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem");
 
1238
    QCOMPARE(flukeCerts.size(), 1);
 
1239
    QList<QSslCertificate> globalCerts = QSslSocket::defaultCaCertificates();
 
1240
    QVERIFY(!globalCerts.contains(flukeCerts.first()));
 
1241
    QSslSocket::addDefaultCaCertificate(flukeCerts.first());
 
1242
    QCOMPARE(QSslSocket::defaultCaCertificates().size(), globalCerts.size() + 1);
 
1243
    QVERIFY(QSslSocket::defaultCaCertificates().contains(flukeCerts.first()));
 
1244
 
 
1245
    // Restore the global CA chain
 
1246
    QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
 
1247
}
 
1248
 
 
1249
void tst_QSslSocket::addDefaultCaCertificates()
 
1250
{
 
1251
}
 
1252
 
 
1253
void tst_QSslSocket::addDefaultCaCertificates2()
 
1254
{
 
1255
}
 
1256
 
 
1257
void tst_QSslSocket::defaultCaCertificates()
 
1258
{
 
1259
    if (!QSslSocket::supportsSsl())
 
1260
        return;
 
1261
 
 
1262
    QList<QSslCertificate> certs = QSslSocket::defaultCaCertificates();
 
1263
    QVERIFY(certs.size() > 1);
 
1264
    QCOMPARE(certs, QSslSocket::systemCaCertificates());
 
1265
}
 
1266
 
 
1267
void tst_QSslSocket::defaultCiphers()
 
1268
{
 
1269
}
 
1270
 
 
1271
void tst_QSslSocket::resetDefaultCiphers()
 
1272
{
 
1273
}
 
1274
 
 
1275
void tst_QSslSocket::setDefaultCaCertificates()
 
1276
{
 
1277
}
 
1278
 
 
1279
void tst_QSslSocket::setDefaultCiphers()
 
1280
{
 
1281
}
 
1282
 
 
1283
void tst_QSslSocket::supportedCiphers()
 
1284
{
 
1285
    if (!QSslSocket::supportsSsl())
 
1286
        return;
 
1287
 
 
1288
    QList<QSslCipher> ciphers = QSslSocket::supportedCiphers();
 
1289
    QVERIFY(ciphers.size() > 1);
 
1290
 
 
1291
    QSslSocket socket;
 
1292
    QCOMPARE(socket.supportedCiphers(), ciphers);
 
1293
    QCOMPARE(socket.defaultCiphers(), ciphers);
 
1294
    QCOMPARE(socket.ciphers(), ciphers);
 
1295
}
 
1296
 
 
1297
void tst_QSslSocket::systemCaCertificates()
 
1298
{
 
1299
    if (!QSslSocket::supportsSsl())
 
1300
        return;
 
1301
 
 
1302
    QList<QSslCertificate> certs = QSslSocket::systemCaCertificates();
 
1303
    QVERIFY(certs.size() > 1);
 
1304
    QCOMPARE(certs, QSslSocket::defaultCaCertificates());
 
1305
}
 
1306
 
 
1307
void tst_QSslSocket::wildcardCertificateNames()
 
1308
{
 
1309
    // Passing CN matches
 
1310
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("www.example.com"), QString("www.example.com")), true );
 
1311
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.example.com"), QString("www.example.com")), true );
 
1312
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("xxx*.example.com"), QString("xxxwww.example.com")), true );
 
1313
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("f*.example.com"), QString("foo.example.com")), true );
 
1314
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("192.168.0.0"), QString("192.168.0.0")), true );
 
1315
 
 
1316
    // Failing CN matches
 
1317
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("xxx.example.com"), QString("www.example.com")), false );
 
1318
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*"), QString("www.example.com")), false );
 
1319
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.*.com"), QString("www.example.com")), false );
 
1320
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.example.com"), QString("baa.foo.example.com")), false );
 
1321
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("f*.example.com"), QString("baa.example.com")), false );
 
1322
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.com"), QString("example.com")), false );
 
1323
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*fail.com"), QString("example.com")), false );
 
1324
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.example."), QString("www.example.")), false );
 
1325
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.example."), QString("www.example")), false );
 
1326
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString(""), QString("www")), false );
 
1327
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*"), QString("www")), false );
 
1328
    QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.168.0.0"), QString("192.168.0.0")), false );
 
1329
}
 
1330
 
 
1331
void tst_QSslSocket::wildcard()
 
1332
{
 
1333
    QSKIP("TODO: solve wildcard problem");
 
1334
 
 
1335
    if (!QSslSocket::supportsSsl())
 
1336
        return;
 
1337
 
 
1338
    // Fluke runs an apache server listening on port 4443, serving the
 
1339
    // wildcard fluke.*.troll.no.  The DNS entry for
 
1340
    // fluke.wildcard.dev.troll.no, served by ares (root for dev.troll.no),
 
1341
    // returns the CNAME fluke.troll.no for this domain. The web server
 
1342
    // responds with the wildcard, and QSslSocket should accept that as a
 
1343
    // valid connection.  This was broken in 4.3.0.
 
1344
    QSslSocketPtr socket = newSocket();
 
1345
    socket->addCaCertificates(QLatin1String("certs/aspiriniks.ca.crt"));
 
1346
    this->socket = socket.data();
 
1347
#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
 
1348
    connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
 
1349
            this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
 
1350
#endif
 
1351
    socket->connectToHostEncrypted(QtNetworkSettings::wildcardServerName(), 4443);
 
1352
 
 
1353
    QVERIFY2(socket->waitForEncrypted(3000), qPrintable(socket->errorString()));
 
1354
 
 
1355
    QSslCertificate certificate = socket->peerCertificate();
 
1356
    QVERIFY(certificate.subjectInfo(QSslCertificate::CommonName).contains(QString(QtNetworkSettings::serverLocalName() + ".*." + QtNetworkSettings::serverDomainName())));
 
1357
    QVERIFY(certificate.issuerInfo(QSslCertificate::CommonName).contains(QtNetworkSettings::serverName()));
 
1358
 
 
1359
    socket->close();
 
1360
}
 
1361
 
 
1362
class SslServer2 : public QTcpServer
 
1363
{
 
1364
protected:
 
1365
    void incomingConnection(qintptr socketDescriptor)
 
1366
    {
 
1367
        QSslSocket *socket = new QSslSocket(this);
 
1368
        socket->ignoreSslErrors();
 
1369
 
 
1370
        // Only set the certificate
 
1371
        QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert");
 
1372
        QVERIFY(!localCert.isEmpty());
 
1373
        QVERIFY(localCert.first().handle());
 
1374
        socket->setLocalCertificate(localCert.first());
 
1375
 
 
1376
        QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState));
 
1377
 
 
1378
        socket->startServerEncryption();
 
1379
    }
 
1380
};
 
1381
 
 
1382
void tst_QSslSocket::setEmptyKey()
 
1383
{
 
1384
    if (!QSslSocket::supportsSsl())
 
1385
        return;
 
1386
 
 
1387
    QFETCH_GLOBAL(bool, setProxy);
 
1388
    if (setProxy)
 
1389
        return;
 
1390
 
 
1391
    SslServer2 server;
 
1392
    server.listen();
 
1393
 
 
1394
    QSslSocket socket;
 
1395
    socket.connectToHostEncrypted("127.0.0.1", server.serverPort());
 
1396
 
 
1397
    QTestEventLoop::instance().enterLoop(2);
 
1398
 
 
1399
    QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
 
1400
    QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
 
1401
}
 
1402
 
 
1403
void tst_QSslSocket::spontaneousWrite()
 
1404
{
 
1405
    QFETCH_GLOBAL(bool, setProxy);
 
1406
    if (setProxy)
 
1407
        return;
 
1408
 
 
1409
    SslServer server;
 
1410
    QSslSocket *receiver = new QSslSocket(this);
 
1411
    connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop()));
 
1412
 
 
1413
    // connect two sockets to each other:
 
1414
    QVERIFY(server.listen(QHostAddress::LocalHost));
 
1415
    receiver->connectToHost("127.0.0.1", server.serverPort());
 
1416
    QVERIFY(receiver->waitForConnected(5000));
 
1417
    QVERIFY(server.waitForNewConnection(0));
 
1418
 
 
1419
    QSslSocket *sender = server.socket;
 
1420
    QVERIFY(sender);
 
1421
    QVERIFY(sender->state() == QAbstractSocket::ConnectedState);
 
1422
    receiver->setObjectName("receiver");
 
1423
    sender->setObjectName("sender");
 
1424
    receiver->ignoreSslErrors();
 
1425
    receiver->startClientEncryption();
 
1426
 
 
1427
    // SSL handshake:
 
1428
    connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop()));
 
1429
    enterLoop(1);
 
1430
    QVERIFY(!timeout());
 
1431
    QVERIFY(sender->isEncrypted());
 
1432
    QVERIFY(receiver->isEncrypted());
 
1433
 
 
1434
    // make sure there's nothing to be received on the sender:
 
1435
    while (sender->waitForReadyRead(10) || receiver->waitForBytesWritten(10)) {}
 
1436
 
 
1437
    // spontaneously write something:
 
1438
    QByteArray data("Hello World");
 
1439
    sender->write(data);
 
1440
 
 
1441
    // check if the other side receives it:
 
1442
    enterLoop(1);
 
1443
    QVERIFY(!timeout());
 
1444
    QCOMPARE(receiver->bytesAvailable(), qint64(data.size()));
 
1445
    QCOMPARE(receiver->readAll(), data);
 
1446
}
 
1447
 
 
1448
void tst_QSslSocket::setReadBufferSize()
 
1449
{
 
1450
    QFETCH_GLOBAL(bool, setProxy);
 
1451
    if (setProxy)
 
1452
        return;
 
1453
 
 
1454
    SslServer server;
 
1455
    QSslSocket *receiver = new QSslSocket(this);
 
1456
    connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop()));
 
1457
 
 
1458
    // connect two sockets to each other:
 
1459
    QVERIFY(server.listen(QHostAddress::LocalHost));
 
1460
    receiver->connectToHost("127.0.0.1", server.serverPort());
 
1461
    QVERIFY(receiver->waitForConnected(5000));
 
1462
    QVERIFY(server.waitForNewConnection(0));
 
1463
 
 
1464
    QSslSocket *sender = server.socket;
 
1465
    QVERIFY(sender);
 
1466
    QVERIFY(sender->state() == QAbstractSocket::ConnectedState);
 
1467
    receiver->setObjectName("receiver");
 
1468
    sender->setObjectName("sender");
 
1469
    receiver->ignoreSslErrors();
 
1470
    receiver->startClientEncryption();
 
1471
 
 
1472
    // SSL handshake:
 
1473
    connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop()));
 
1474
    enterLoop(1);
 
1475
    QVERIFY(!timeout());
 
1476
    QVERIFY(sender->isEncrypted());
 
1477
    QVERIFY(receiver->isEncrypted());
 
1478
 
 
1479
    QByteArray data(2048, 'b');
 
1480
    receiver->setReadBufferSize(39 * 1024); // make it a non-multiple of the data.size()
 
1481
 
 
1482
    // saturate the incoming buffer
 
1483
    while (sender->state() == QAbstractSocket::ConnectedState &&
 
1484
           receiver->state() == QAbstractSocket::ConnectedState &&
 
1485
           receiver->bytesAvailable() < receiver->readBufferSize()) {
 
1486
        sender->write(data);
 
1487
        //qDebug() << receiver->bytesAvailable() << "<" << receiver->readBufferSize() << (receiver->bytesAvailable() < receiver->readBufferSize());
 
1488
 
 
1489
        while (sender->bytesToWrite())
 
1490
            QVERIFY(sender->waitForBytesWritten(10));
 
1491
 
 
1492
        // drain it:
 
1493
        while (receiver->bytesAvailable() < receiver->readBufferSize() &&
 
1494
               receiver->waitForReadyRead(10)) {}
 
1495
    }
 
1496
 
 
1497
    //qDebug() << sender->bytesToWrite() << "bytes to write";
 
1498
    //qDebug() << receiver->bytesAvailable() << "bytes available";
 
1499
 
 
1500
    // send a bit more
 
1501
    sender->write(data);
 
1502
    sender->write(data);
 
1503
    sender->write(data);
 
1504
    sender->write(data);
 
1505
    QVERIFY(sender->waitForBytesWritten(10));
 
1506
 
 
1507
    qint64 oldBytesAvailable = receiver->bytesAvailable();
 
1508
 
 
1509
    // now unset the read buffer limit and iterate
 
1510
    receiver->setReadBufferSize(0);
 
1511
    enterLoop(1);
 
1512
    QVERIFY(!timeout());
 
1513
 
 
1514
    QVERIFY(receiver->bytesAvailable() > oldBytesAvailable);
 
1515
}
 
1516
 
 
1517
class SetReadBufferSize_task_250027_handler : public QObject {
 
1518
    Q_OBJECT
 
1519
public slots:
 
1520
    void readyReadSlot() {
 
1521
        QTestEventLoop::instance().exitLoop();
 
1522
    }
 
1523
    void waitSomeMore(QSslSocket *socket) {
 
1524
        QTime t;
 
1525
        t.start();
 
1526
        while (!socket->encryptedBytesAvailable()) {
 
1527
            QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents, 250);
 
1528
            if (t.elapsed() > 1000 || socket->state() != QAbstractSocket::ConnectedState)
 
1529
                return;
 
1530
        }
 
1531
    }
 
1532
};
 
1533
 
 
1534
void tst_QSslSocket::setReadBufferSize_task_250027()
 
1535
{
 
1536
    // do not execute this when a proxy is set.
 
1537
    QFETCH_GLOBAL(bool, setProxy);
 
1538
    if (setProxy)
 
1539
        return;
 
1540
 
 
1541
    QSslSocketPtr socket = newSocket();
 
1542
    socket->setReadBufferSize(1000); // limit to 1 kb/sec
 
1543
    socket->ignoreSslErrors();
 
1544
    socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
1545
    socket->ignoreSslErrors();
 
1546
    QVERIFY(socket->waitForConnected(10*1000));
 
1547
    QVERIFY(socket->waitForEncrypted(10*1000));
 
1548
 
 
1549
    // exit the event loop as soon as we receive a readyRead()
 
1550
    SetReadBufferSize_task_250027_handler setReadBufferSize_task_250027_handler;
 
1551
    connect(socket.data(), SIGNAL(readyRead()), &setReadBufferSize_task_250027_handler, SLOT(readyReadSlot()));
 
1552
 
 
1553
    // provoke a response by sending a request
 
1554
    socket->write("GET /qtest/fluke.gif HTTP/1.0\n"); // this file is 27 KB
 
1555
    socket->write("Host: ");
 
1556
    socket->write(QtNetworkSettings::serverName().toLocal8Bit().constData());
 
1557
    socket->write("\n");
 
1558
    socket->write("Connection: close\n");
 
1559
    socket->write("\n");
 
1560
    socket->flush();
 
1561
 
 
1562
    QTestEventLoop::instance().enterLoop(10);
 
1563
    setReadBufferSize_task_250027_handler.waitSomeMore(socket.data());
 
1564
    QByteArray firstRead = socket->readAll();
 
1565
    // First read should be some data, but not the whole file
 
1566
    QVERIFY(firstRead.size() > 0 && firstRead.size() < 20*1024);
 
1567
 
 
1568
    QTestEventLoop::instance().enterLoop(10);
 
1569
    setReadBufferSize_task_250027_handler.waitSomeMore(socket.data());
 
1570
    QByteArray secondRead = socket->readAll();
 
1571
    // second read should be some more data
 
1572
    QVERIFY(secondRead.size() > 0);
 
1573
 
 
1574
    socket->close();
 
1575
}
 
1576
 
 
1577
class SslServer3 : public QTcpServer
 
1578
{
 
1579
    Q_OBJECT
 
1580
public:
 
1581
    SslServer3() : socket(0) { }
 
1582
    QSslSocket *socket;
 
1583
 
 
1584
protected:
 
1585
    void incomingConnection(qintptr socketDescriptor)
 
1586
    {
 
1587
        socket = new QSslSocket(this);
 
1588
        connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
 
1589
 
 
1590
        QFile file(SRCDIR "certs/fluke.key");
 
1591
        QVERIFY(file.open(QIODevice::ReadOnly));
 
1592
        QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
 
1593
        QVERIFY(!key.isNull());
 
1594
        socket->setPrivateKey(key);
 
1595
 
 
1596
        QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert");
 
1597
        QVERIFY(!localCert.isEmpty());
 
1598
        QVERIFY(localCert.first().handle());
 
1599
        socket->setLocalCertificate(localCert.first());
 
1600
 
 
1601
        QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState));
 
1602
        QVERIFY(!socket->peerAddress().isNull());
 
1603
        QVERIFY(socket->peerPort() != 0);
 
1604
        QVERIFY(!socket->localAddress().isNull());
 
1605
        QVERIFY(socket->localPort() != 0);
 
1606
    }
 
1607
 
 
1608
protected slots:
 
1609
    void ignoreErrorSlot()
 
1610
    {
 
1611
        socket->ignoreSslErrors();
 
1612
    }
 
1613
};
 
1614
 
 
1615
class ThreadedSslServer: public QThread
 
1616
{
 
1617
    Q_OBJECT
 
1618
public:
 
1619
    QSemaphore dataReadSemaphore;
 
1620
    int serverPort;
 
1621
    bool ok;
 
1622
 
 
1623
    ThreadedSslServer() : serverPort(-1), ok(false)
 
1624
    { }
 
1625
 
 
1626
    ~ThreadedSslServer()
 
1627
    {
 
1628
        if (isRunning()) wait(2000);
 
1629
        QVERIFY(ok);
 
1630
    }
 
1631
 
 
1632
signals:
 
1633
    void listening();
 
1634
 
 
1635
protected:
 
1636
    void run()
 
1637
    {
 
1638
        // if all goes well (no timeouts), this thread will sleep for a total of 500 ms
 
1639
        // (i.e., 5 times 100 ms, one sleep for each operation)
 
1640
 
 
1641
        SslServer3 server;
 
1642
        server.listen(QHostAddress::LocalHost);
 
1643
        serverPort = server.serverPort();
 
1644
        emit listening();
 
1645
 
 
1646
        // delayed acceptance:
 
1647
        QTest::qSleep(100);
 
1648
        bool ret = server.waitForNewConnection(2000);
 
1649
        Q_UNUSED(ret);
 
1650
 
 
1651
        // delayed start of encryption
 
1652
        QTest::qSleep(100);
 
1653
        QSslSocket *socket = server.socket;
 
1654
        if (!socket || !socket->isValid())
 
1655
            return;             // error
 
1656
        socket->ignoreSslErrors();
 
1657
        socket->startServerEncryption();
 
1658
        if (!socket->waitForEncrypted(2000))
 
1659
            return;             // error
 
1660
 
 
1661
        // delayed reading data
 
1662
        QTest::qSleep(100);
 
1663
        if (!socket->waitForReadyRead(2000))
 
1664
            return;             // error
 
1665
        socket->readAll();
 
1666
        dataReadSemaphore.release();
 
1667
 
 
1668
        // delayed sending data
 
1669
        QTest::qSleep(100);
 
1670
        socket->write("Hello, World");
 
1671
        while (socket->bytesToWrite())
 
1672
            if (!socket->waitForBytesWritten(2000))
 
1673
                return;         // error
 
1674
 
 
1675
        // delayed replying (reading then sending)
 
1676
        QTest::qSleep(100);
 
1677
        if (!socket->waitForReadyRead(2000))
 
1678
            return;             // error
 
1679
        socket->write("Hello, World");
 
1680
        while (socket->bytesToWrite())
 
1681
            if (!socket->waitForBytesWritten(2000))
 
1682
                return;         // error
 
1683
 
 
1684
        // delayed disconnection:
 
1685
        QTest::qSleep(100);
 
1686
        socket->disconnectFromHost();
 
1687
        if (!socket->waitForDisconnected(2000))
 
1688
            return;             // error
 
1689
 
 
1690
        delete socket;
 
1691
        ok = true;
 
1692
    }
 
1693
};
 
1694
 
 
1695
void tst_QSslSocket::waitForMinusOne()
 
1696
{
 
1697
#ifdef Q_OS_WIN
 
1698
    QSKIP("QTBUG-24451 - indefinite wait may hang");
 
1699
#endif
 
1700
    QFETCH_GLOBAL(bool, setProxy);
 
1701
    if (setProxy)
 
1702
        return;
 
1703
 
 
1704
    ThreadedSslServer server;
 
1705
    connect(&server, SIGNAL(listening()), SLOT(exitLoop()));
 
1706
 
 
1707
    // start the thread and wait for it to be ready
 
1708
    server.start();
 
1709
    enterLoop(1);
 
1710
    QVERIFY(!timeout());
 
1711
 
 
1712
    // connect to the server
 
1713
    QSslSocket socket;
 
1714
    QTest::qSleep(100);
 
1715
    socket.connectToHost("127.0.0.1", server.serverPort);
 
1716
    QVERIFY(socket.waitForConnected(-1));
 
1717
    socket.ignoreSslErrors();
 
1718
    socket.startClientEncryption();
 
1719
 
 
1720
    // first verification: this waiting should take 200 ms
 
1721
    QVERIFY2(socket.waitForEncrypted(-1), qPrintable(socket.errorString()));
 
1722
    QVERIFY(socket.isEncrypted());
 
1723
    QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
 
1724
    QCOMPARE(socket.bytesAvailable(), Q_INT64_C(0));
 
1725
 
 
1726
    // second verification: write and make sure the other side got it (100 ms)
 
1727
    socket.write("How are you doing?");
 
1728
    QVERIFY(socket.bytesToWrite() != 0);
 
1729
    QVERIFY(socket.waitForBytesWritten(-1));
 
1730
    QVERIFY(server.dataReadSemaphore.tryAcquire(1, 2000));
 
1731
 
 
1732
    // third verification: it should wait for 100 ms:
 
1733
    QVERIFY(socket.waitForReadyRead(-1));
 
1734
    QVERIFY(socket.isEncrypted());
 
1735
    QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
 
1736
    QVERIFY(socket.bytesAvailable() != 0);
 
1737
 
 
1738
    // fourth verification: deadlock prevention:
 
1739
    // we write and then wait for reading; the other side needs to receive before
 
1740
    // replying (100 ms delay)
 
1741
    socket.write("I'm doing just fine!");
 
1742
    QVERIFY(socket.bytesToWrite() != 0);
 
1743
    QVERIFY(socket.waitForReadyRead(-1));
 
1744
 
 
1745
    // fifth verification: it should wait for 200 ms more
 
1746
    QVERIFY(socket.waitForDisconnected(-1));
 
1747
}
 
1748
 
 
1749
class VerifyServer : public QTcpServer
 
1750
{
 
1751
    Q_OBJECT
 
1752
public:
 
1753
    VerifyServer() : socket(0) { }
 
1754
    QSslSocket *socket;
 
1755
 
 
1756
protected:
 
1757
    void incomingConnection(qintptr socketDescriptor)
 
1758
    {
 
1759
        socket = new QSslSocket(this);
 
1760
 
 
1761
        socket->setPrivateKey(SRCDIR "certs/fluke.key");
 
1762
        socket->setLocalCertificate(SRCDIR "certs/fluke.cert");
 
1763
        socket->setSocketDescriptor(socketDescriptor);
 
1764
        socket->startServerEncryption();
 
1765
    }
 
1766
};
 
1767
 
 
1768
void tst_QSslSocket::verifyMode()
 
1769
{
 
1770
    QFETCH_GLOBAL(bool, setProxy);
 
1771
    if (setProxy)
 
1772
        return;
 
1773
 
 
1774
    QSslSocket socket;
 
1775
    QCOMPARE(socket.peerVerifyMode(), QSslSocket::AutoVerifyPeer);
 
1776
    socket.setPeerVerifyMode(QSslSocket::VerifyNone);
 
1777
    QCOMPARE(socket.peerVerifyMode(), QSslSocket::VerifyNone);
 
1778
    socket.setPeerVerifyMode(QSslSocket::VerifyNone);
 
1779
    socket.setPeerVerifyMode(QSslSocket::VerifyPeer);
 
1780
    QCOMPARE(socket.peerVerifyMode(), QSslSocket::VerifyPeer);
 
1781
 
 
1782
    socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
1783
    QVERIFY(!socket.waitForEncrypted());
 
1784
 
 
1785
    QList<QSslError> expectedErrors = QList<QSslError>()
 
1786
                                      << QSslError(QSslError::SelfSignedCertificate, socket.peerCertificate());
 
1787
    QCOMPARE(socket.sslErrors(), expectedErrors);
 
1788
    socket.abort();
 
1789
 
 
1790
    VerifyServer server;
 
1791
    server.listen();
 
1792
 
 
1793
    QSslSocket clientSocket;
 
1794
    clientSocket.connectToHostEncrypted("127.0.0.1", server.serverPort());
 
1795
    clientSocket.ignoreSslErrors();
 
1796
 
 
1797
    QEventLoop loop;
 
1798
    QTimer::singleShot(5000, &loop, SLOT(quit()));
 
1799
    connect(&clientSocket, SIGNAL(encrypted()), &loop, SLOT(quit()));
 
1800
    loop.exec();
 
1801
 
 
1802
    QVERIFY(clientSocket.isEncrypted());
 
1803
#if (defined(UBUNTU_ONEIRIC) && defined(__x86_64__)) || defined(Q_OS_WIN) || defined(Q_OS_MAC)
 
1804
    QEXPECT_FAIL("", "QTBUG-24234", Abort);
 
1805
#endif
 
1806
    QVERIFY(server.socket->sslErrors().isEmpty());
 
1807
}
 
1808
 
 
1809
void tst_QSslSocket::verifyDepth()
 
1810
{
 
1811
    QSslSocket socket;
 
1812
    QCOMPARE(socket.peerVerifyDepth(), 0);
 
1813
    socket.setPeerVerifyDepth(1);
 
1814
    QCOMPARE(socket.peerVerifyDepth(), 1);
 
1815
    QTest::ignoreMessage(QtWarningMsg, "QSslSocket::setPeerVerifyDepth: cannot set negative depth of -1");
 
1816
    socket.setPeerVerifyDepth(-1);
 
1817
    QCOMPARE(socket.peerVerifyDepth(), 1);
 
1818
}
 
1819
 
 
1820
void tst_QSslSocket::peerVerifyError()
 
1821
{
 
1822
    QSslSocketPtr socket = newSocket();
 
1823
    QSignalSpy sslErrorsSpy(socket.data(), SIGNAL(sslErrors(QList<QSslError>)));
 
1824
    QSignalSpy peerVerifyErrorSpy(socket.data(), SIGNAL(peerVerifyError(QSslError)));
 
1825
 
 
1826
    socket->connectToHostEncrypted(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(), 443);
 
1827
    QVERIFY(!socket->waitForEncrypted(10000));
 
1828
    QVERIFY(!peerVerifyErrorSpy.isEmpty());
 
1829
    QVERIFY(!sslErrorsSpy.isEmpty());
 
1830
    QCOMPARE(qvariant_cast<QSslError>(peerVerifyErrorSpy.last().at(0)).error(), QSslError::HostNameMismatch);
 
1831
    QCOMPARE(qvariant_cast<QList<QSslError> >(sslErrorsSpy.at(0).at(0)).size(), peerVerifyErrorSpy.size());
 
1832
}
 
1833
 
 
1834
void tst_QSslSocket::disconnectFromHostWhenConnecting()
 
1835
{
 
1836
    QSslSocketPtr socket = newSocket();
 
1837
    socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
 
1838
    socket->ignoreSslErrors();
 
1839
    socket->write("XXXX LOGOUT\r\n");
 
1840
    QAbstractSocket::SocketState state = socket->state();
 
1841
    // without proxy, the state will be HostLookupState;
 
1842
    // with    proxy, the state will be ConnectingState.
 
1843
    QVERIFY(socket->state() == QAbstractSocket::HostLookupState ||
 
1844
            socket->state() == QAbstractSocket::ConnectingState);
 
1845
    socket->disconnectFromHost();
 
1846
    // the state of the socket must be the same before and after calling
 
1847
    // disconnectFromHost()
 
1848
    QCOMPARE(state, socket->state());
 
1849
    QVERIFY(socket->state() == QAbstractSocket::HostLookupState ||
 
1850
            socket->state() == QAbstractSocket::ConnectingState);
 
1851
    QVERIFY(socket->waitForDisconnected(10000));
 
1852
    QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
 
1853
    // we did not call close, so the socket must be still open
 
1854
    QVERIFY(socket->isOpen());
 
1855
    QCOMPARE(socket->bytesToWrite(), qint64(0));
 
1856
 
 
1857
    // don't forget to login
 
1858
    QCOMPARE((int) socket->write("USER ftptest\r\n"), 14);
 
1859
 
 
1860
}
 
1861
 
 
1862
void tst_QSslSocket::disconnectFromHostWhenConnected()
 
1863
{
 
1864
    QSslSocketPtr socket = newSocket();
 
1865
    socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
 
1866
    socket->ignoreSslErrors();
 
1867
    QVERIFY(socket->waitForEncrypted(5000));
 
1868
    socket->write("XXXX LOGOUT\r\n");
 
1869
    QCOMPARE(socket->state(), QAbstractSocket::ConnectedState);
 
1870
    socket->disconnectFromHost();
 
1871
    QCOMPARE(socket->state(), QAbstractSocket::ClosingState);
 
1872
    QVERIFY(socket->waitForDisconnected(5000));
 
1873
    QCOMPARE(socket->bytesToWrite(), qint64(0));
 
1874
}
 
1875
 
 
1876
void tst_QSslSocket::resetProxy()
 
1877
{
 
1878
    QFETCH_GLOBAL(bool, setProxy);
 
1879
    if (setProxy)
 
1880
        return;
 
1881
 
 
1882
    // check fix for bug 199941
 
1883
 
 
1884
    QNetworkProxy goodProxy(QNetworkProxy::NoProxy);
 
1885
    QNetworkProxy badProxy(QNetworkProxy::HttpProxy, "thisCannotWorkAbsolutelyNotForSure", 333);
 
1886
 
 
1887
    // make sure the connection works, and then set a nonsense proxy, and then
 
1888
    // make sure it does not work anymore
 
1889
    QSslSocket socket;
 
1890
    socket.addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
 
1891
    socket.setProxy(goodProxy);
 
1892
    socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
1893
    QVERIFY2(socket.waitForConnected(10000), qPrintable(socket.errorString()));
 
1894
    socket.abort();
 
1895
    socket.setProxy(badProxy);
 
1896
    socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
1897
    QVERIFY(! socket.waitForConnected(10000));
 
1898
 
 
1899
    // don't forget to login
 
1900
    QCOMPARE((int) socket.write("USER ftptest\r\n"), 14);
 
1901
    QCOMPARE((int) socket.write("PASS password\r\n"), 15);
 
1902
 
 
1903
    enterLoop(10);
 
1904
 
 
1905
    // now the other way round:
 
1906
    // set the nonsense proxy and make sure the connection does not work,
 
1907
    // and then set the right proxy and make sure it works
 
1908
    QSslSocket socket2;
 
1909
    socket2.addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
 
1910
    socket2.setProxy(badProxy);
 
1911
    socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
1912
    QVERIFY(! socket2.waitForConnected(10000));
 
1913
    socket2.abort();
 
1914
    socket2.setProxy(goodProxy);
 
1915
    socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
1916
    QVERIFY2(socket2.waitForConnected(10000), qPrintable(socket.errorString()));
 
1917
}
 
1918
 
 
1919
void tst_QSslSocket::ignoreSslErrorsList_data()
 
1920
{
 
1921
    QTest::addColumn<QList<QSslError> >("expectedSslErrors");
 
1922
    QTest::addColumn<int>("expectedSslErrorSignalCount");
 
1923
 
 
1924
    // construct the list of errors that we will get with the SSL handshake and that we will ignore
 
1925
    QList<QSslError> expectedSslErrors;
 
1926
    // fromPath gives us a list of certs, but it actually only contains one
 
1927
    QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
 
1928
    QSslError rightError(QSslError::SelfSignedCertificate, certs.at(0));
 
1929
    QSslError wrongError(QSslError::SelfSignedCertificate);
 
1930
 
 
1931
 
 
1932
    QTest::newRow("SSL-failure-empty-list") << expectedSslErrors << 1;
 
1933
    expectedSslErrors.append(wrongError);
 
1934
    QTest::newRow("SSL-failure-wrong-error") << expectedSslErrors << 1;
 
1935
    expectedSslErrors.append(rightError);
 
1936
    QTest::newRow("allErrorsInExpectedList1") << expectedSslErrors << 0;
 
1937
    expectedSslErrors.removeAll(wrongError);
 
1938
    QTest::newRow("allErrorsInExpectedList2") << expectedSslErrors << 0;
 
1939
    expectedSslErrors.removeAll(rightError);
 
1940
    QTest::newRow("SSL-failure-empty-list-again") << expectedSslErrors << 1;
 
1941
}
 
1942
 
 
1943
void tst_QSslSocket::ignoreSslErrorsList()
 
1944
{
 
1945
    QSslSocket socket;
 
1946
    connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
 
1947
            this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
 
1948
 
 
1949
//    this->socket = &socket;
 
1950
    QSslCertificate cert;
 
1951
 
 
1952
    QFETCH(QList<QSslError>, expectedSslErrors);
 
1953
    socket.ignoreSslErrors(expectedSslErrors);
 
1954
 
 
1955
    QFETCH(int, expectedSslErrorSignalCount);
 
1956
    QSignalSpy sslErrorsSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
 
1957
 
 
1958
    socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
1959
 
 
1960
    bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
 
1961
    QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess);
 
1962
    QCOMPARE(sslErrorsSpy.count(), expectedSslErrorSignalCount);
 
1963
}
 
1964
 
 
1965
void tst_QSslSocket::ignoreSslErrorsListWithSlot_data()
 
1966
{
 
1967
    ignoreSslErrorsList_data();
 
1968
}
 
1969
 
 
1970
// this is not a test, just a slot called in the test below
 
1971
void tst_QSslSocket::ignoreErrorListSlot(const QList<QSslError> &)
 
1972
{
 
1973
    socket->ignoreSslErrors(storedExpectedSslErrors);
 
1974
}
 
1975
 
 
1976
void tst_QSslSocket::ignoreSslErrorsListWithSlot()
 
1977
{
 
1978
    QSslSocket socket;
 
1979
    this->socket = &socket;
 
1980
 
 
1981
    QFETCH(QList<QSslError>, expectedSslErrors);
 
1982
    // store the errors to ignore them later in the slot connected below
 
1983
    storedExpectedSslErrors = expectedSslErrors;
 
1984
    connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
 
1985
            this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
 
1986
    connect(&socket, SIGNAL(sslErrors(QList<QSslError>)),
 
1987
            this, SLOT(ignoreErrorListSlot(QList<QSslError>)));
 
1988
    socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
1989
 
 
1990
    QFETCH(int, expectedSslErrorSignalCount);
 
1991
    bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
 
1992
    QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess);
 
1993
}
 
1994
 
 
1995
// make sure a closed socket has no bytesAvailable()
 
1996
// related to https://bugs.webkit.org/show_bug.cgi?id=28016
 
1997
void tst_QSslSocket::readFromClosedSocket()
 
1998
{
 
1999
    QSslSocketPtr socket = newSocket();
 
2000
    socket->ignoreSslErrors();
 
2001
    socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
2002
    socket->ignoreSslErrors();
 
2003
    socket->waitForConnected();
 
2004
    socket->waitForEncrypted();
 
2005
    // provoke a response by sending a request
 
2006
    socket->write("GET /qtest/fluke.gif HTTP/1.1\n");
 
2007
    socket->write("Host: ");
 
2008
    socket->write(QtNetworkSettings::serverName().toLocal8Bit().constData());
 
2009
    socket->write("\n");
 
2010
    socket->write("\n");
 
2011
    socket->waitForBytesWritten();
 
2012
    socket->waitForReadyRead();
 
2013
    QVERIFY(socket->state() == QAbstractSocket::ConnectedState);
 
2014
    QVERIFY(socket->bytesAvailable());
 
2015
    socket->close();
 
2016
    QVERIFY(!socket->bytesAvailable());
 
2017
    QVERIFY(!socket->bytesToWrite());
 
2018
    QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
 
2019
}
 
2020
 
 
2021
void tst_QSslSocket::writeBigChunk()
 
2022
{
 
2023
    if (!QSslSocket::supportsSsl())
 
2024
        return;
 
2025
 
 
2026
    QSslSocketPtr socket = newSocket();
 
2027
    this->socket = socket.data();
 
2028
 
 
2029
    connect(this->socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
 
2030
    socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
2031
 
 
2032
    QByteArray data;
 
2033
    data.resize(1024*1024*10); // 10 MB
 
2034
    // init with garbage. needed so ssl cannot compress it in an efficient way.
 
2035
    for (size_t i = 0; i < data.size() / sizeof(int); i++) {
 
2036
        int r = qrand();
 
2037
        data.data()[i*sizeof(int)] = r;
 
2038
    }
 
2039
 
 
2040
    QVERIFY(socket->waitForEncrypted(10000));
 
2041
    QString errorBefore = socket->errorString();
 
2042
 
 
2043
    int ret = socket->write(data.constData(), data.size());
 
2044
    QVERIFY(data.size() == ret);
 
2045
 
 
2046
    // spin the event loop once so QSslSocket::transmit() gets called
 
2047
    QCoreApplication::processEvents();
 
2048
    QString errorAfter = socket->errorString();
 
2049
 
 
2050
    // no better way to do this right now since the error is the same as the default error.
 
2051
    if (socket->errorString().startsWith(QLatin1String("Unable to write data")))
 
2052
    {
 
2053
        qWarning() << socket->error() << socket->errorString();
 
2054
        QFAIL("Error while writing! Check if the OpenSSL BIO size is limited?!");
 
2055
    }
 
2056
    // also check the error string. If another error (than UnknownError) occurred, it should be different than before
 
2057
    QVERIFY(errorBefore == errorAfter);
 
2058
 
 
2059
    // check that everything has been written to OpenSSL
 
2060
    QVERIFY(socket->bytesToWrite() == 0);
 
2061
 
 
2062
    socket->close();
 
2063
}
 
2064
 
 
2065
void tst_QSslSocket::blacklistedCertificates()
 
2066
{
 
2067
    QFETCH_GLOBAL(bool, setProxy);
 
2068
    if (setProxy)
 
2069
        return;
 
2070
 
 
2071
    SslServer server(SRCDIR "certs/fake-login.live.com.key", SRCDIR "certs/fake-login.live.com.pem");
 
2072
    QSslSocket *receiver = new QSslSocket(this);
 
2073
    connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop()));
 
2074
 
 
2075
    // connect two sockets to each other:
 
2076
    QVERIFY(server.listen(QHostAddress::LocalHost));
 
2077
    receiver->connectToHost("127.0.0.1", server.serverPort());
 
2078
    QVERIFY(receiver->waitForConnected(5000));
 
2079
    QVERIFY(server.waitForNewConnection(0));
 
2080
 
 
2081
    QSslSocket *sender = server.socket;
 
2082
    QVERIFY(sender);
 
2083
    QVERIFY(sender->state() == QAbstractSocket::ConnectedState);
 
2084
    receiver->setObjectName("receiver");
 
2085
    sender->setObjectName("sender");
 
2086
    receiver->startClientEncryption();
 
2087
 
 
2088
    connect(receiver, SIGNAL(sslErrors(QList<QSslError>)), SLOT(exitLoop()));
 
2089
    connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop()));
 
2090
    enterLoop(1);
 
2091
    QList<QSslError> sslErrors = receiver->sslErrors();
 
2092
    QVERIFY(sslErrors.count() > 0);
 
2093
    // there are more errors (self signed cert and hostname mismatch), but we only care about the blacklist error
 
2094
    QCOMPARE(sslErrors.at(0).error(), QSslError::CertificateBlacklisted);
 
2095
}
 
2096
 
 
2097
void tst_QSslSocket::versionAccessors()
 
2098
{
 
2099
    if (!QSslSocket::supportsSsl())
 
2100
        return;
 
2101
 
 
2102
    qDebug() << QSslSocket::sslLibraryVersionString();
 
2103
    qDebug() << QString::number(QSslSocket::sslLibraryVersionNumber(), 16);
 
2104
}
 
2105
 
 
2106
void tst_QSslSocket::sslOptions()
 
2107
{
 
2108
    if (!QSslSocket::supportsSsl())
 
2109
        return;
 
2110
 
 
2111
#ifdef SSL_OP_NO_COMPRESSION
 
2112
    QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols,
 
2113
                                                           QSslConfigurationPrivate::defaultSslOptions),
 
2114
             long(SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_COMPRESSION));
 
2115
#else
 
2116
    QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols,
 
2117
                                                           QSslConfigurationPrivate::defaultSslOptions),
 
2118
             long(SSL_OP_ALL|SSL_OP_NO_SSLv2));
 
2119
#endif
 
2120
 
 
2121
    QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols,
 
2122
                                                           QSsl::SslOptionDisableEmptyFragments
 
2123
                                                           |QSsl::SslOptionDisableLegacyRenegotiation),
 
2124
             long(SSL_OP_ALL|SSL_OP_NO_SSLv2));
 
2125
 
 
2126
#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
 
2127
    QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols,
 
2128
                                                           QSsl::SslOptionDisableEmptyFragments),
 
2129
             long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)));
 
2130
#endif
 
2131
 
 
2132
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
 
2133
    QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols,
 
2134
                                                           QSsl::SslOptionDisableLegacyRenegotiation),
 
2135
             long((SSL_OP_ALL|SSL_OP_NO_SSLv2) & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS));
 
2136
#endif
 
2137
 
 
2138
#ifdef SSL_OP_NO_TICKET
 
2139
    QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols,
 
2140
                                                           QSsl::SslOptionDisableEmptyFragments
 
2141
                                                           |QSsl::SslOptionDisableLegacyRenegotiation
 
2142
                                                           |QSsl::SslOptionDisableSessionTickets),
 
2143
             long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET)));
 
2144
#endif
 
2145
 
 
2146
#ifdef SSL_OP_NO_TICKET
 
2147
#ifdef SSL_OP_NO_COMPRESSION
 
2148
    QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols,
 
2149
                                                           QSsl::SslOptionDisableEmptyFragments
 
2150
                                                           |QSsl::SslOptionDisableLegacyRenegotiation
 
2151
                                                           |QSsl::SslOptionDisableSessionTickets
 
2152
                                                           |QSsl::SslOptionDisableCompression),
 
2153
             long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET|SSL_OP_NO_COMPRESSION)));
 
2154
#endif
 
2155
#endif
 
2156
}
 
2157
 
 
2158
void tst_QSslSocket::encryptWithoutConnecting()
 
2159
{
 
2160
    if (!QSslSocket::supportsSsl())
 
2161
        return;
 
2162
 
 
2163
    QTest::ignoreMessage(QtWarningMsg,
 
2164
                         "QSslSocket::startClientEncryption: cannot start handshake when not connected");
 
2165
 
 
2166
    QSslSocket sock;
 
2167
    sock.startClientEncryption();
 
2168
}
 
2169
 
 
2170
void tst_QSslSocket::resume_data()
 
2171
{
 
2172
    QTest::addColumn<bool>("ignoreErrorsAfterPause");
 
2173
    QTest::addColumn<QList<QSslError> >("errorsToIgnore");
 
2174
    QTest::addColumn<bool>("expectSuccess");
 
2175
 
 
2176
    QList<QSslError> errorsList;
 
2177
    QTest::newRow("DoNotIgnoreErrors") << false << QList<QSslError>() << false;
 
2178
    QTest::newRow("ignoreAllErrors") << true << QList<QSslError>() << true;
 
2179
 
 
2180
    QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
 
2181
    QSslError rightError(QSslError::SelfSignedCertificate, certs.at(0));
 
2182
    QSslError wrongError(QSslError::SelfSignedCertificate);
 
2183
    errorsList.append(wrongError);
 
2184
    QTest::newRow("ignoreSpecificErrors-Wrong") << true << errorsList << false;
 
2185
    errorsList.clear();
 
2186
    errorsList.append(rightError);
 
2187
    QTest::newRow("ignoreSpecificErrors-Right") << true << errorsList << true;
 
2188
}
 
2189
 
 
2190
void tst_QSslSocket::resume()
 
2191
{
 
2192
    // make sure the server certificate is not in the list of accepted certificates,
 
2193
    // we want to trigger the sslErrors signal
 
2194
    QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
 
2195
 
 
2196
    QFETCH(bool, ignoreErrorsAfterPause);
 
2197
    QFETCH(QList<QSslError>, errorsToIgnore);
 
2198
    QFETCH(bool, expectSuccess);
 
2199
 
 
2200
    QSslSocket socket;
 
2201
    socket.setPauseMode(QAbstractSocket::PauseOnSslErrors);
 
2202
 
 
2203
    QSignalSpy sslErrorSpy(&socket, SIGNAL(sslErrors(QList<QSslError>)));
 
2204
    QSignalSpy encryptedSpy(&socket, SIGNAL(encrypted()));
 
2205
    QSignalSpy errorSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
 
2206
 
 
2207
    connect(&socket, SIGNAL(sslErrors(QList<QSslError>)), &QTestEventLoop::instance(), SLOT(exitLoop()));
 
2208
    connect(&socket, SIGNAL(encrypted()), &QTestEventLoop::instance(), SLOT(exitLoop()));
 
2209
    connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
 
2210
            this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
 
2211
    connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), &QTestEventLoop::instance(), SLOT(exitLoop()));
 
2212
 
 
2213
    socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
 
2214
    QTestEventLoop::instance().enterLoop(10);
 
2215
    QVERIFY(!QTestEventLoop::instance().timeout());
 
2216
    QCOMPARE(sslErrorSpy.count(), 1);
 
2217
    QCOMPARE(errorSpy.count(), 0);
 
2218
    QCOMPARE(encryptedSpy.count(), 0);
 
2219
    QVERIFY(!socket.isEncrypted());
 
2220
    if (ignoreErrorsAfterPause) {
 
2221
        if (errorsToIgnore.empty())
 
2222
            socket.ignoreSslErrors();
 
2223
        else
 
2224
            socket.ignoreSslErrors(errorsToIgnore);
 
2225
    }
 
2226
    socket.resume();
 
2227
    QTestEventLoop::instance().enterLoop(10);
 
2228
    QVERIFY(!QTestEventLoop::instance().timeout()); // quit by encrypted() or error() signal
 
2229
    if (expectSuccess) {
 
2230
        QCOMPARE(encryptedSpy.count(), 1);
 
2231
        QVERIFY(socket.isEncrypted());
 
2232
        QCOMPARE(errorSpy.count(), 0);
 
2233
        socket.disconnectFromHost();
 
2234
        QVERIFY(socket.waitForDisconnected(10000));
 
2235
    } else {
 
2236
        QCOMPARE(encryptedSpy.count(), 0);
 
2237
        QVERIFY(!socket.isEncrypted());
 
2238
        QCOMPARE(errorSpy.count(), 1);
 
2239
        QCOMPARE(socket.error(), QAbstractSocket::SslHandshakeFailedError);
 
2240
    }
 
2241
}
 
2242
 
 
2243
class WebSocket : public QSslSocket
 
2244
{
 
2245
    Q_OBJECT
 
2246
public:
 
2247
    explicit WebSocket(qintptr socketDescriptor,
 
2248
                       const QString &keyFile = SRCDIR "certs/fluke.key",
 
2249
                       const QString &certFile = SRCDIR "certs/fluke.cert");
 
2250
 
 
2251
protected slots:
 
2252
    void onReadyReadFirstBytes(void);
 
2253
 
 
2254
private:
 
2255
    void _startServerEncryption(void);
 
2256
 
 
2257
    QString m_keyFile;
 
2258
    QString m_certFile;
 
2259
 
 
2260
private:
 
2261
    Q_DISABLE_COPY(WebSocket)
 
2262
};
 
2263
 
 
2264
WebSocket::WebSocket (qintptr socketDescriptor, const QString &keyFile, const QString &certFile)
 
2265
    : m_keyFile(keyFile),
 
2266
      m_certFile(certFile)
 
2267
{
 
2268
    QVERIFY(setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState, QIODevice::ReadWrite | QIODevice::Unbuffered));
 
2269
    connect (this, SIGNAL(readyRead()), this, SLOT(onReadyReadFirstBytes()));
 
2270
}
 
2271
 
 
2272
void WebSocket::_startServerEncryption (void)
 
2273
{
 
2274
    QFile file(m_keyFile);
 
2275
    QVERIFY(file.open(QIODevice::ReadOnly));
 
2276
    QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
 
2277
    QVERIFY(!key.isNull());
 
2278
    setPrivateKey(key);
 
2279
 
 
2280
    QList<QSslCertificate> localCert = QSslCertificate::fromPath(m_certFile);
 
2281
    QVERIFY(!localCert.isEmpty());
 
2282
    QVERIFY(localCert.first().handle());
 
2283
    setLocalCertificate(localCert.first());
 
2284
 
 
2285
    QVERIFY(!peerAddress().isNull());
 
2286
    QVERIFY(peerPort() != 0);
 
2287
    QVERIFY(!localAddress().isNull());
 
2288
    QVERIFY(localPort() != 0);
 
2289
 
 
2290
    setProtocol(QSsl::AnyProtocol);
 
2291
    setPeerVerifyMode(QSslSocket::VerifyNone);
 
2292
    ignoreSslErrors();
 
2293
    startServerEncryption();
 
2294
}
 
2295
 
 
2296
void WebSocket::onReadyReadFirstBytes (void)
 
2297
{
 
2298
    peek(1);
 
2299
    disconnect(this,SIGNAL(readyRead()), this, SLOT(onReadyReadFirstBytes()));
 
2300
    _startServerEncryption();
 
2301
}
 
2302
 
 
2303
class SslServer4 : public QTcpServer
 
2304
{
 
2305
    Q_OBJECT
 
2306
public:
 
2307
    SslServer4() : socket(0) {}
 
2308
    WebSocket *socket;
 
2309
 
 
2310
protected:
 
2311
    void incomingConnection(qintptr socketDescriptor)
 
2312
    {
 
2313
        socket =  new WebSocket(socketDescriptor);
 
2314
    }
 
2315
};
 
2316
 
 
2317
void tst_QSslSocket::qtbug18498_peek()
 
2318
{
 
2319
    QFETCH_GLOBAL(bool, setProxy);
 
2320
    if (setProxy)
 
2321
        return;
 
2322
 
 
2323
    SslServer4 server;
 
2324
    QSslSocket *client = new QSslSocket(this);
 
2325
 
 
2326
    QVERIFY(server.listen(QHostAddress::LocalHost));
 
2327
    client->connectToHost("127.0.0.1", server.serverPort());
 
2328
    QVERIFY(client->waitForConnected(5000));
 
2329
    QVERIFY(server.waitForNewConnection(1000));
 
2330
    client->setObjectName("client");
 
2331
    client->ignoreSslErrors();
 
2332
 
 
2333
    connect(client, SIGNAL(encrypted()), this, SLOT(exitLoop()));
 
2334
    connect(client, SIGNAL(disconnected()), this, SLOT(exitLoop()));
 
2335
 
 
2336
    client->startClientEncryption();
 
2337
    WebSocket *serversocket = server.socket;
 
2338
    QVERIFY(serversocket);
 
2339
    serversocket->setObjectName("server");
 
2340
 
 
2341
    enterLoop(1);
 
2342
    QVERIFY(!timeout());
 
2343
    QVERIFY(serversocket->isEncrypted());
 
2344
    QVERIFY(client->isEncrypted());
 
2345
 
 
2346
    QByteArray data("abc123");
 
2347
    client->write(data.data());
 
2348
 
 
2349
    connect(serversocket, SIGNAL(readyRead()), this, SLOT(exitLoop()));
 
2350
    enterLoop(1);
 
2351
    QVERIFY(!timeout());
 
2352
 
 
2353
    QByteArray peek1_data;
 
2354
    peek1_data.reserve(data.size());
 
2355
    QByteArray peek2_data;
 
2356
    QByteArray read_data;
 
2357
 
 
2358
    int lngth = serversocket->peek(peek1_data.data(), 10);
 
2359
    peek1_data.resize(lngth);
 
2360
 
 
2361
    peek2_data = serversocket->peek(10);
 
2362
    read_data = serversocket->readAll();
 
2363
 
 
2364
    QCOMPARE(peek1_data, data);
 
2365
    QCOMPARE(peek2_data, data);
 
2366
    QCOMPARE(read_data, data);
 
2367
}
 
2368
 
 
2369
class SslServer5 : public QTcpServer
 
2370
{
 
2371
    Q_OBJECT
 
2372
public:
 
2373
    SslServer5() : socket(0) {}
 
2374
    QSslSocket *socket;
 
2375
 
 
2376
protected:
 
2377
    void incomingConnection(qintptr socketDescriptor)
 
2378
    {
 
2379
        socket =  new QSslSocket;
 
2380
        socket->setSocketDescriptor(socketDescriptor);
 
2381
    }
 
2382
};
 
2383
 
 
2384
void tst_QSslSocket::qtbug18498_peek2()
 
2385
{
 
2386
    QFETCH_GLOBAL(bool, setProxy);
 
2387
    if (setProxy)
 
2388
        return;
 
2389
 
 
2390
    SslServer5 listener;
 
2391
    QVERIFY(listener.listen(QHostAddress::Any));
 
2392
    QScopedPointer<QSslSocket> client(new QSslSocket);
 
2393
    client->connectToHost(QHostAddress::LocalHost, listener.serverPort());
 
2394
    QVERIFY(client->waitForConnected(5000));
 
2395
    QVERIFY(listener.waitForNewConnection(1000));
 
2396
 
 
2397
    QScopedPointer<QSslSocket> server(listener.socket);
 
2398
 
 
2399
    QVERIFY(server->write("HELLO\r\n", 7));
 
2400
    QElapsedTimer stopwatch;
 
2401
    stopwatch.start();
 
2402
    while (client->bytesAvailable() < 7 && stopwatch.elapsed() < 5000)
 
2403
        QTest::qWait(100);
 
2404
    char c;
 
2405
    QVERIFY(client->peek(&c,1) == 1);
 
2406
    QCOMPARE(c, 'H');
 
2407
    QVERIFY(client->read(&c,1) == 1);
 
2408
    QCOMPARE(c, 'H');
 
2409
    QByteArray b = client->peek(2);
 
2410
    QCOMPARE(b, QByteArray("EL"));
 
2411
    char a[3];
 
2412
    QVERIFY(client->peek(a, 2) == 2);
 
2413
    QCOMPARE(a[0], 'E');
 
2414
    QCOMPARE(a[1], 'L');
 
2415
    QCOMPARE(client->readAll(), QByteArray("ELLO\r\n"));
 
2416
 
 
2417
    //check data split between QIODevice and plain socket buffers.
 
2418
    QByteArray bigblock;
 
2419
    bigblock.fill('#', QIODEVICE_BUFFERSIZE + 1024);
 
2420
    QVERIFY(client->write(QByteArray("head")));
 
2421
    QVERIFY(client->write(bigblock));
 
2422
    while (server->bytesAvailable() < bigblock.length() + 4 && stopwatch.elapsed() < 5000)
 
2423
        QTest::qWait(100);
 
2424
    QCOMPARE(server->read(4), QByteArray("head"));
 
2425
    QCOMPARE(server->peek(bigblock.length()), bigblock);
 
2426
    b.reserve(bigblock.length());
 
2427
    b.resize(server->peek(b.data(), bigblock.length()));
 
2428
    QCOMPARE(b, bigblock);
 
2429
 
 
2430
    //check oversized peek
 
2431
    QCOMPARE(server->peek(bigblock.length() * 3), bigblock);
 
2432
    b.reserve(bigblock.length() * 3);
 
2433
    b.resize(server->peek(b.data(), bigblock.length() * 3));
 
2434
    QCOMPARE(b, bigblock);
 
2435
 
 
2436
    QCOMPARE(server->readAll(), bigblock);
 
2437
 
 
2438
    QVERIFY(client->write("STARTTLS\r\n"));
 
2439
    stopwatch.start();
 
2440
    // ### Qt5 use QTRY_VERIFY
 
2441
    while (server->bytesAvailable() < 10 && stopwatch.elapsed() < 5000)
 
2442
        QTest::qWait(100);
 
2443
    QVERIFY(server->peek(&c,1) == 1);
 
2444
    QCOMPARE(c, 'S');
 
2445
    b = server->peek(3);
 
2446
    QCOMPARE(b, QByteArray("STA"));
 
2447
    QCOMPARE(server->read(5), QByteArray("START"));
 
2448
    QVERIFY(server->peek(a, 3) == 3);
 
2449
    QCOMPARE(a[0], 'T');
 
2450
    QCOMPARE(a[1], 'L');
 
2451
    QCOMPARE(a[2], 'S');
 
2452
    QCOMPARE(server->readAll(), QByteArray("TLS\r\n"));
 
2453
 
 
2454
    QFile file(SRCDIR "certs/fluke.key");
 
2455
    QVERIFY(file.open(QIODevice::ReadOnly));
 
2456
    QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
 
2457
    QVERIFY(!key.isNull());
 
2458
    server->setPrivateKey(key);
 
2459
 
 
2460
    QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert");
 
2461
    QVERIFY(!localCert.isEmpty());
 
2462
    QVERIFY(localCert.first().handle());
 
2463
    server->setLocalCertificate(localCert.first());
 
2464
 
 
2465
    server->setProtocol(QSsl::AnyProtocol);
 
2466
    server->setPeerVerifyMode(QSslSocket::VerifyNone);
 
2467
 
 
2468
    server->ignoreSslErrors();
 
2469
    client->ignoreSslErrors();
 
2470
 
 
2471
    server->startServerEncryption();
 
2472
    client->startClientEncryption();
 
2473
 
 
2474
    QVERIFY(server->write("hello\r\n", 7));
 
2475
    stopwatch.start();
 
2476
    while (client->bytesAvailable() < 7 && stopwatch.elapsed() < 5000)
 
2477
        QTest::qWait(100);
 
2478
    QVERIFY(server->mode() == QSslSocket::SslServerMode && client->mode() == QSslSocket::SslClientMode);
 
2479
    QVERIFY(client->peek(&c,1) == 1);
 
2480
    QCOMPARE(c, 'h');
 
2481
    QVERIFY(client->read(&c,1) == 1);
 
2482
    QCOMPARE(c, 'h');
 
2483
    b = client->peek(2);
 
2484
    QCOMPARE(b, QByteArray("el"));
 
2485
    QCOMPARE(client->readAll(), QByteArray("ello\r\n"));
 
2486
 
 
2487
    QVERIFY(client->write("goodbye\r\n"));
 
2488
    stopwatch.start();
 
2489
    while (server->bytesAvailable() < 9 && stopwatch.elapsed() < 5000)
 
2490
        QTest::qWait(100);
 
2491
    QVERIFY(server->peek(&c,1) == 1);
 
2492
    QCOMPARE(c, 'g');
 
2493
    QCOMPARE(server->readAll(), QByteArray("goodbye\r\n"));
 
2494
    client->disconnectFromHost();
 
2495
    QVERIFY(client->waitForDisconnected(5000));
 
2496
}
 
2497
 
 
2498
void tst_QSslSocket::setEmptyDefaultConfiguration() // this test should be last, as it has some side effects
 
2499
{
 
2500
    // used to produce a crash in QSslConfigurationPrivate::deepCopyDefaultConfiguration, QTBUG-13265
 
2501
 
 
2502
    if (!QSslSocket::supportsSsl())
 
2503
        return;
 
2504
 
 
2505
    QSslConfiguration emptyConf;
 
2506
    QSslConfiguration::setDefaultConfiguration(emptyConf);
 
2507
 
 
2508
    QSslSocketPtr socket = newSocket();
 
2509
    connect(socket.data(), SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
 
2510
    socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
 
2511
    QVERIFY2(!socket->waitForEncrypted(4000), qPrintable(socket->errorString()));
 
2512
}
 
2513
 
 
2514
#endif // QT_NO_SSL
 
2515
 
 
2516
QTEST_MAIN(tst_QSslSocket)
 
2517
 
 
2518
#include "tst_qsslsocket.moc"