diff options
Diffstat (limited to 'src/network/ssl')
-rw-r--r-- | src/network/ssl/qocsp_p.h | 74 | ||||
-rw-r--r-- | src/network/ssl/qocspresponse.cpp | 109 | ||||
-rw-r--r-- | src/network/ssl/qocspresponse.h | 29 | ||||
-rw-r--r-- | src/network/ssl/qocspresponse_p.h | 17 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket.cpp | 10 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket.h | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_mac.cpp | 14 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl.cpp | 34 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl_symbols_p.h | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_schannel.cpp | 39 | ||||
-rw-r--r-- | src/network/ssl/ssl.pri | 2 |
11 files changed, 234 insertions, 98 deletions
diff --git a/src/network/ssl/qocsp_p.h b/src/network/ssl/qocsp_p.h new file mode 100644 index 0000000000..71f59da0b4 --- /dev/null +++ b/src/network/ssl/qocsp_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QOCSP_P_H +#define QOCSP_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +// Note, this file is a workaround: on 64-bit Windows one of OpenSSL +// includes combined with openssl/ocsp.h results in macros from +// wincrypt.h exposed. OpenSSL's own very "unique" and "inventive" +// names like OCSP_RESPONSE or X509_NAME were asking to clash with +// other entities (presumably macros) with the same names. Normally, +// ossl_typ.h un-defines them, but due to a bug in OpenSSL, fails +// to do this on Win 64. Thus we have to do it here. We only undef +// 3 names, ossl_typ.h has more, but apparently we don't need them +// (no name clash so far). + +QT_REQUIRE_CONFIG(ocsp); + +#ifdef Q_OS_WIN +#undef X509_NAME +#undef OCSP_REQUEST +#undef OCSP_RESPONSE +#endif // Q_OS_WIN + +#include <openssl/ocsp.h> + +#endif // QOCSP_P_H diff --git a/src/network/ssl/qocspresponse.cpp b/src/network/ssl/qocspresponse.cpp index 1466364af2..496979913b 100644 --- a/src/network/ssl/qocspresponse.cpp +++ b/src/network/ssl/qocspresponse.cpp @@ -40,6 +40,8 @@ #include "qocspresponse_p.h" #include "qocspresponse.h" +#include "qhashfunctions.h" + QT_BEGIN_NAMESPACE /*! @@ -56,13 +58,13 @@ QT_BEGIN_NAMESPACE configured with OCSP stapling enabled. \sa QSslSocket, QSslSocket::ocspResponse(), certificateStatus(), - revocationReason(), responder(), subject(), OcspCertificateStatus, OcspRevocationReason, + revocationReason(), responder(), subject(), QOcspCertificateStatus, QOcspRevocationReason, QSslConfiguration::setOcspStaplingEnabled(), QSslConfiguration::ocspStaplingEnabled(), QSslConfiguration::peerCertificate() */ /*! - \enum OcspCertificateStatus + \enum QOcspCertificateStatus \brief Describes the Online Certificate Status \relates QOcspResponse \since 5.13 @@ -79,11 +81,11 @@ QT_BEGIN_NAMESPACE \value Unknown This state indicates that the responder doesn't know about the certificate being requested. - \sa OcspRevocationReason + \sa QOcspRevocationReason */ /*! - \enum OcspRevocationReason + \enum QOcspRevocationReason \brief Describes the reason for revocation \relates QOcspResponse \since 5.13 @@ -109,10 +111,10 @@ QT_BEGIN_NAMESPACE /*! \since 5.13 - Creates a new response with status OcspCertificateStatus::Unknown - and revocation reason OcspRevocationReason::None. + Creates a new response with status QOcspCertificateStatus::Unknown + and revocation reason QOcspRevocationReason::None. - \sa OcspCertificateStatus + \sa QOcspCertificateStatus */ QOcspResponse::QOcspResponse() : d(new QOcspResponsePrivate) @@ -124,64 +126,51 @@ QOcspResponse::QOcspResponse() Creates a new response, the copy of \a other. */ -QOcspResponse::QOcspResponse(const QOcspResponse &other) -{ - *d = *other.d; -} +QOcspResponse::QOcspResponse(const QOcspResponse &other) = default; /*! \since 5.13 Move-constructs a QOcspResponse instance from \a other. */ -QOcspResponse::QOcspResponse(QOcspResponse &&other) Q_DECL_NOTHROW -{ - d.swap(other.d); -} +QOcspResponse::QOcspResponse(QOcspResponse &&other) Q_DECL_NOTHROW = default; /*! \since 5.13 Destroys the response. */ -QOcspResponse::~QOcspResponse() -{ -} +QOcspResponse::~QOcspResponse() = default; /*! \since 5.13 - Assignes \a other to the response and returns a reference to this response. + Assigns \a other to the response and returns a reference to this response. */ -QOcspResponse &QOcspResponse::operator=(const QOcspResponse &other) -{ - if (this != &other) - *d = *other.d; - - return *this; -} +QOcspResponse &QOcspResponse::operator=(const QOcspResponse &other) = default; /*! \since 5.13 Move-assigns \a other to this QOcspResponse instance. */ -QOcspResponse &QOcspResponse::operator=(QOcspResponse &&other) Q_DECL_NOTHROW -{ - if (this != &other) - d.swap(other.d); +QOcspResponse &QOcspResponse::operator=(QOcspResponse &&other) Q_DECL_NOTHROW = default; - return *this; -} +/*! + \fn void QOcspResponse::swap(QOcspResponse &other) + \since 5.13 + + Swaps this response with \a other. +*/ /*! \since 5.13 Returns the certificate status. - \sa OcspCertificateStatus + \sa QOcspCertificateStatus */ -OcspCertificateStatus QOcspResponse::certificateStatus() const +QOcspCertificateStatus QOcspResponse::certificateStatus() const { return d->certificateStatus; } @@ -191,7 +180,7 @@ OcspCertificateStatus QOcspResponse::certificateStatus() const Returns the reason for revocation. */ -OcspRevocationReason QOcspResponse::revocationReason() const +QOcspRevocationReason QOcspResponse::revocationReason() const { return d->revocationReason; } @@ -216,4 +205,54 @@ QSslCertificate QOcspResponse::subject() const return d->subjectCert; } +/*! + \fn bool operator==(const QOcspResponse &lhs, const QOcspResponse &rhs) + + Returns \c true if \a lhs and \a rhs are the responses for the same + certificate, signed by the same responder, have the same + revocation reason and the same certificate status. + + \since 5.13 + \relates QOcspResponse + */ +Q_NETWORK_EXPORT bool operator==(const QOcspResponse &lhs, const QOcspResponse &rhs) +{ + return lhs.d == rhs.d || *lhs.d == *rhs.d; +} + +/*! + \fn bool operator != (const QOcspResponse &lhs, const QOcspResponse &rhs) + + Returns \c true if \a lhs and \a rhs are responses for different certificates, + or signed by different responders, or have different revocation reasons, or different + certificate statuses. + + \since 5.13 + \relates QOcspResponse +*/ + +/*! + \fn uint qHash(const QOcspResponse &response, uint seed) + + Returns the hash value for the \a response, using \a seed to seed the calculation. + + \since 5.13 + \relates QHash +*/ +uint qHash(const QOcspResponse &response, uint seed) +{ + const QOcspResponsePrivate *d = response.d.data(); + Q_ASSERT(d); + + QtPrivate::QHashCombine hasher; + uint hash = hasher(seed, int(d->certificateStatus)); + hash = hasher(hash, int(d->revocationReason)); + if (!d->signerCert.isNull()) + hash = hasher(hash, d->signerCert); + if (!d->subjectCert.isNull()) + hash = hasher(hash, d->subjectCert); + + return hash; +} + QT_END_NAMESPACE diff --git a/src/network/ssl/qocspresponse.h b/src/network/ssl/qocspresponse.h index 5cff625b84..552a088ba5 100644 --- a/src/network/ssl/qocspresponse.h +++ b/src/network/ssl/qocspresponse.h @@ -42,8 +42,9 @@ #include <QtNetwork/qtnetworkglobal.h> +#include <QtCore/qshareddata.h> +#include <QtCore/qmetatype.h> #include <QtCore/qobject.h> -#include <QtCore/qscopedpointer.h> #ifndef Q_CLANG_QDOC QT_REQUIRE_CONFIG(ssl); @@ -51,14 +52,14 @@ QT_REQUIRE_CONFIG(ssl); QT_BEGIN_NAMESPACE -enum class OcspCertificateStatus +enum class QOcspCertificateStatus { Good, Revoked, Unknown }; -enum class OcspRevocationReason +enum class QOcspRevocationReason { None = -1, Unspecified, @@ -71,8 +72,11 @@ enum class OcspRevocationReason RemoveFromCRL }; +class QOcspResponse; +Q_NETWORK_EXPORT uint qHash(const QOcspResponse &response, uint seed = 0); + class QOcspResponsePrivate; -class QOcspResponse +class Q_NETWORK_EXPORT QOcspResponse { public: @@ -84,18 +88,29 @@ public: QOcspResponse &operator = (const QOcspResponse &other); QOcspResponse &operator = (QOcspResponse &&other) Q_DECL_NOTHROW; - OcspCertificateStatus certificateStatus() const; - OcspRevocationReason revocationReason() const; + QOcspCertificateStatus certificateStatus() const; + QOcspRevocationReason revocationReason() const; class QSslCertificate responder() const; QSslCertificate subject() const; + void swap(QOcspResponse &other) Q_DECL_NOTHROW { d.swap(other.d); } + private: friend class QSslSocketBackendPrivate; - QScopedPointer<QOcspResponsePrivate> d; + friend Q_NETWORK_EXPORT bool operator==(const QOcspResponse &lhs, const QOcspResponse &rhs); + friend Q_NETWORK_EXPORT uint qHash(const QOcspResponse &response, uint seed); + + QSharedDataPointer<QOcspResponsePrivate> d; }; +inline bool operator!=(const QOcspResponse &lhs, const QOcspResponse &rhs) { return !(lhs == rhs); } + +Q_DECLARE_SHARED(QOcspResponse) + QT_END_NAMESPACE +Q_DECLARE_METATYPE(QOcspResponse) + #endif // QOCSPRESPONSE_H diff --git a/src/network/ssl/qocspresponse_p.h b/src/network/ssl/qocspresponse_p.h index 44480df633..e421b76899 100644 --- a/src/network/ssl/qocspresponse_p.h +++ b/src/network/ssl/qocspresponse_p.h @@ -44,6 +44,9 @@ #include <qsslcertificate.h> #include <qocspresponse.h> + +#include <qshareddata.h> + // // W A R N I N G // ------------- @@ -57,17 +60,25 @@ QT_BEGIN_NAMESPACE -class QOcspResponsePrivate +class QOcspResponsePrivate : public QSharedData { public: - OcspCertificateStatus certificateStatus = OcspCertificateStatus::Unknown; - OcspRevocationReason revocationReason = OcspRevocationReason::None; + QOcspCertificateStatus certificateStatus = QOcspCertificateStatus::Unknown; + QOcspRevocationReason revocationReason = QOcspRevocationReason::None; QSslCertificate signerCert; QSslCertificate subjectCert; }; +inline bool operator==(const QOcspResponsePrivate &lhs, const QOcspResponsePrivate &rhs) +{ + return lhs.certificateStatus == rhs.certificateStatus + && lhs.revocationReason == rhs.revocationReason + && lhs.signerCert == rhs.signerCert + && lhs.subjectCert == rhs.subjectCert; +} + QT_END_NAMESPACE #endif // QOCSPRESPONSE_P_H diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index fc9a44f896..cf8a472606 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1228,6 +1228,7 @@ QSslKey QSslSocket::privateKey() const return d->configuration.privateKey; } +#if QT_DEPRECATED_SINCE(5, 5) /*! \deprecated @@ -1371,6 +1372,7 @@ QList<QSslCipher> QSslSocket::supportedCiphers() { return QSslSocketPrivate::supportedCiphers(); } +#endif // #if QT_DEPRECATED_SINCE(5, 5) /*! Searches all files in the \a path for certificates encoded in the @@ -1430,6 +1432,7 @@ void QSslSocket::addCaCertificates(const QList<QSslCertificate> &certificates) d->configuration.caCertificates += certificates; } +#if QT_DEPRECATED_SINCE(5, 5) /*! \deprecated @@ -1474,6 +1477,7 @@ QList<QSslCertificate> QSslSocket::caCertificates() const Q_D(const QSslSocket); return d->configuration.caCertificates; } +#endif // #if QT_DEPRECATED_SINCE(5, 5) /*! Searches all files in the \a path for certificates with the @@ -1518,6 +1522,7 @@ void QSslSocket::addDefaultCaCertificates(const QList<QSslCertificate> &certific QSslSocketPrivate::addDefaultCaCertificates(certificates); } +#if QT_DEPRECATED_SINCE(5, 5) /*! \deprecated @@ -1585,6 +1590,7 @@ QList<QSslCertificate> QSslSocket::systemCaCertificates() // we are calling ensureInitialized() in the method below return QSslSocketPrivate::systemCaCertificates(); } +#endif // #if QT_DEPRECATED_SINCE(5, 5) /*! Waits until the socket is connected, or \a msecs milliseconds, @@ -2454,8 +2460,8 @@ void QSslSocketPrivate::createPlainSocket(QIODevice::OpenMode openMode) q->connect(plainSocket, SIGNAL(bytesWritten(qint64)), q, SLOT(_q_bytesWrittenSlot(qint64)), Qt::DirectConnection); - q->connect(plainSocket, SIGNAL(channelBytesWritten(int, qint64)), - q, SLOT(_q_channelBytesWrittenSlot(int, qint64)), + q->connect(plainSocket, SIGNAL(channelBytesWritten(int,qint64)), + q, SLOT(_q_channelBytesWrittenSlot(int,qint64)), Qt::DirectConnection); q->connect(plainSocket, SIGNAL(readChannelFinished()), q, SLOT(_q_readChannelFinishedSlot()), diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h index 4a695a6b01..35943c7d7e 100644 --- a/src/network/ssl/qsslsocket.h +++ b/src/network/ssl/qsslsocket.h @@ -44,6 +44,7 @@ #include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qlist.h> #include <QtCore/qregexp.h> +#include <QtCore/qvector.h> #ifndef QT_NO_SSL # include <QtNetwork/qtcpsocket.h> # include <QtNetwork/qsslerror.h> @@ -61,7 +62,6 @@ class QSslConfiguration; class QSslEllipticCurve; class QSslPreSharedKeyAuthenticator; class QOcspResponse; -template<class> class QVector; class QSslSocketPrivate; class Q_NETWORK_EXPORT QSslSocket : public QTcpSocket diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 9c3c98e390..487e975db6 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -506,6 +506,8 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const return QSsl::TlsV1_1; case kTLSProtocol12: return QSsl::TlsV1_2; + case kTLSProtocol13: + return QSsl::TlsV1_3; default: return QSsl::UnknownProtocol; } @@ -1153,8 +1155,6 @@ bool QSslSocketBackendPrivate::setSessionProtocol() qCDebug(lcSsl) << plainSocket << "requesting : any"; #endif err = SSLSetProtocolVersionMin(context, kTLSProtocol1); - if (err == errSecSuccess) - err = SSLSetProtocolVersionMax(context, kTLSProtocol12); } else if (configuration.protocol == QSsl::TlsV1SslV3) { #ifdef QSSLSOCKET_DEBUG qCDebug(lcSsl) << plainSocket << "requesting : SSLv3 - TLSv1.2"; @@ -1167,29 +1167,21 @@ bool QSslSocketBackendPrivate::setSessionProtocol() qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2"; #endif err = SSLSetProtocolVersionMin(context, kTLSProtocol1); - if (err == errSecSuccess) - err = SSLSetProtocolVersionMax(context, kTLSProtocol12); } else if (configuration.protocol == QSsl::TlsV1_0OrLater) { #ifdef QSSLSOCKET_DEBUG qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2"; #endif err = SSLSetProtocolVersionMin(context, kTLSProtocol1); - if (err == errSecSuccess) - err = SSLSetProtocolVersionMax(context, kTLSProtocol12); } else if (configuration.protocol == QSsl::TlsV1_1OrLater) { #ifdef QSSLSOCKET_DEBUG qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1 - TLSv1.2"; #endif err = SSLSetProtocolVersionMin(context, kTLSProtocol11); - if (err == errSecSuccess) - err = SSLSetProtocolVersionMax(context, kTLSProtocol12); } else if (configuration.protocol == QSsl::TlsV1_2OrLater) { #ifdef QSSLSOCKET_DEBUG qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2"; #endif err = SSLSetProtocolVersionMin(context, kTLSProtocol12); - if (err == errSecSuccess) - err = SSLSetProtocolVersionMax(context, kTLSProtocol12); } else { #ifdef QSSLSOCKET_DEBUG qCDebug(lcSsl) << plainSocket << "no protocol version found in the configuration"; @@ -1224,6 +1216,8 @@ bool QSslSocketBackendPrivate::verifySessionProtocol() const protocolOk = (sessionProtocol() >= QSsl::TlsV1_1); else if (configuration.protocol == QSsl::TlsV1_2OrLater) protocolOk = (sessionProtocol() >= QSsl::TlsV1_2); + else if (configuration.protocol == QSsl::TlsV1_3OrLater) + protocolOk = (sessionProtocol() >= QSsl::TlsV1_3OrLater); else protocolOk = (sessionProtocol() == configuration.protocol); diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 15b2b4c2cf..c48cd42360 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -85,7 +85,7 @@ #include <QtCore/qscopedvaluerollback.h> #if QT_CONFIG(ocsp) -#include <openssl/ocsp.h> +#include "qocsp_p.h" #endif #include <algorithm> @@ -258,29 +258,29 @@ QSslError qt_OCSP_response_status_to_QSslError(long code) Q_UNREACHABLE(); } -OcspRevocationReason qt_OCSP_revocation_reason(int reason) +QOcspRevocationReason qt_OCSP_revocation_reason(int reason) { switch (reason) { case OCSP_REVOKED_STATUS_NOSTATUS: - return OcspRevocationReason::None; + return QOcspRevocationReason::None; case OCSP_REVOKED_STATUS_UNSPECIFIED: - return OcspRevocationReason::Unspecified; + return QOcspRevocationReason::Unspecified; case OCSP_REVOKED_STATUS_KEYCOMPROMISE: - return OcspRevocationReason::KeyCompromise; + return QOcspRevocationReason::KeyCompromise; case OCSP_REVOKED_STATUS_CACOMPROMISE: - return OcspRevocationReason::CACompromise; + return QOcspRevocationReason::CACompromise; case OCSP_REVOKED_STATUS_AFFILIATIONCHANGED: - return OcspRevocationReason::AffiliationChanged; + return QOcspRevocationReason::AffiliationChanged; case OCSP_REVOKED_STATUS_SUPERSEDED: - return OcspRevocationReason::Superseded; + return QOcspRevocationReason::Superseded; case OCSP_REVOKED_STATUS_CESSATIONOFOPERATION: - return OcspRevocationReason::CessationOfOperation; + return QOcspRevocationReason::CessationOfOperation; case OCSP_REVOKED_STATUS_CERTIFICATEHOLD: - return OcspRevocationReason::CertificateHold; + return QOcspRevocationReason::CertificateHold; case OCSP_REVOKED_STATUS_REMOVEFROMCRL: - return OcspRevocationReason::RemoveFromCRL; + return QOcspRevocationReason::RemoveFromCRL; default: - return OcspRevocationReason::None; + return QOcspRevocationReason::None; } Q_UNREACHABLE(); @@ -596,6 +596,10 @@ bool QSslSocketBackendPrivate::initSslContext() void QSslSocketBackendPrivate::destroySslContext() { if (ssl) { + // We do not send a shutdown alert here. Just mark the session as + // resumable for qhttpnetworkconnection's "optimization", otherwise + // OpenSSL won't start a session resumption. + q_SSL_shutdown(ssl); q_SSL_free(ssl); ssl = nullptr; } @@ -1620,15 +1624,15 @@ bool QSslSocketBackendPrivate::checkOcspStatus() switch (certStatus) { case V_OCSP_CERTSTATUS_GOOD: // This certificate was not found among the revoked ones. - dResponse->certificateStatus = OcspCertificateStatus::Good; + dResponse->certificateStatus = QOcspCertificateStatus::Good; break; case V_OCSP_CERTSTATUS_REVOKED: - dResponse->certificateStatus = OcspCertificateStatus::Revoked; + dResponse->certificateStatus = QOcspCertificateStatus::Revoked; dResponse->revocationReason = qt_OCSP_revocation_reason(reason); ocspErrors.push_back({QSslError::CertificateRevoked, configuration.peerCertificate}); break; case V_OCSP_CERTSTATUS_UNKNOWN: - dResponse->certificateStatus = OcspCertificateStatus::Unknown; + dResponse->certificateStatus = QOcspCertificateStatus::Unknown; ocspErrors.push_back({QSslError::OcspStatusUnknown, configuration.peerCertificate}); } diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index cf426e2ed2..e09820b2f2 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -73,7 +73,7 @@ #include <QtCore/qglobal.h> #if QT_CONFIG(ocsp) -#include <openssl/ocsp.h> +#include "qocsp_p.h" #endif QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/qsslsocket_schannel.cpp b/src/network/ssl/qsslsocket_schannel.cpp index 965e9bf2f3..e75f81bd36 100644 --- a/src/network/ssl/qsslsocket_schannel.cpp +++ b/src/network/ssl/qsslsocket_schannel.cpp @@ -142,12 +142,9 @@ Medium priority: - Setting cipher-suites (or ALG_ID) - People have survived without it in WinRT - - ALPN: - For HTTP2. Note: Windows 8.1 and up ONLY. Low priority: - Possibly make RAII wrappers for SecBuffer (which I commonly create QScopeGuards for) - - Perform the '@future' optimization in "transmit()" */ @@ -1188,23 +1185,21 @@ void QSslSocketBackendPrivate::transmit() qint64 totalBytesWritten = 0; qint64 writeBufferSize; while ((writeBufferSize = writeBuffer.size()) > 0) { - QByteArray plaintext; + const int headerSize = int(streamSizes.cbHeader); + const int trailerSize = int(streamSizes.cbTrailer); + // Try to read 'cbMaximumMessage' bytes from buffer before encrypting. + const int size = int(std::min(writeBufferSize, qint64(streamSizes.cbMaximumMessage))); + QByteArray fullMessage(headerSize + trailerSize + size, Qt::Uninitialized); { - // Try to read 'cbMaximumMessage' bytes from buffer before encrypting. - int size = int(std::min(writeBufferSize, qint64(streamSizes.cbMaximumMessage))); - plaintext.resize(size); // Use peek() here instead of read() so we don't lose data if encryption fails. - qint64 copied = writeBuffer.peek(plaintext.data(), size); + qint64 copied = writeBuffer.peek(fullMessage.data() + headerSize, size); Q_ASSERT(copied == size); } - QByteArray header(int(streamSizes.cbHeader), '\0'); - QByteArray trailer(int(streamSizes.cbTrailer), '\0'); SecBuffer inputBuffers[4]{ - // @future[0/1]: optimize by using one container for all fields... - createSecBuffer(header, SECBUFFER_STREAM_HEADER), - createSecBuffer(plaintext, SECBUFFER_DATA), - createSecBuffer(trailer, SECBUFFER_STREAM_TRAILER), + createSecBuffer(fullMessage.data(), headerSize, SECBUFFER_STREAM_HEADER), + createSecBuffer(fullMessage.data() + headerSize, size, SECBUFFER_DATA), + createSecBuffer(fullMessage.data() + headerSize + size, trailerSize, SECBUFFER_STREAM_TRAILER), createSecBuffer(nullptr, 0, SECBUFFER_EMPTY) }; SecBufferDesc message{ @@ -1220,18 +1215,14 @@ void QSslSocketBackendPrivate::transmit() return; } // Data was encrypted successfully, so we free() what we peek()ed earlier - writeBuffer.free(plaintext.length()); - - // trailer has been observed to change size, so resize them all (when needed) to be safe - header = header.left(int(inputBuffers[0].cbBuffer)); - plaintext = plaintext.left(int(inputBuffers[1].cbBuffer)); - trailer = trailer.left(int(inputBuffers[2].cbBuffer)); - const qint64 bytesWritten = plainSocket->write(header // @future[1/1]: ...because they need to be merged - + plaintext - + trailer); + writeBuffer.free(size); + + // The trailer's size is not final, so resize fullMessage to not send trailing junk + fullMessage.resize(inputBuffers[0].cbBuffer + inputBuffers[1].cbBuffer + inputBuffers[2].cbBuffer); + const qint64 bytesWritten = plainSocket->write(fullMessage); #ifdef QSSLSOCKET_DEBUG qCDebug(lcSsl) << "Wrote" << bytesWritten << "of total" - << header.length() + plaintext.length() + trailer.length() << "bytes"; + << fullMessage.length() << "bytes"; #endif if (bytesWritten >= 0) { totalBytesWritten += bytesWritten; diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri index 5712a26fd8..8bb70a2aed 100644 --- a/src/network/ssl/ssl.pri +++ b/src/network/ssl/ssl.pri @@ -100,6 +100,8 @@ qtConfig(ssl) { SOURCES += ssl/qdtls_openssl.cpp } + qtConfig(ocsp): HEADERS += ssl/qocsp_p.h + qtConfig(opensslv11) { HEADERS += ssl/qsslsocket_openssl11_symbols_p.h SOURCES += ssl/qsslsocket_openssl11.cpp \ |