diff options
author | Timur Pocheptsov <timur.pocheptsov@qt.io> | 2020-06-03 12:30:41 +0200 |
---|---|---|
committer | Timur Pocheptsov <timur.pocheptsov@qt.io> | 2020-07-28 15:35:41 +0200 |
commit | c9a702a04d4b90b0a04966d7918f01ddfe9808c1 (patch) | |
tree | 64c9628c57dedb615405b5af25faeca92be72d0d /src | |
parent | 964f5757ea00c5fd4a8c617e8df1bfa353c5b225 (diff) |
QSslSocket (OpenSSL, Windows) - make sure we ignore stale fetch results
The CA fetcher on Windows works on a separate thread, it can take
quite some time to finish its job and if a connection was meanwhile
closed (via 'abort', 'close' or 'disconnectFromHost') but the socket
is still alive/re-used - we don't want to be fooled by the previous
fetch 'finished' signal, only if it's fetching for the same certificate.
Change-Id: Ibd0a70000ad10cff10207d37d7b47c38e615d0f1
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/network/ssl/qsslsocket.cpp | 13 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl.cpp | 15 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_p.h | 1 |
3 files changed, 28 insertions, 1 deletions
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index e294a45157..66bcb79c4c 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -898,6 +898,10 @@ void QSslSocket::close() qCDebug(lcSsl) << "QSslSocket::close()"; #endif Q_D(QSslSocket); + + // We don't want any CA roots fetched anymore. + d->caToFetch = QSslCertificate{}; + if (encryptedBytesToWrite() || !d->writeBuffer.isEmpty()) flush(); if (d->plainSocket) @@ -947,6 +951,11 @@ void QSslSocket::abort() #ifdef QSSLSOCKET_DEBUG qCDebug(lcSsl) << "QSslSocket::abort()"; #endif + // On Windows, CertGetCertificateChain is probably still doing its + // job, if the socket is re-used, we want to ignore its reported + // root CA. + d->caToFetch = QSslCertificate{}; + if (d->plainSocket) d->plainSocket->abort(); close(); @@ -1768,6 +1777,9 @@ void QSslSocket::disconnectFromHost() d->pendingClose = true; return; } + // Make sure we don't process any signal from the CA fetcher + // (Windows): + d->caToFetch = QSslCertificate{}; // Perhaps emit closing() if (d->state != ClosingState) { @@ -1884,6 +1896,7 @@ void QSslSocketPrivate::init() configuration.peerCertificate.clear(); configuration.peerCertificateChain.clear(); fetchAuthorityInformation = false; + caToFetch = QSslCertificate{}; } /*! diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 43fe94639f..99b7a77b4d 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1736,8 +1736,13 @@ void QSslSocketBackendPrivate::fetchCaRootForCert(const QSslCertificate &cert) if (fetchAuthorityInformation) customRoots = configuration.caCertificates; + //Remember we are fetching and what we are fetching: + caToFetch = cert; + QWindowsCaRootFetcher *fetcher = new QWindowsCaRootFetcher(cert, mode, customRoots, q->peerVerifyName()); - QObject::connect(fetcher, SIGNAL(finished(QSslCertificate,QSslCertificate)), q, SLOT(_q_caRootLoaded(QSslCertificate,QSslCertificate)), Qt::QueuedConnection); + QObjectPrivate::connect(fetcher, &QWindowsCaRootFetcher::finished, + this, &QSslSocketBackendPrivate::_q_caRootLoaded, + Qt::QueuedConnection); QMetaObject::invokeMethod(fetcher, "start", Qt::QueuedConnection); pauseSocketNotifiers(q); paused = true; @@ -1746,6 +1751,14 @@ void QSslSocketBackendPrivate::fetchCaRootForCert(const QSslCertificate &cert) //This is the callback from QWindowsCaRootFetcher, trustedRoot will be invalid (default constructed) if it failed. void QSslSocketBackendPrivate::_q_caRootLoaded(QSslCertificate cert, QSslCertificate trustedRoot) { + if (caToFetch != cert) { + //Ooops, something from the previous connection attempt, ignore! + return; + } + + //Done, fetched already: + caToFetch = QSslCertificate{}; + if (fetchAuthorityInformation) { if (!configuration.caCertificates.contains(trustedRoot)) trustedRoot = QSslCertificate{}; diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 170fbb6b35..60d5cd1484 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -222,6 +222,7 @@ protected: QList<QOcspResponse> ocspResponses; bool handshakeInterrupted = false; bool fetchAuthorityInformation = false; + QSslCertificate caToFetch; }; #if QT_CONFIG(securetransport) || QT_CONFIG(schannel) |