diff options
Diffstat (limited to 'src/network/ssl/qdtls.cpp')
-rw-r--r-- | src/network/ssl/qdtls.cpp | 470 |
1 files changed, 254 insertions, 216 deletions
diff --git a/src/network/ssl/qdtls.cpp b/src/network/ssl/qdtls.cpp index af89740898..38ce144c8a 100644 --- a/src/network/ssl/qdtls.cpp +++ b/src/network/ssl/qdtls.cpp @@ -1,45 +1,10 @@ -/**************************************************************************** -** -** Copyright (C) 2018 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$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qsslconfiguration.h" -#include "qdtls_openssl_p.h" +#include "qsslsocket_p.h" #include "qudpsocket.h" +#include "qsslcipher.h" #include "qdtls_p.h" #include "qssl_p.h" #include "qdtls.h" @@ -57,7 +22,7 @@ The QDtlsClientVerifier class implements server-side DTLS cookie generation and verification. Datagram security protocols are highly susceptible to a - variety of Denial-of-Service attacks. According to \l {https://tools.ietf.org/html/rfc6347#section-4.2.1}{RFC 6347, section 4.2.1}, + variety of Denial-of-Service attacks. According to \l {RFC 6347, section 4.2.1}, these are two of the more common types of attack: \list @@ -70,7 +35,7 @@ which can be quite large, thus flooding the victim machine with datagrams. \endlist - As a countermeasure to these attacks, \l {https://tools.ietf.org/html/rfc6347#section-4.2.1}{RFC 6347, section 4.2.1} + As a countermeasure to these attacks, \l {RFC 6347, section 4.2.1} proposes a stateless cookie technique that a server may deploy: \list @@ -118,7 +83,7 @@ \note The default secret is shared by all objects of the classes QDtlsClientVerifier and QDtls. Since this can impose security risks, RFC 6347 recommends to change - the server's secret frequently. Please see \l {https://tools.ietf.org/html/rfc6347}{RFC 6347, section 4.2.1} + the server's secret frequently. Please see \l {RFC 6347, section 4.2.1} for hints about possible server implementations. Cookie generator parameters can be set using the class QDtlsClientVerifier::GeneratorParameters and setCookieGeneratorParameters(): @@ -249,7 +214,7 @@ \warning It's recommended to call shutdown() before destroying the client's QDtls object if you are planning to re-use the same port number to connect to the server later. Otherwise, the server may drop incoming ClientHello messages, - see \l{https://tools.ietf.org/html/rfc6347#page-25}{RFC 6347, section 4.2.8} + see \l {RFC 6347, section 4.2.8} for more details and implementation hints. If the server does not use QDtlsClientVerifier, it \e must configure its @@ -337,72 +302,6 @@ QT_BEGIN_NAMESPACE -QSslConfiguration QDtlsBasePrivate::configuration() const -{ - auto copyPrivate = new QSslConfigurationPrivate(dtlsConfiguration); - copyPrivate->ref.storeRelaxed(0); // the QSslConfiguration constructor refs up - QSslConfiguration copy(copyPrivate); - copyPrivate->sessionCipher = sessionCipher; - copyPrivate->sessionProtocol = sessionProtocol; - - return copy; -} - -void QDtlsBasePrivate::setConfiguration(const QSslConfiguration &configuration) -{ - dtlsConfiguration.localCertificateChain = configuration.localCertificateChain(); - dtlsConfiguration.privateKey = configuration.privateKey(); - dtlsConfiguration.ciphers = configuration.ciphers(); - dtlsConfiguration.ellipticCurves = configuration.ellipticCurves(); - dtlsConfiguration.preSharedKeyIdentityHint = configuration.preSharedKeyIdentityHint(); - dtlsConfiguration.dhParams = configuration.diffieHellmanParameters(); - dtlsConfiguration.caCertificates = configuration.caCertificates(); - dtlsConfiguration.peerVerifyDepth = configuration.peerVerifyDepth(); - dtlsConfiguration.peerVerifyMode = configuration.peerVerifyMode(); - dtlsConfiguration.protocol = configuration.protocol(); - dtlsConfiguration.sslOptions = configuration.d->sslOptions; - dtlsConfiguration.sslSession = configuration.sessionTicket(); - dtlsConfiguration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint(); - dtlsConfiguration.nextAllowedProtocols = configuration.allowedNextProtocols(); - dtlsConfiguration.nextNegotiatedProtocol = configuration.nextNegotiatedProtocol(); - dtlsConfiguration.nextProtocolNegotiationStatus = configuration.nextProtocolNegotiationStatus(); - dtlsConfiguration.dtlsCookieEnabled = configuration.dtlsCookieVerificationEnabled(); - dtlsConfiguration.allowRootCertOnDemandLoading = configuration.d->allowRootCertOnDemandLoading; - dtlsConfiguration.backendConfig = configuration.backendConfiguration(); - - clearDtlsError(); -} - -bool QDtlsBasePrivate::setCookieGeneratorParameters(QCryptographicHash::Algorithm alg, - const QByteArray &key) -{ - if (!key.size()) { - setDtlsError(QDtlsError::InvalidInputParameters, - QDtls::tr("Invalid (empty) secret")); - return false; - } - - clearDtlsError(); - - hashAlgorithm = alg; - secret = key; - - return true; -} - -bool QDtlsBasePrivate::isDtlsProtocol(QSsl::SslProtocol protocol) -{ - switch (protocol) { - case QSsl::DtlsV1_0: - case QSsl::DtlsV1_0OrLater: - case QSsl::DtlsV1_2: - case QSsl::DtlsV1_2OrLater: - return true; - default: - return false; - } -} - static QString msgUnsupportedMulticastAddress() { return QDtls::tr("Multicast and broadcast addresses are not supported"); @@ -434,22 +333,37 @@ QDtlsClientVerifier::GeneratorParameters::GeneratorParameters(QCryptographicHash { } +QDtlsClientVerifierPrivate::QDtlsClientVerifierPrivate() +{ + const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse(); + if (!tlsBackend) { + qCWarning(lcSsl, "No TLS backend is available, cannot verify DTLS client"); + return; + } + backend.reset(tlsBackend->createDtlsCookieVerifier()); + if (!backend.get()) + qCWarning(lcSsl) << "The backend" << tlsBackend->backendName() << "does not support DTLS cookies"; +} + +QDtlsClientVerifierPrivate::~QDtlsClientVerifierPrivate() = default; + /*! Constructs a QDtlsClientVerifier object, \a parent is passed to QObject's constructor. */ QDtlsClientVerifier::QDtlsClientVerifier(QObject *parent) - : QObject(*new QDtlsClientVerifierOpenSSL, parent) + : QObject(*new QDtlsClientVerifierPrivate, parent) { Q_D(QDtlsClientVerifier); - d->mode = QSslSocket::SslServerMode; - // The default configuration suffices: verifier never does a full - // handshake and upon verifying a cookie in a client hello message, - // it reports success. - auto conf = QSslConfiguration::defaultDtlsConfiguration(); - conf.setPeerVerifyMode(QSslSocket::VerifyNone); - d->setConfiguration(conf); + if (auto *backend = d->backend.get()) { + // The default configuration suffices: verifier never does a full + // handshake and upon verifying a cookie in a client hello message, + // it reports success. + auto conf = QSslConfiguration::defaultDtlsConfiguration(); + conf.setPeerVerifyMode(QSslSocket::VerifyNone); + backend->setConfiguration(conf); + } } /*! @@ -473,8 +387,10 @@ QDtlsClientVerifier::~QDtlsClientVerifier() bool QDtlsClientVerifier::setCookieGeneratorParameters(const GeneratorParameters ¶ms) { Q_D(QDtlsClientVerifier); + if (auto *backend = d->backend.get()) + return backend->setCookieGeneratorParameters(params); - return d->setCookieGeneratorParameters(params.hash, params.secret); + return false; } /*! @@ -491,7 +407,10 @@ QDtlsClientVerifier::GeneratorParameters QDtlsClientVerifier::cookieGeneratorPar { Q_D(const QDtlsClientVerifier); - return {d->hashAlgorithm, d->secret}; + if (const auto *backend = d->backend.get()) + return backend->cookieGeneratorParameters(); + + return {}; } /*! @@ -514,19 +433,23 @@ bool QDtlsClientVerifier::verifyClient(QUdpSocket *socket, const QByteArray &dgr { Q_D(QDtlsClientVerifier); + auto *backend = d->backend.get(); + if (!backend) + return false; + if (!socket || address.isNull() || !dgram.size()) { - d->setDtlsError(QDtlsError::InvalidInputParameters, - tr("A valid UDP socket, non-empty datagram, valid address/port were expected")); + backend->setDtlsError(QDtlsError::InvalidInputParameters, + tr("A valid UDP socket, non-empty datagram, and valid address/port were expected")); return false; } if (address.isBroadcast() || address.isMulticast()) { - d->setDtlsError(QDtlsError::InvalidInputParameters, - msgUnsupportedMulticastAddress()); + backend->setDtlsError(QDtlsError::InvalidInputParameters, + msgUnsupportedMulticastAddress()); return false; } - return d->verifyClient(socket, dgram, address, port); + return backend->verifyClient(socket, dgram, address, port); } /*! @@ -539,7 +462,10 @@ QByteArray QDtlsClientVerifier::verifiedHello() const { Q_D(const QDtlsClientVerifier); - return d->verifiedClientHello; + if (const auto *backend = d->backend.get()) + return backend->verifiedHello(); + + return {}; } /*! @@ -551,7 +477,10 @@ QDtlsError QDtlsClientVerifier::dtlsError() const { Q_D(const QDtlsClientVerifier); - return d->errorCode; + if (const auto *backend = d->backend.get()) + return backend->error(); + + return QDtlsError::TlsInitializationError; } /*! @@ -561,11 +490,17 @@ QDtlsError QDtlsClientVerifier::dtlsError() const */ QString QDtlsClientVerifier::dtlsErrorString() const { - Q_D(const QDtlsBase); + Q_D(const QDtlsClientVerifier); + + if (const auto *backend = d->backend.get()) + return backend->errorString(); - return d->errorDescription; + return QStringLiteral("No TLS backend is available, no client verification"); } +QDtlsPrivate::QDtlsPrivate() = default; +QDtlsPrivate::~QDtlsPrivate() = default; + /*! Creates a QDtls object, \a parent is passed to the QObject constructor. \a mode is QSslSocket::SslServerMode for a server-side DTLS connection or @@ -574,11 +509,19 @@ QString QDtlsClientVerifier::dtlsErrorString() const \sa sslMode(), QSslSocket::SslMode */ QDtls::QDtls(QSslSocket::SslMode mode, QObject *parent) - : QObject(*new QDtlsPrivateOpenSSL, parent) + : QObject(*new QDtlsPrivate, parent) { Q_D(QDtls); - - d->mode = mode; + const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse(); + if (!tlsBackend) { + qCWarning(lcSsl, "No TLS backend found, QDtls is unsupported"); + return; + } + d->backend.reset(tlsBackend->createDtlsCryptograph(this, mode)); + if (!d->backend.get()) { + qCWarning(lcSsl) << "TLS backend" << tlsBackend->backendName() + << "does not support the protocol DTLS"; + } setDtlsConfiguration(QSslConfiguration::defaultDtlsConfiguration()); } @@ -601,29 +544,30 @@ bool QDtls::setPeer(const QHostAddress &address, quint16 port, { Q_D(QDtls); - if (d->handshakeState != HandshakeNotStarted) { - d->setDtlsError(QDtlsError::InvalidOperation, - tr("Cannot set peer after handshake started")); + auto *backend = d->backend.get(); + if (!backend) + return false; + + if (backend->state() != HandshakeNotStarted) { + backend->setDtlsError(QDtlsError::InvalidOperation, + tr("Cannot set peer after handshake started")); return false; } if (address.isNull()) { - d->setDtlsError(QDtlsError::InvalidInputParameters, - tr("Invalid address")); + backend->setDtlsError(QDtlsError::InvalidInputParameters, + tr("Invalid address")); return false; } if (address.isBroadcast() || address.isMulticast()) { - d->setDtlsError(QDtlsError::InvalidInputParameters, - msgUnsupportedMulticastAddress()); + backend->setDtlsError(QDtlsError::InvalidInputParameters, + msgUnsupportedMulticastAddress()); return false; } - d->clearDtlsError(); - - d->remoteAddress = address; - d->remotePort = port; - d->peerVerificationName = verificationName; + backend->clearDtlsError(); + backend->setPeer(address, port, verificationName); return true; } @@ -640,14 +584,18 @@ bool QDtls::setPeerVerificationName(const QString &name) { Q_D(QDtls); - if (d->handshakeState != HandshakeNotStarted) { - d->setDtlsError(QDtlsError::InvalidOperation, + auto *backend = d->backend.get(); + if (!backend) + return false; + + if (backend->state() != HandshakeNotStarted) { + backend->setDtlsError(QDtlsError::InvalidOperation, tr("Cannot set verification name after handshake started")); return false; } - d->clearDtlsError(); - d->peerVerificationName = name; + backend->clearDtlsError(); + backend->setPeerVerificationName(name); return true; } @@ -661,7 +609,10 @@ QHostAddress QDtls::peerAddress() const { Q_D(const QDtls); - return d->remoteAddress; + if (const auto *backend = d->backend.get()) + return backend->peerAddress(); + + return {}; } /*! @@ -671,9 +622,12 @@ QHostAddress QDtls::peerAddress() const */ quint16 QDtls::peerPort() const { - Q_D(const QDtlsBase); + Q_D(const QDtls); + + if (const auto *backend = d->backend.get()) + return backend->peerPort(); - return d->remotePort; + return 0; } /*! @@ -686,7 +640,10 @@ QString QDtls::peerVerificationName() const { Q_D(const QDtls); - return d->peerVerificationName; + if (const auto *backend = d->backend.get()) + return backend->peerVerificationName(); + + return {}; } /*! @@ -699,7 +656,10 @@ QSslSocket::SslMode QDtls::sslMode() const { Q_D(const QDtls); - return d->mode; + if (const auto *backend = d->backend.get()) + return backend->cryptographMode(); + + return QSslSocket::UnencryptedMode; } /*! @@ -712,7 +672,8 @@ void QDtls::setMtuHint(quint16 mtuHint) { Q_D(QDtls); - d->mtuHint = mtuHint; + if (auto *backend = d->backend.get()) + backend->setDtlsMtuHint(mtuHint); } /*! @@ -724,7 +685,10 @@ quint16 QDtls::mtuHint() const { Q_D(const QDtls); - return d->mtuHint; + if (const auto *backend = d->backend.get()) + return backend->dtlsMtuHint(); + + return 0; } /*! @@ -741,7 +705,10 @@ bool QDtls::setCookieGeneratorParameters(const GeneratorParameters ¶ms) { Q_D(QDtls); - return d->setCookieGeneratorParameters(params.hash, params.secret); + if (auto *backend = d->backend.get()) + backend->setCookieGeneratorParameters(params); + + return false; } /*! @@ -759,7 +726,10 @@ QDtls::GeneratorParameters QDtls::cookieGeneratorParameters() const { Q_D(const QDtls); - return {d->hashAlgorithm, d->secret}; + if (const auto *backend = d->backend.get()) + return backend->cookieGeneratorParameters(); + + return {}; } /*! @@ -774,13 +744,17 @@ bool QDtls::setDtlsConfiguration(const QSslConfiguration &configuration) { Q_D(QDtls); - if (d->handshakeState != HandshakeNotStarted) { - d->setDtlsError(QDtlsError::InvalidOperation, - tr("Cannot set configuration after handshake started")); + auto *backend = d->backend.get(); + if (!backend) + return false; + + if (backend->state() != HandshakeNotStarted) { + backend->setDtlsError(QDtlsError::InvalidOperation, + tr("Cannot set configuration after handshake started")); return false; } - d->setConfiguration(configuration); + backend->setConfiguration(configuration); return true; } @@ -793,8 +767,10 @@ bool QDtls::setDtlsConfiguration(const QSslConfiguration &configuration) QSslConfiguration QDtls::dtlsConfiguration() const { Q_D(const QDtls); + if (const auto *backend = d->backend.get()) + return backend->configuration(); - return d->configuration(); + return {}; } /*! @@ -806,7 +782,10 @@ QDtls::HandshakeState QDtls::handshakeState()const { Q_D(const QDtls); - return d->handshakeState; + if (const auto *backend = d->backend.get()) + return backend->state(); + + return QDtls::HandshakeNotStarted; } /*! @@ -832,13 +811,17 @@ bool QDtls::doHandshake(QUdpSocket *socket, const QByteArray &dgram) { Q_D(QDtls); - if (d->handshakeState == HandshakeNotStarted) + auto *backend = d->backend.get(); + if (!backend) + return false; + + if (backend->state() == HandshakeNotStarted) return startHandshake(socket, dgram); - else if (d->handshakeState == HandshakeInProgress) + else if (backend->state() == HandshakeInProgress) return continueHandshake(socket, dgram); - d->setDtlsError(QDtlsError::InvalidOperation, - tr("Cannot start/continue handshake, invalid handshake state")); + backend->setDtlsError(QDtlsError::InvalidOperation, + tr("Cannot start/continue handshake, invalid handshake state")); return false; } @@ -849,34 +832,38 @@ bool QDtls::startHandshake(QUdpSocket *socket, const QByteArray &datagram) { Q_D(QDtls); + auto *backend = d->backend.get(); + if (!backend) + return false; + if (!socket) { - d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket")); + backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket")); return false; } - if (d->remoteAddress.isNull()) { - d->setDtlsError(QDtlsError::InvalidOperation, - tr("To start a handshake you must set peer's address and port first")); + if (backend->peerAddress().isNull()) { + backend->setDtlsError(QDtlsError::InvalidOperation, + tr("To start a handshake you must set peer's address and port first")); return false; } if (sslMode() == QSslSocket::SslServerMode && !datagram.size()) { - d->setDtlsError(QDtlsError::InvalidInputParameters, - tr("To start a handshake, DTLS server requires non-empty datagram (client hello)")); + backend->setDtlsError(QDtlsError::InvalidInputParameters, + tr("To start a handshake, DTLS server requires non-empty datagram (client hello)")); return false; } - if (d->handshakeState != HandshakeNotStarted) { - d->setDtlsError(QDtlsError::InvalidOperation, - tr("Cannot start handshake, already done/in progress")); + if (backend->state() != HandshakeNotStarted) { + backend->setDtlsError(QDtlsError::InvalidOperation, + tr("Cannot start handshake, already done/in progress")); return false; } - return d->startHandshake(socket, datagram); + return backend->startHandshake(socket, datagram); } /*! - If a timeout occures during the handshake, the handshakeTimeout() signal + If a timeout occurs during the handshake, the handshakeTimeout() signal is emitted. The application must call handleTimeout() to retransmit handshake messages; handleTimeout() returns \c true if a timeout has occurred, false otherwise. \a socket must be a valid pointer. @@ -887,12 +874,16 @@ bool QDtls::handleTimeout(QUdpSocket *socket) { Q_D(QDtls); + auto *backend = d->backend.get(); + if (!backend) + return false; + if (!socket) { - d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket")); + backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket")); return false; } - return d->handleTimeout(socket); + return backend->handleTimeout(socket); } /*! @@ -902,19 +893,23 @@ bool QDtls::continueHandshake(QUdpSocket *socket, const QByteArray &datagram) { Q_D(QDtls); + auto *backend = d->backend.get(); + if (!backend) + return false; + if (!socket || !datagram.size()) { - d->setDtlsError(QDtlsError::InvalidInputParameters, - tr("A valid QUdpSocket and non-empty datagram are needed to continue the handshake")); + backend->setDtlsError(QDtlsError::InvalidInputParameters, + tr("A valid QUdpSocket and non-empty datagram are needed to continue the handshake")); return false; } - if (d->handshakeState != HandshakeInProgress) { - d->setDtlsError(QDtlsError::InvalidOperation, - tr("Cannot continue handshake, not in InProgress state")); + if (backend->state() != HandshakeInProgress) { + backend->setDtlsError(QDtlsError::InvalidOperation, + tr("Cannot continue handshake, not in InProgress state")); return false; } - return d->continueHandshake(socket, datagram); + return backend->continueHandshake(socket, datagram); } /*! @@ -929,18 +924,22 @@ bool QDtls::resumeHandshake(QUdpSocket *socket) { Q_D(QDtls); + auto *backend = d->backend.get(); + if (!backend) + return false; + if (!socket) { - d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket")); + backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket")); return false; } - if (d->handshakeState != PeerVerificationFailed) { - d->setDtlsError(QDtlsError::InvalidOperation, - tr("Cannot resume, not in VerificationError state")); + if (backend->state() != PeerVerificationFailed) { + backend->setDtlsError(QDtlsError::InvalidOperation, + tr("Cannot resume, not in VerificationError state")); return false; } - return d->resumeHandshake(socket); + return backend->resumeHandshake(socket); } /*! @@ -953,18 +952,22 @@ bool QDtls::abortHandshake(QUdpSocket *socket) { Q_D(QDtls); + auto *backend = d->backend.get(); + if (!backend) + return false; + if (!socket) { - d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket")); + backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket")); return false; } - if (d->handshakeState != PeerVerificationFailed && d->handshakeState != HandshakeInProgress) { - d->setDtlsError(QDtlsError::InvalidOperation, - tr("No handshake in progress, nothing to abort")); + if (backend->state() != PeerVerificationFailed && backend->state() != HandshakeInProgress) { + backend->setDtlsError(QDtlsError::InvalidOperation, + tr("No handshake in progress, nothing to abort")); return false; } - d->abortHandshake(socket); + backend->abortHandshake(socket); return true; } @@ -979,19 +982,23 @@ bool QDtls::shutdown(QUdpSocket *socket) { Q_D(QDtls); + auto *backend = d->backend.get(); + if (!backend) + return false; + if (!socket) { - d->setDtlsError(QDtlsError::InvalidInputParameters, - tr("Invalid (nullptr) socket")); + backend->setDtlsError(QDtlsError::InvalidInputParameters, + tr("Invalid (nullptr) socket")); return false; } - if (!d->connectionEncrypted) { - d->setDtlsError(QDtlsError::InvalidOperation, - tr("Cannot send shutdown alert, not encrypted")); + if (!backend->isConnectionEncrypted()) { + backend->setDtlsError(QDtlsError::InvalidOperation, + tr("Cannot send shutdown alert, not encrypted")); return false; } - d->sendShutdownAlert(socket); + backend->sendShutdownAlert(socket); return true; } @@ -1004,7 +1011,11 @@ bool QDtls::isConnectionEncrypted() const { Q_D(const QDtls); - return d->connectionEncrypted; + + if (const auto *backend = d->backend.get()) + return backend->isConnectionEncrypted(); + + return false; } /*! @@ -1023,7 +1034,10 @@ QSslCipher QDtls::sessionCipher() const { Q_D(const QDtls); - return d->sessionCipher; + if (const auto *backend = d->backend.get()) + return backend->dtlsSessionCipher(); + + return {}; } /*! @@ -1040,7 +1054,10 @@ QSsl::SslProtocol QDtls::sessionProtocol() const { Q_D(const QDtls); - return d->sessionProtocol; + if (const auto *backend = d->backend.get()) + return backend->dtlsSessionProtocol(); + + return QSsl::UnknownProtocol; } /*! @@ -1055,18 +1072,22 @@ qint64 QDtls::writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram { Q_D(QDtls); + auto *backend = d->backend.get(); + if (!backend) + return -1; + if (!socket) { - d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket")); + backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket")); return -1; } if (!isConnectionEncrypted()) { - d->setDtlsError(QDtlsError::InvalidOperation, - tr("Cannot write a datagram, not in encrypted state")); + backend->setDtlsError(QDtlsError::InvalidOperation, + tr("Cannot write a datagram, not in encrypted state")); return -1; } - return d->writeDatagramEncrypted(socket, dgram); + return backend->writeDatagramEncrypted(socket, dgram); } /*! @@ -1079,21 +1100,25 @@ QByteArray QDtls::decryptDatagram(QUdpSocket *socket, const QByteArray &dgram) { Q_D(QDtls); + auto *backend = d->backend.get(); + if (!backend) + return {}; + if (!socket) { - d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket")); + backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket")); return {}; } if (!isConnectionEncrypted()) { - d->setDtlsError(QDtlsError::InvalidOperation, - tr("Cannot read a datagram, not in encrypted state")); + backend->setDtlsError(QDtlsError::InvalidOperation, + tr("Cannot read a datagram, not in encrypted state")); return {}; } if (!dgram.size()) return {}; - return d->decryptDatagram(socket, dgram); + return backend->decryptDatagram(socket, dgram); } /*! @@ -1105,7 +1130,10 @@ QDtlsError QDtls::dtlsError() const { Q_D(const QDtls); - return d->errorCode; + if (const auto *backend = d->backend.get()) + return backend->error(); + + return QDtlsError::NoError; } /*! @@ -1118,7 +1146,10 @@ QString QDtls::dtlsErrorString() const { Q_D(const QDtls); - return d->errorDescription; + if (const auto *backend = d->backend.get()) + return backend->errorString(); + + return {}; } /*! @@ -1131,7 +1162,11 @@ QList<QSslError> QDtls::peerVerificationErrors() const { Q_D(const QDtls); - return d->tlsErrors; + if (const auto *backend = d->backend.get()) + return backend->peerVerificationErrors(); + + //return d->tlsErrors; + return {}; } /*! @@ -1156,7 +1191,10 @@ void QDtls::ignoreVerificationErrors(const QList<QSslError> &errorsToIgnore) { Q_D(QDtls); - d->tlsErrorsToIgnore = errorsToIgnore; + if (auto *backend = d->backend.get()) + backend->ignoreVerificationErrors(errorsToIgnore); } QT_END_NAMESPACE + +#include "moc_qdtls.cpp" |