QSslSocket (OpenSSL) - handle abort/close on sslErrors emitted

If a user's code, attached to sslErrors signal, calls abort/close
or disconnectFromHost but our SSL socket was configured not to verify a peer,
no need to continue handshake after calling checkSslErrors
(and finally crashing on invalid 'ssl' pointer).

Task-number: QTBUG-53906
Change-Id: I7f185511d278f9d6f16e7d6c5ba424707141459c
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@theqtcompany.com>
bb10
Timur Pocheptsov 2016-06-09 10:36:50 +02:00
parent e969e6d2ca
commit 23173c725c
2 changed files with 32 additions and 0 deletions

View File

@ -1240,6 +1240,11 @@ bool QSslSocketBackendPrivate::startHandshake()
#endif
if (!checkSslErrors())
return false;
// A slot, attached to sslErrors signal can call
// abort/close/disconnetFromHost/etc; no need to
// continue handshake then.
if (q->state() != QAbstractSocket::ConnectedState)
return false;
} else {
sslErrors.clear();
}

View File

@ -212,6 +212,7 @@ private slots:
void ignoreSslErrorsList();
void ignoreSslErrorsListWithSlot_data();
void ignoreSslErrorsListWithSlot();
void abortOnSslErrors();
void readFromClosedSocket();
void writeBigChunk();
void blacklistedCertificates();
@ -250,6 +251,11 @@ protected slots:
{
socket->ignoreSslErrors();
}
void abortOnErrorSlot()
{
QSslSocket *sock = static_cast<QSslSocket *>(sender());
sock->abort();
}
void untrustedWorkaroundSlot(const QList<QSslError> &errors)
{
if (errors.size() == 1 &&
@ -2311,6 +2317,27 @@ void tst_QSslSocket::ignoreSslErrorsListWithSlot()
QSKIP("Skipping flaky test - See QTBUG-29941");
}
void tst_QSslSocket::abortOnSslErrors()
{
QFETCH_GLOBAL(bool, setProxy);
if (setProxy)
return;
SslServer server;
QVERIFY(server.listen());
QSslSocket clientSocket;
connect(&clientSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(abortOnErrorSlot()));
clientSocket.connectToHostEncrypted("127.0.0.1", server.serverPort());
clientSocket.ignoreSslErrors();
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
loop.exec();
QCOMPARE(clientSocket.state(), QAbstractSocket::UnconnectedState);
}
// make sure a closed socket has no bytesAvailable()
// related to https://bugs.webkit.org/show_bug.cgi?id=28016
void tst_QSslSocket::readFromClosedSocket()