summaryrefslogtreecommitdiffstats
path: root/tests/auto/network/ssl
diff options
context:
space:
mode:
authorTimur Pocheptsov <timur.pocheptsov@qt.io>2018-05-08 12:35:46 +0200
committerTimur Pocheptsov <timur.pocheptsov@qt.io>2018-07-12 09:16:25 +0000
commit86632bd377e9809a6670ee069b45bfb59a07d0fa (patch)
treed6a097ad8d1df19aad6153dde42a1b27af84bac5 /tests/auto/network/ssl
parente40f23f098a1e79c22df611b6312317582b95a3a (diff)
QSslSocketBackendPrivate - avoid recursion while handing errors
The logic seems to be simple - if client code on error signal tries to close TLS socket and this socket has buffered data, it calls 'flush' and 'transmit' or even 'startHandshake' as a result, which in turn will set and emit error again. To auto- test this, we initiate a handshake with pre-shared key hint on a server side and both client/server sockets incorrectly configured (missing PSK signals). We also do early write into the client socket to make sure it has some data buffered by the moment we call 'close'. Task-number: QTBUG-68089 Task-number: QTBUG-56476 Change-Id: I6ba6435bd572ad85d9209c4c81774a397081b34f Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'tests/auto/network/ssl')
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp63
1 files changed, 63 insertions, 0 deletions
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index f07d3c6507..b759aed074 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -202,6 +202,9 @@ private slots:
void verifyDepth();
void disconnectFromHostWhenConnecting();
void disconnectFromHostWhenConnected();
+#ifndef QT_NO_OPENSSL
+ void closeWhileEmittingSocketError();
+#endif
void resetProxy();
void ignoreSslErrorsList_data();
void ignoreSslErrorsList();
@@ -2336,6 +2339,66 @@ void tst_QSslSocket::disconnectFromHostWhenConnected()
QCOMPARE(socket->bytesToWrite(), qint64(0));
}
+#ifndef QT_NO_OPENSSL
+
+class BrokenPskHandshake : public QTcpServer
+{
+public:
+ void socketError(QAbstractSocket::SocketError error)
+ {
+ Q_UNUSED(error);
+ QSslSocket *clientSocket = qobject_cast<QSslSocket *>(sender());
+ Q_ASSERT(clientSocket);
+ clientSocket->close();
+ QTestEventLoop::instance().exitLoop();
+ }
+private:
+
+ void incomingConnection(qintptr handle) override
+ {
+ if (!socket.setSocketDescriptor(handle))
+ return;
+
+ QSslConfiguration serverConfig(QSslConfiguration::defaultConfiguration());
+ serverConfig.setPreSharedKeyIdentityHint("abcdefghijklmnop");
+ socket.setSslConfiguration(serverConfig);
+ socket.startServerEncryption();
+ }
+
+ QSslSocket socket;
+};
+
+void tst_QSslSocket::closeWhileEmittingSocketError()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ BrokenPskHandshake handshake;
+ if (!handshake.listen())
+ QSKIP("failed to start TLS server");
+
+ QSslSocket clientSocket;
+ QSslConfiguration clientConfig(QSslConfiguration::defaultConfiguration());
+ clientConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
+ clientSocket.setSslConfiguration(clientConfig);
+
+ QSignalSpy socketErrorSpy(&clientSocket, SIGNAL(error(QAbstractSocket::SocketError)));
+ void (QSslSocket::*errorSignal)(QAbstractSocket::SocketError) = &QSslSocket::error;
+ connect(&clientSocket, errorSignal, &handshake, &BrokenPskHandshake::socketError);
+
+ clientSocket.connectToHostEncrypted(QStringLiteral("127.0.0.1"), handshake.serverPort());
+ // Make sure we have some data buffered so that close will try to flush:
+ clientSocket.write(QByteArray(1000000, Qt::Uninitialized));
+
+ QTestEventLoop::instance().enterLoopMSecs(1000);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QCOMPARE(socketErrorSpy.count(), 1);
+}
+
+#endif // QT_NO_OPENSSL
+
void tst_QSslSocket::resetProxy()
{
#ifndef QT_NO_NETWORKPROXY