Skip to content

Commit 488cb66

Browse files
phartmannThe Qt Project
authored andcommitted
SSL internals: do not write after shutting down the socket
... but rather throw an error, so the HTTP layer can recover from a SSL shutdown gracefully. In case the other side sent us a shutdown, we tried to send one as well, which results in an error. (backport of commit e145b67fbd54f147dab0f8e460280a9c8533aa7b) Change-Id: I57291a5363cb0f6585dbd6aaa521c748766a1fdf Reviewed-by: Richard J. Moore <[email protected]>
1 parent 1df30fb commit 488cb66

File tree

4 files changed

+15
-5
lines changed

4 files changed

+15
-5
lines changed

src/network/ssl/qsslsocket.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,7 @@ QSslSocketPrivate::QSslSocketPrivate()
18511851
, mode(QSslSocket::UnencryptedMode)
18521852
, autoStartHandshake(false)
18531853
, connectionEncrypted(false)
1854+
, shutdown(false)
18541855
, ignoreAllSslErrors(false)
18551856
, readyReadEmittedPointer(0)
18561857
, allowRootCertOnDemandLoading(true)
@@ -1875,6 +1876,7 @@ void QSslSocketPrivate::init()
18751876
autoStartHandshake = false;
18761877
connectionEncrypted = false;
18771878
ignoreAllSslErrors = false;
1879+
shutdown = false;
18781880

18791881
// we don't want to clear the ignoreErrorsList, so
18801882
// that it is possible setting it before connecting

src/network/ssl/qsslsocket_openssl.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,8 +1163,11 @@ void QSslSocketBackendPrivate::transmit()
11631163
#ifdef QSSLSOCKET_DEBUG
11641164
qDebug() << "QSslSocketBackendPrivate::transmit: remote disconnect";
11651165
#endif
1166-
plainSocket->disconnectFromHost();
1167-
break;
1166+
shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves
1167+
q->setErrorString(QSslSocket::tr("The TLS/SSL connection has been closed"));
1168+
q->setSocketError(QAbstractSocket::RemoteHostClosedError);
1169+
emit q->error(QAbstractSocket::RemoteHostClosedError);
1170+
return;
11681171
case SSL_ERROR_SYSCALL: // some IO error
11691172
case SSL_ERROR_SSL: // error in the SSL library
11701173
// we do not know exactly what the error is, nor whether we can recover from it,
@@ -1447,8 +1450,11 @@ bool QSslSocketBackendPrivate::startHandshake()
14471450
void QSslSocketBackendPrivate::disconnectFromHost()
14481451
{
14491452
if (ssl) {
1450-
q_SSL_shutdown(ssl);
1451-
transmit();
1453+
if (!shutdown) {
1454+
q_SSL_shutdown(ssl);
1455+
shutdown = true;
1456+
transmit();
1457+
}
14521458
}
14531459
plainSocket->disconnectFromHost();
14541460
}

src/network/ssl/qsslsocket_p.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ class QSslSocketPrivate : public QTcpSocketPrivate
108108
QSslSocket::SslMode mode;
109109
bool autoStartHandshake;
110110
bool connectionEncrypted;
111+
bool shutdown;
111112
bool ignoreAllSslErrors;
112113
QList<QSslError> ignoreErrorsList;
113114
bool* readyReadEmittedPointer;

tests/auto/qsslsocket/tst_qsslsocket.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1996,7 +1996,8 @@ void tst_QSslSocket::writeBigChunk()
19961996
QFAIL("Error while writing! Check if the OpenSSL BIO size is limited?!");
19971997
}
19981998
// also check the error string. If another error (than UnknownError) occurred, it should be different than before
1999-
QVERIFY(errorBefore == errorAfter);
1999+
QVERIFY2(errorBefore == errorAfter || socket->error() == QAbstractSocket::RemoteHostClosedError,
2000+
QByteArray("unexpected error: ").append(qPrintable(errorAfter)));
20002001

20012002
// check that everything has been written to OpenSSL
20022003
QVERIFY(socket->bytesToWrite() == 0);

0 commit comments

Comments
 (0)