diff options
author | Timur Pocheptsov <timur.pocheptsov@theqtcompany.com> | 2016-06-15 10:01:14 +0200 |
---|---|---|
committer | Timur Pocheptsov <timur.pocheptsov@theqtcompany.com> | 2016-06-30 08:04:55 +0000 |
commit | faeaddc1b92f1000a5a1d9d7cdea9276bdfefe26 (patch) | |
tree | eb1c9e945ce114ea7f9921e4fe447973799688f7 /src/network/ssl | |
parent | 7a8330ddf7601608346036e2f120a4497e016ee8 (diff) |
QSslSocket::transmit (macOS/iOS) - do not use invalid context
1. QSslSocketBackendPrivate::transmit can invalidate SSL context
causing subsequent SSLWrite or SSLRead calls to fail; these report
errSecParam (as null context is an invalid parameter) spuriously,
when we should rather report the cause of invalidation. The OpenSSL
backend can trigger this when it aborts connection during an SSL
handshake, on an sslErrors signal. As transmit() emits readReady(),
a directly connected slot can trigger the same problem if it aborts or
closes.
2. If during peer verification (and in checkSslErrors) we disconnect
on sslErrors signal, peer verification must be considered failed and
should not continue handshake/set connectionEncrypted.
Task-number: QTBUG-52975
Task-number: QTBUG-53906
Change-Id: Iacd3b489a4156e25ef3460ace40d21f34a946bed
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/network/ssl')
-rw-r--r-- | src/network/ssl/qsslsocket_mac.cpp | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 4e090f96cb..9f0359aa47 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -634,7 +634,7 @@ void QSslSocketBackendPrivate::transmit() if (connectionEncrypted && !writeBuffer.isEmpty()) { qint64 totalBytesWritten = 0; - while (writeBuffer.nextDataBlockSize() > 0) { + while (writeBuffer.nextDataBlockSize() > 0 && context) { const size_t nextDataBlockSize = writeBuffer.nextDataBlockSize(); size_t writtenBytes = 0; const OSStatus err = SSLWrite(context, writeBuffer.readPointer(), nextDataBlockSize, &writtenBytes); @@ -668,7 +668,7 @@ void QSslSocketBackendPrivate::transmit() if (connectionEncrypted) { QVarLengthArray<char, 4096> data; - while (true) { + while (context) { size_t readBytes = 0; data.resize(4096); const OSStatus err = SSLRead(context, data.data(), data.size(), &readBytes); @@ -1305,7 +1305,10 @@ bool QSslSocketBackendPrivate::verifyPeerTrust() // report errors if (!errors.isEmpty() && !canIgnoreVerify) { sslErrors = errors; - if (!checkSslErrors()) + // checkSslErrors unconditionally emits sslErrors: + // a user's slot can abort/close/disconnect on this + // signal, so we also test the socket's state: + if (!checkSslErrors() || q->state() != QAbstractSocket::ConnectedState) return false; } else { sslErrors.clear(); |