diff options
Diffstat (limited to 'tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp')
-rw-r--r-- | tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp | 236 |
1 files changed, 163 insertions, 73 deletions
diff --git a/tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp b/tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp index b13114cb47..26d3a50a5b 100644 --- a/tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp +++ b/tests/auto/network/ssl/qsslserver/tst_qsslserver.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QDebug> @@ -23,6 +23,9 @@ private slots: void testHandshakeInterruptedOnError(); void testPreSharedKeyAuthenticationRequired(); #endif + void plaintextClient(); + void quietClient(); + void twoGoodAndManyBadClients(); private: QString testDataDir; @@ -139,15 +142,15 @@ void tst_QSslServer::testOneSuccessfulConnection() QVERIFY(server.startedEncryptionHandshakeSpy.isValid()); // Check that no connections has occurred - QCOMPARE(server.sslErrorsSpy.count(), 0); - QCOMPARE(server.peerVerifyErrorSpy.count(), 0); - QCOMPARE(server.errorOccurredSpy.count(), 0); - QCOMPARE(server.pendingConnectionAvailableSpy.count(), 0); - QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 0); - QCOMPARE(server.alertSentSpy.count(), 0); - QCOMPARE(server.alertReceivedSpy.count(), 0); - QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 0); - QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 0); + QCOMPARE(server.sslErrorsSpy.size(), 0); + QCOMPARE(server.peerVerifyErrorSpy.size(), 0); + QCOMPARE(server.errorOccurredSpy.size(), 0); + QCOMPARE(server.pendingConnectionAvailableSpy.size(), 0); + QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 0); + QCOMPARE(server.alertSentSpy.size(), 0); + QCOMPARE(server.alertReceivedSpy.size(), 0); + QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 0); + QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 0); // Connect client QSslSocket client; @@ -184,15 +187,15 @@ void tst_QSslServer::testOneSuccessfulConnection() loop.exec(); // Check that one encrypted connection has occurred without error - QCOMPARE(server.sslErrorsSpy.count(), 0); - QCOMPARE(server.peerVerifyErrorSpy.count(), 0); - QCOMPARE(server.errorOccurredSpy.count(), 0); - QCOMPARE(server.pendingConnectionAvailableSpy.count(), 1); - QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 0); - QCOMPARE(server.alertSentSpy.count(), 0); - QCOMPARE(server.alertReceivedSpy.count(), 0); - QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 0); - QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 1); + QCOMPARE(server.sslErrorsSpy.size(), 0); + QCOMPARE(server.peerVerifyErrorSpy.size(), 0); + QCOMPARE(server.errorOccurredSpy.size(), 0); + QCOMPARE(server.pendingConnectionAvailableSpy.size(), 1); + QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 0); + QCOMPARE(server.alertSentSpy.size(), 0); + QCOMPARE(server.alertReceivedSpy.size(), 0); + QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 0); + QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 1); // Check client socket QVERIFY(client.isEncrypted()); @@ -221,16 +224,16 @@ void tst_QSslServer::testSelfSignedCertificateRejectedByServer() loop.exec(); // Check that one encrypted connection has failed - QCOMPARE(server.sslErrorsSpy.count(), 1); - QCOMPARE(server.peerVerifyErrorSpy.count(), 1); - QCOMPARE(server.errorOccurredSpy.count(), 1); - QCOMPARE(server.pendingConnectionAvailableSpy.count(), 0); - QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 0); - QCOMPARE(server.alertSentSpy.count(), + QCOMPARE(server.sslErrorsSpy.size(), 1); + QCOMPARE(server.peerVerifyErrorSpy.size(), 1); + QCOMPARE(server.errorOccurredSpy.size(), 1); + QCOMPARE(server.pendingConnectionAvailableSpy.size(), 0); + QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 0); + QCOMPARE(server.alertSentSpy.size(), isTestingOpenSsl ? 1 : 0); // OpenSSL only signal - QCOMPARE(server.alertReceivedSpy.count(), 0); - QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 0); - QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 1); + QCOMPARE(server.alertReceivedSpy.size(), 0); + QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 0); + QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 1); // Type of certificate error to expect const auto certificateError = @@ -238,13 +241,13 @@ void tst_QSslServer::testSelfSignedCertificateRejectedByServer() // Check the sslErrorsSpy const auto sslErrorsSpyErrors = - qvariant_cast<QList<QSslError>>(qAsConst(server.sslErrorsSpy).first()[1]); + qvariant_cast<QList<QSslError>>(std::as_const(server.sslErrorsSpy).first()[1]); QCOMPARE(sslErrorsSpyErrors.size(), 1); QCOMPARE(sslErrorsSpyErrors.first().error(), certificateError); // Check the peerVerifyErrorSpy const auto peerVerifyErrorSpyError = - qvariant_cast<QSslError>(qAsConst(server.peerVerifyErrorSpy).first()[1]); + qvariant_cast<QSslError>(std::as_const(server.peerVerifyErrorSpy).first()[1]); QCOMPARE(peerVerifyErrorSpyError.error(), certificateError); // Check client socket @@ -287,32 +290,32 @@ void tst_QSslServer::testSelfSignedCertificateRejectedByClient() QTcpSocket *connection = server.server.nextPendingConnection(); if (connection == nullptr) { // Client disconnected before connection accepted by server - QCOMPARE(server.sslErrorsSpy.count(), 0); - QCOMPARE(server.peerVerifyErrorSpy.count(), 0); - QCOMPARE(server.errorOccurredSpy.count(), 1); // Client rejected first - QCOMPARE(server.pendingConnectionAvailableSpy.count(), 0); - QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 0); - QCOMPARE(server.alertSentSpy.count(), 0); - QCOMPARE(server.alertReceivedSpy.count(), + QCOMPARE(server.sslErrorsSpy.size(), 0); + QCOMPARE(server.peerVerifyErrorSpy.size(), 0); + QCOMPARE(server.errorOccurredSpy.size(), 1); // Client rejected first + QCOMPARE(server.pendingConnectionAvailableSpy.size(), 0); + QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 0); + QCOMPARE(server.alertSentSpy.size(), 0); + QCOMPARE(server.alertReceivedSpy.size(), isTestingOpenSsl ? 1 : 0); // OpenSSL only signal - QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 0); - QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 1); + QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 0); + QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 1); const auto errrOccuredSpyError = qvariant_cast<QAbstractSocket::SocketError>( - qAsConst(server.errorOccurredSpy).first()[1]); + std::as_const(server.errorOccurredSpy).first()[1]); QCOMPARE(errrOccuredSpyError, socketError); } else { // Client disconnected after connection accepted by server - QCOMPARE(server.sslErrorsSpy.count(), 0); - QCOMPARE(server.peerVerifyErrorSpy.count(), 0); - QCOMPARE(server.errorOccurredSpy.count(), 0); // Server accepted first - QCOMPARE(server.pendingConnectionAvailableSpy.count(), 1); - QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 0); - QCOMPARE(server.alertSentSpy.count(), 0); - QCOMPARE(server.alertReceivedSpy.count(), + QCOMPARE(server.sslErrorsSpy.size(), 0); + QCOMPARE(server.peerVerifyErrorSpy.size(), 0); + QCOMPARE(server.errorOccurredSpy.size(), 0); // Server accepted first + QCOMPARE(server.pendingConnectionAvailableSpy.size(), 1); + QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 0); + QCOMPARE(server.alertSentSpy.size(), 0); + QCOMPARE(server.alertReceivedSpy.size(), isTestingOpenSsl ? 1 : 0); // OpenSSL only signal - QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 0); - QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 1); + QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 0); + QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 1); QCOMPARE(connection->state(), QAbstractSocket::UnconnectedState); QCOMPARE(connection->error(), socketError); @@ -322,12 +325,12 @@ void tst_QSslServer::testSelfSignedCertificateRejectedByClient() } // Check that client has rejected server - QCOMPARE(clientConnectedSpy.count(), 1); - QCOMPARE(clientHostFoundSpy.count(), 1); - QCOMPARE(clientDisconnectedSpy.count(), 1); - QCOMPARE(clientConnectionEncryptedSpy.count(), 0); - QCOMPARE(clientSslErrorsSpy.count(), isTestingOpenSsl ? 0 : 1); - QCOMPARE(clientErrorOccurredSpy.count(), 1); + QCOMPARE(clientConnectedSpy.size(), 1); + QCOMPARE(clientHostFoundSpy.size(), 1); + QCOMPARE(clientDisconnectedSpy.size(), 1); + QCOMPARE(clientConnectionEncryptedSpy.size(), 0); + QCOMPARE(clientSslErrorsSpy.size(), isTestingOpenSsl ? 0 : 1); + QCOMPARE(clientErrorOccurredSpy.size(), 1); // Check client socket QVERIFY(!client.isEncrypted()); @@ -361,15 +364,15 @@ void tst_QSslServer::testHandshakeInterruptedOnError() loop.exec(); // Check that client certificate causes handshake interrupted signal to be emitted - QCOMPARE(server.sslErrorsSpy.count(), 0); - QCOMPARE(server.peerVerifyErrorSpy.count(), 0); - QCOMPARE(server.errorOccurredSpy.count(), 1); - QCOMPARE(server.pendingConnectionAvailableSpy.count(), 0); - QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 0); - QCOMPARE(server.alertSentSpy.count(), 1); - QCOMPARE(server.alertReceivedSpy.count(), 0); - QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 1); - QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 1); + QCOMPARE(server.sslErrorsSpy.size(), 0); + QCOMPARE(server.peerVerifyErrorSpy.size(), 0); + QCOMPARE(server.errorOccurredSpy.size(), 1); + QCOMPARE(server.pendingConnectionAvailableSpy.size(), 0); + QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 0); + QCOMPARE(server.alertSentSpy.size(), 1); + QCOMPARE(server.alertReceivedSpy.size(), 0); + QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 1); + QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 1); } void tst_QSslServer::testPreSharedKeyAuthenticationRequired() @@ -419,15 +422,15 @@ void tst_QSslServer::testPreSharedKeyAuthenticationRequired() loop.exec(); // Check that server is connected - QCOMPARE(server.sslErrorsSpy.count(), 1); - QCOMPARE(server.peerVerifyErrorSpy.count(), 1); - QCOMPARE(server.errorOccurredSpy.count(), 0); - QCOMPARE(server.pendingConnectionAvailableSpy.count(), 1); - QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.count(), 1); - QCOMPARE(server.alertSentSpy.count(), 0); - QCOMPARE(server.alertReceivedSpy.count(), 0); - QCOMPARE(server.handshakeInterruptedOnErrorSpy.count(), 0); - QCOMPARE(server.startedEncryptionHandshakeSpy.count(), 1); + QCOMPARE(server.sslErrorsSpy.size(), 1); + QCOMPARE(server.peerVerifyErrorSpy.size(), 1); + QCOMPARE(server.errorOccurredSpy.size(), 0); + QCOMPARE(server.pendingConnectionAvailableSpy.size(), 1); + QCOMPARE(server.preSharedKeyAuthenticationRequiredSpy.size(), 1); + QCOMPARE(server.alertSentSpy.size(), 0); + QCOMPARE(server.alertReceivedSpy.size(), 0); + QCOMPARE(server.handshakeInterruptedOnErrorSpy.size(), 0); + QCOMPARE(server.startedEncryptionHandshakeSpy.size(), 1); // Check client socket QVERIFY(client.isEncrypted()); @@ -436,6 +439,93 @@ void tst_QSslServer::testPreSharedKeyAuthenticationRequired() #endif +void tst_QSslServer::plaintextClient() +{ + QSslConfiguration serverConfiguration = selfSignedServerQSslConfiguration(); + SslServerSpy server(serverConfiguration); + QVERIFY(server.server.listen()); + + QTcpSocket socket; + QSignalSpy socketDisconnectedSpy(&socket, &QTcpSocket::disconnected); + socket.connectToHost(QHostAddress::LocalHost, server.server.serverPort()); + QVERIFY(socket.waitForConnected()); + QTest::qWait(100); + // No disconnect from short break...: + QCOMPARE(socket.state(), QAbstractSocket::SocketState::ConnectedState); + + // ... but we write some plaintext data...: + socket.write("Hello World!"); + socket.waitForBytesWritten(); + // ... and quickly get disconnected: + QTRY_COMPARE_GT(socketDisconnectedSpy.size(), 0); + QCOMPARE(socket.state(), QAbstractSocket::SocketState::UnconnectedState); +} + +void tst_QSslServer::quietClient() +{ + QSslConfiguration serverConfiguration = selfSignedServerQSslConfiguration(); + SslServerSpy server(serverConfiguration); + server.server.setHandshakeTimeout(1'000); + QVERIFY(server.server.listen()); + + quint16 serverPeerPort = 0; + auto grabServerPeerPort = [&serverPeerPort](QSslSocket *socket) { + serverPeerPort = socket->peerPort(); + }; + QObject::connect(&server.server, &QSslServer::errorOccurred, &server.server, + grabServerPeerPort); + + QTcpSocket socket; + QSignalSpy socketDisconnectedSpy(&socket, &QTcpSocket::disconnected); + socket.connectToHost(QHostAddress::LocalHost, server.server.serverPort()); + quint16 clientLocalPort = socket.localPort(); + QVERIFY(socket.waitForConnected()); + // Disconnects after overlong break: + QVERIFY(socketDisconnectedSpy.wait(5'000)); + QCOMPARE(socket.state(), QAbstractSocket::SocketState::UnconnectedState); + + QCOMPARE_GT(server.errorOccurredSpy.size(), 0); + QCOMPARE(serverPeerPort, clientLocalPort); +} + +void tst_QSslServer::twoGoodAndManyBadClients() +{ + QSslConfiguration serverConfiguration = selfSignedServerQSslConfiguration(); + SslServerSpy server(serverConfiguration); + server.server.setHandshakeTimeout(750); + constexpr qsizetype ExpectedConnections = 5; + server.server.setMaxPendingConnections(ExpectedConnections); + QVERIFY(server.server.listen()); + + auto connectGoodClient = [&server](QSslSocket *socket) { + QObject::connect(socket, &QSslSocket::sslErrors, socket, + qOverload<const QList<QSslError> &>(&QSslSocket::ignoreSslErrors)); + socket->connectToHostEncrypted("127.0.0.1", server.server.serverPort()); + }; + // Connect one socket encrypted so we have a socket in the regular queue + QSslSocket tlsSocket; + connectGoodClient(&tlsSocket); + + // Then we connect a bunch of TCP sockets who will not send any data at all + std::array<QTcpSocket, size_t(ExpectedConnections) * 2> sockets; + for (QTcpSocket &socket : sockets) + socket.connectToHost(QHostAddress::LocalHost, server.server.serverPort()); + QTest::qWait(500); // some leeway to let connections try to connect... + + // I happen to know the sockets are all children of the server, so let's see + // how many are created: + qsizetype connectedCount = server.server.findChildren<QSslSocket *>().size(); + QCOMPARE(connectedCount, ExpectedConnections); + // 1 socket is ready and pending + QCOMPARE(server.pendingConnectionAvailableSpy.size(), 1); + + // Connect another client to make sure that the server is accepting connections again even after + // all the bad actors tried to connect: + QSslSocket goodClient; + connectGoodClient(&goodClient); + QTRY_COMPARE(server.pendingConnectionAvailableSpy.size(), 2); +} + QTEST_MAIN(tst_QSslServer) #include "tst_qsslserver.moc" |