summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMårten Nordheim <marten.nordheim@qt.io>2019-09-27 16:16:52 +0200
committerMårten Nordheim <marten.nordheim@qt.io>2019-10-07 11:34:39 +0200
commit3dd8f6dc34a1357018484158a5e91c3afc71ae77 (patch)
treee5b6775858a2f4a54878f88910187af000482356
parente00d888daefbfbd5f17e0772421773f8e295087b (diff)
Schannel: no longer keep old ssl errors around when reusing socket
And add a test for it so it can no longer happen in any current or future implementation. Change-Id: I3214aa90595e291b1e1c66befe185cfe1ea7bc6b Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
-rw-r--r--src/network/ssl/qsslsocket_schannel.cpp3
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp49
2 files changed, 51 insertions, 1 deletions
diff --git a/src/network/ssl/qsslsocket_schannel.cpp b/src/network/ssl/qsslsocket_schannel.cpp
index 339ecf4da2..46c109b6e5 100644
--- a/src/network/ssl/qsslsocket_schannel.cpp
+++ b/src/network/ssl/qsslsocket_schannel.cpp
@@ -974,6 +974,7 @@ bool QSslSocketBackendPrivate::performHandshake()
bool QSslSocketBackendPrivate::verifyHandshake()
{
Q_Q(QSslSocket);
+ sslErrors.clear();
const bool isClient = mode == QSslSocket::SslClientMode;
#define CHECK_STATUS(status) \
@@ -1062,7 +1063,7 @@ bool QSslSocketBackendPrivate::verifyHandshake()
}
// verifyCertContext returns false if the user disconnected while it was checking errors.
- if (certificateContext && sslErrors.isEmpty() && !verifyCertContext(certificateContext))
+ if (certificateContext && !verifyCertContext(certificateContext))
return false;
if (!checkSslErrors() || state != QAbstractSocket::ConnectedState) {
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index 66475e55ad..79ea505d11 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -259,6 +259,8 @@ private slots:
void disabledProtocols_data();
void disabledProtocols();
+ void oldErrorsOnSocketReuse();
+
void setEmptyDefaultConfiguration(); // this test should be last
protected slots:
@@ -4192,6 +4194,53 @@ void tst_QSslSocket::disabledProtocols()
}
}
+void tst_QSslSocket::oldErrorsOnSocketReuse()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return; // not relevant
+ SslServer server;
+ server.protocol = QSsl::TlsV1_1;
+ server.m_certFile = testDataDir + "certs/fluke.cert";
+ server.m_keyFile = testDataDir + "certs/fluke.key";
+ QVERIFY(server.listen(QHostAddress::SpecialAddress::LocalHost));
+
+ QSslSocket socket;
+ socket.setProtocol(QSsl::TlsV1_1);
+ QList<QSslError> errorList;
+ auto connection = connect(&socket, QOverload<const QList<QSslError> &>::of(&QSslSocket::sslErrors),
+ [&socket, &errorList](const QList<QSslError> &errors) {
+ errorList += errors;
+ socket.ignoreSslErrors(errors);
+ socket.resume();
+ });
+
+ socket.connectToHostEncrypted(QString::fromLatin1("localhost"), server.serverPort());
+ QVERIFY(QTest::qWaitFor([&socket](){ return socket.isEncrypted(); }));
+ socket.disconnectFromHost();
+ if (socket.state() != QAbstractSocket::UnconnectedState) {
+ QVERIFY(QTest::qWaitFor(
+ [&socket](){
+ return socket.state() == QAbstractSocket::UnconnectedState;
+ }));
+ }
+
+ auto oldList = errorList;
+ errorList.clear();
+ server.close();
+ server.m_certFile = testDataDir + "certs/bogus-client.crt";
+ server.m_keyFile = testDataDir + "certs/bogus-client.key";
+ QVERIFY(server.listen(QHostAddress::SpecialAddress::LocalHost));
+
+ socket.connectToHostEncrypted(QString::fromLatin1("localhost"), server.serverPort());
+ QVERIFY(QTest::qWaitFor([&socket](){ return socket.isEncrypted(); }));
+
+ for (const auto &error : oldList) {
+ QVERIFY2(!errorList.contains(error),
+ "The new errors should not contain any of the old ones");
+ }
+}
+
#endif // QT_NO_SSL
QTEST_MAIN(tst_QSslSocket)