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>
This commit is contained in:
Mårten Nordheim 2019-09-27 16:16:52 +02:00
parent e00d888dae
commit 3dd8f6dc34
2 changed files with 51 additions and 1 deletions

View File

@ -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) {

View File

@ -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)