diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2021-02-05 18:41:51 +0100 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2021-02-15 10:45:44 +0100 |
commit | 6d4da1340f18b66e60ed6969aeb7180e00d39077 (patch) | |
tree | fa905e6431a407b5172a4e9d77690d1f89c0b747 /src/network/ssl | |
parent | 08ace69f0e9d89d8dd758207ed1804f7e4468936 (diff) |
Schannel: Fix incomplete downloads with read buffer restricted
When the read buffer has a max size we do our best not to exceed it.
Usually there's no problem and we just read more when the next
tcp frame arrives. However if there's data leftover after the last
tcp frame arrived then we won't receive any more data. To counter
this QSslSocket would try to invoke QSslSocketPrivate::transmit
indirectly if there were any bytes available on the plain socket.
The problem is that with Schannel the last few remaining bytes
would not be in the plain socket, but in the 'intermediateBuffer'.
So let's make QSslSocket aware of that.
Fixes: QTBUG-90625
Pick-to: 5.15 6.0 6.1
Change-Id: If56e4cce558f99c9a08a1f6818e005a887712ef2
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Norbert Pfeiler <norbert.pfeiler+git@gmail.com>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'src/network/ssl')
-rw-r--r-- | src/network/ssl/qsslsocket.cpp | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_p.h | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_schannel_p.h | 2 |
3 files changed, 5 insertions, 1 deletions
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index ffbb4d61cc..67f9b58c28 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1950,7 +1950,7 @@ qint64 QSslSocket::readData(char *data, qint64 maxlen) #endif } else { // possibly trigger another transmit() to decrypt more data from the socket - if (d->plainSocket->bytesAvailable()) + if (d->plainSocket->bytesAvailable() || d->hasUndecryptedData()) QMetaObject::invokeMethod(this, "_q_flushReadBuffer", Qt::QueuedConnection); else if (d->state != QAbstractSocket::ConnectedState) return maxlen ? qint64(-1) : qint64(0); diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 6bd6cc02a4..1d6881d012 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -224,6 +224,8 @@ private: protected: bool verifyErrorsHaveBeenIgnored(); + // Only implemented/useful in Schannel for now + virtual bool hasUndecryptedData() { return false; }; bool paused; bool flushTriggered; bool systemOrSslErrorDetected = false; diff --git a/src/network/ssl/qsslsocket_schannel_p.h b/src/network/ssl/qsslsocket_schannel_p.h index 57c8c75629..30f5a9695b 100644 --- a/src/network/ssl/qsslsocket_schannel_p.h +++ b/src/network/ssl/qsslsocket_schannel_p.h @@ -123,6 +123,8 @@ private: bool rootCertOnDemandLoadingAllowed(); + bool hasUndecryptedData() override { return intermediateBuffer.size() > 0; } + SecPkgContext_ConnectionInfo connectionInfo = {}; SecPkgContext_StreamSizes streamSizes = {}; |