Convert QDtls classes to the new plugin-based design

Essentially, the same code re-shuffled and placed behind
the new interfaces.

Fixes: QTBUG-91174
Task-number: QTBUG-65922
Change-Id: I8f14697f10713f9738c5c7805aed0150c084850c
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
(cherry picked from commit 6c835796c8ea2590008900ffb5f4bf0d902ee73d)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Timur Pocheptsov 2021-02-25 11:30:21 +01:00 committed by Qt Cherry-pick Bot
parent fe9d7bf759
commit 7c1aa0c48c
11 changed files with 749 additions and 278 deletions

View File

@ -357,6 +357,7 @@ qt_internal_extend_target(Network CONDITION QT_FEATURE_securetransport AND QT_FE
qt_internal_extend_target(Network CONDITION QT_FEATURE_dtls AND QT_FEATURE_ssl
SOURCES
ssl/qdtls.cpp ssl/qdtls.h ssl/qdtls_p.h
ssl/qdtls_base.cpp ssl/qdtls_base_p.h
)
qt_internal_extend_target(Network CONDITION QT_FEATURE_openssl AND QT_FEATURE_ssl

View File

@ -38,8 +38,9 @@
****************************************************************************/
#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"
@ -337,72 +338,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 +369,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 +423,10 @@ QDtlsClientVerifier::~QDtlsClientVerifier()
bool QDtlsClientVerifier::setCookieGeneratorParameters(const GeneratorParameters &params)
{
Q_D(QDtlsClientVerifier);
if (auto *backend = d->backend.get())
return backend->setCookieGeneratorParameters(params);
return d->setCookieGeneratorParameters(params.hash, params.secret);
return false;
}
/*!
@ -491,7 +443,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 +469,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 +498,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 +513,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 +526,17 @@ QDtlsError QDtlsClientVerifier::dtlsError() const
*/
QString QDtlsClientVerifier::dtlsErrorString() const
{
Q_D(const QDtlsBase);
Q_D(const QDtlsClientVerifier);
return d->errorDescription;
if (const auto *backend = d->backend.get())
return backend->errorString();
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 +545,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 +580,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 +620,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 +645,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 +658,12 @@ QHostAddress QDtls::peerAddress() const
*/
quint16 QDtls::peerPort() const
{
Q_D(const QDtlsBase);
Q_D(const QDtls);
return d->remotePort;
if (const auto *backend = d->backend.get())
return backend->peerPort();
return 0;
}
/*!
@ -686,7 +676,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 +692,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 +708,8 @@ void QDtls::setMtuHint(quint16 mtuHint)
{
Q_D(QDtls);
d->mtuHint = mtuHint;
if (auto *backend = d->backend.get())
backend->setDtlsMtuHint(mtuHint);
}
/*!
@ -724,7 +721,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 +741,10 @@ bool QDtls::setCookieGeneratorParameters(const GeneratorParameters &params)
{
Q_D(QDtls);
return d->setCookieGeneratorParameters(params.hash, params.secret);
if (auto *backend = d->backend.get())
backend->setCookieGeneratorParameters(params);
return false;
}
/*!
@ -759,7 +762,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 +780,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 +803,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 +818,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 +847,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,30 +868,34 @@ 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);
}
/*!
@ -887,12 +910,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 +929,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 +960,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 +988,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 +1018,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 +1047,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 +1070,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 +1090,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 +1108,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 +1136,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 +1166,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 +1182,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 +1198,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 +1227,8 @@ 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

View File

@ -0,0 +1,137 @@
/****************************************************************************
**
** Copyright (C) 2021 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$
**
****************************************************************************/
#include "qdtls_base_p.h"
QT_BEGIN_NAMESPACE
void QDtlsBasePrivate::setDtlsError(QDtlsError code, const QString &description)
{
errorCode = code;
errorDescription = description;
}
QDtlsError QDtlsBasePrivate::error() const
{
return errorCode;
}
QString QDtlsBasePrivate::errorString() const
{
return errorDescription;
}
void QDtlsBasePrivate::clearDtlsError()
{
errorCode = QDtlsError::NoError;
errorDescription.clear();
}
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(const GenParams &params)
{
if (!params.secret.size()) {
setDtlsError(QDtlsError::InvalidInputParameters,
QDtls::tr("Invalid (empty) secret"));
return false;
}
clearDtlsError();
hashAlgorithm = params.hash;
secret = params.secret;
return true;
}
QDtlsClientVerifier::GeneratorParameters
QDtlsBasePrivate::cookieGeneratorParameters() const
{
return {hashAlgorithm, secret};
}
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;
}
}
QT_END_NAMESPACE

View File

@ -0,0 +1,115 @@
/****************************************************************************
**
** Copyright (C) 2021 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 QDTLS_BASE_P_H
#define QDTLS_BASE_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.
//
#include <private/qtnetworkglobal_p.h>
QT_REQUIRE_CONFIG(dtls);
#include "qsslconfiguration_p.h"
#include "qtlsbackend_p.h"
#include "qsslcipher.h"
#include "qsslsocket.h"
#include "qssl.h"
#include <QtNetwork/qhostaddress.h>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qglobal.h>
#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
// This class exists to re-implement the shared error/cookie handling
// for both QDtls and QDtlsClientVerifier classes. Use it if/when
// you need it. Backend neutral.
class QDtlsBasePrivate : virtual public QSsl::DtlsBase
{
public:
QDtlsBasePrivate(QSslSocket::SslMode m, const QByteArray &s) : mode(m), secret(s) {}
void setDtlsError(QDtlsError code, const QString &description) override;
QDtlsError error() const override;
QString errorString() const override;
void clearDtlsError() override;
void setConfiguration(const QSslConfiguration &configuration) override;
QSslConfiguration configuration() const override;
bool setCookieGeneratorParameters(const GenParams &) override;
GenParams cookieGeneratorParameters() const override;
static bool isDtlsProtocol(QSsl::SslProtocol protocol);
QHostAddress remoteAddress;
quint16 remotePort = 0;
quint16 mtuHint = 0;
QDtlsError errorCode = QDtlsError::NoError;
QString errorDescription;
QSslConfigurationPrivate dtlsConfiguration;
QSslSocket::SslMode mode = QSslSocket::SslClientMode;
QSslCipher sessionCipher;
QSsl::SslProtocol sessionProtocol = QSsl::UnknownProtocol;
QString peerVfyName;
QByteArray secret;
#ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha1;
#else
QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha256;
#endif
};
QT_END_NAMESPACE
#endif // QDTLS_BASE_P_H

View File

@ -783,8 +783,8 @@ void DtlsState::setLinkMtu(QDtlsBasePrivate *dtlsBase)
} // namespace dtlsopenssl
QDtlsClientVerifierOpenSSL::QDtlsClientVerifierOpenSSL()
: QDtlsBasePrivate(QSslSocket::SslServerMode, dtlsutil::fallbackSecret())
{
secret = dtlsutil::fallbackSecret();
}
bool QDtlsClientVerifierOpenSSL::verifyClient(QUdpSocket *socket, const QByteArray &dgram,
@ -827,6 +827,11 @@ bool QDtlsClientVerifierOpenSSL::verifyClient(QUdpSocket *socket, const QByteArr
return false;
}
QByteArray QDtlsClientVerifierOpenSSL::verifiedHello() const
{
return verifiedClientHello;
}
void QDtlsPrivateOpenSSL::TimeoutHandler::start(int hintMs)
{
Q_ASSERT(timerId == -1);
@ -861,12 +866,66 @@ void QDtlsPrivateOpenSSL::TimeoutHandler::timerEvent(QTimerEvent *event)
dtlsConnection->reportTimeout();
}
QDtlsPrivateOpenSSL::QDtlsPrivateOpenSSL()
QDtlsPrivateOpenSSL::QDtlsPrivateOpenSSL(QDtls *qObject, QSslSocket::SslMode side)
: QDtlsBasePrivate(side, dtlsutil::fallbackSecret()), q(qObject)
{
secret = dtlsutil::fallbackSecret();
Q_ASSERT(qObject);
dtls.dtlsPrivate = this;
}
QSslSocket::SslMode QDtlsPrivateOpenSSL::cryptographMode() const
{
return mode;
}
void QDtlsPrivateOpenSSL::setPeer(const QHostAddress &addr, quint16 port, const QString &name)
{
remoteAddress = addr;
remotePort = port;
peerVfyName = name;
}
QHostAddress QDtlsPrivateOpenSSL::peerAddress() const
{
return remoteAddress;
}
quint16 QDtlsPrivateOpenSSL::peerPort() const
{
return remotePort;
}
void QDtlsPrivateOpenSSL::setPeerVerificationName(const QString &name)
{
peerVfyName = name;
}
QString QDtlsPrivateOpenSSL::peerVerificationName() const
{
return peerVfyName;
}
void QDtlsPrivateOpenSSL::setDtlsMtuHint(quint16 mtu)
{
mtuHint = mtu;
}
quint16 QDtlsPrivateOpenSSL::dtlsMtuHint() const
{
return mtuHint;
}
QDtls::HandshakeState QDtlsPrivateOpenSSL::state() const
{
return handshakeState;
}
bool QDtlsPrivateOpenSSL::isConnectionEncrypted() const
{
return connectionEncrypted;
}
bool QDtlsPrivateOpenSSL::startHandshake(QUdpSocket *socket, const QByteArray &dgram)
{
Q_ASSERT(socket);
@ -1070,6 +1129,26 @@ void QDtlsPrivateOpenSSL::sendShutdownAlert(QUdpSocket *socket)
resetDtls();
}
QList<QSslError> QDtlsPrivateOpenSSL::peerVerificationErrors() const
{
return tlsErrors;
}
void QDtlsPrivateOpenSSL::ignoreVerificationErrors(const QList<QSslError> &errorsToIgnore)
{
tlsErrorsToIgnore = errorsToIgnore;
}
QSslCipher QDtlsPrivateOpenSSL::dtlsSessionCipher() const
{
return sessionCipher;
}
QSsl::SslProtocol QDtlsPrivateOpenSSL::dtlsSessionProtocol() const
{
return sessionProtocol;
}
qint64 QDtlsPrivateOpenSSL::writeDatagramEncrypted(QUdpSocket *socket,
const QByteArray &dgram)
{
@ -1191,9 +1270,6 @@ unsigned QDtlsPrivateOpenSSL::pskClientCallback(const char *hint, char *identity
{
// The code below is taken (with some modifications) from qsslsocket_openssl
// - alas, we cannot simply re-use it, it's in QSslSocketPrivate.
Q_Q(QDtls);
{
QSslPreSharedKeyAuthenticator authenticator;
// Fill in some read-only fields (for client code)
@ -1235,8 +1311,6 @@ unsigned QDtlsPrivateOpenSSL::pskClientCallback(const char *hint, char *identity
unsigned QDtlsPrivateOpenSSL::pskServerCallback(const char *identity, unsigned char *psk,
unsigned max_psk_len)
{
Q_Q(QDtls);
{
QSslPreSharedKeyAuthenticator authenticator;
// Fill in some read-only fields (for the user)
@ -1287,7 +1361,7 @@ bool QDtlsPrivateOpenSSL::verifyPeer()
// is empty, we call QAbstractSocket::peerName(), which returns
// either peerName (can be set by setPeerName) or host name
// (can be set as a result of connectToHost).
QString name = peerVerificationName;
QString name = peerVfyName;
if (name.isEmpty()) {
Q_ASSERT(dtls.udpSocket);
name = dtls.udpSocket->peerName();
@ -1366,8 +1440,6 @@ void QDtlsPrivateOpenSSL::fetchNegotiatedParameters()
void QDtlsPrivateOpenSSL::reportTimeout()
{
Q_Q(QDtls);
emit q->handshakeTimeout();
}

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@ -46,6 +46,8 @@
#include <openssl/ossl_typ.h>
#include "qtlsbackend_openssl_p.h"
#include "qdtls_base_p.h"
#include "qdtls_p.h"
#include <private/qsslcontext_openssl_p.h>
@ -55,7 +57,6 @@
#include <QtNetwork/qhostaddress.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qlist.h>
#include <QtCore/qsharedpointer.h>
@ -76,6 +77,7 @@ QT_REQUIRE_CONFIG(dtls);
QT_BEGIN_NAMESPACE
class QDtlsPrivateOpenSSL;
class QDtlsBasePrivate;
class QUdpSocket;
namespace dtlsopenssl
@ -131,23 +133,40 @@ private:
} // namespace dtlsopenssl
class QDtlsClientVerifierOpenSSL : public QDtlsClientVerifierPrivate
class QDtlsClientVerifierOpenSSL : public QSsl::DtlsCookieVerifier, public QDtlsBasePrivate
{
public:
QDtlsClientVerifierOpenSSL();
bool verifyClient(QUdpSocket *socket, const QByteArray &dgram,
const QHostAddress &address, quint16 port) override;
QByteArray verifiedHello() const override;
private:
dtlsopenssl::DtlsState dtls;
QByteArray verifiedClientHello;
};
class QDtlsPrivateOpenSSL : public QDtlsPrivate
class QDtlsPrivateOpenSSL : public QSsl::DtlsCryptograph, public QDtlsBasePrivate
{
public:
QDtlsPrivateOpenSSL();
QDtlsPrivateOpenSSL(QDtls *qObject, QSslSocket::SslMode mode);
private:
QSslSocket::SslMode cryptographMode() const override;
void setPeer(const QHostAddress &addr, quint16 port, const QString &name) override;
QHostAddress peerAddress() const override;
quint16 peerPort() const override;
void setPeerVerificationName(const QString &name) override;
QString peerVerificationName() const override;
virtual void setDtlsMtuHint(quint16 mtu) override;
virtual quint16 dtlsMtuHint() const override;
virtual QDtls::HandshakeState state() const override;
virtual bool isConnectionEncrypted() const override;
bool startHandshake(QUdpSocket *socket, const QByteArray &datagram) override;
bool continueHandshake(QUdpSocket *socket, const QByteArray &datagram) override;
@ -156,9 +175,17 @@ public:
bool handleTimeout(QUdpSocket *socket) override;
void sendShutdownAlert(QUdpSocket *socket) override;
QList<QSslError> peerVerificationErrors() const override;
void ignoreVerificationErrors(const QList<QSslError> &errorsToIgnore) override;
QSslCipher dtlsSessionCipher() const override;
QSsl::SslProtocol dtlsSessionProtocol() const override;
qint64 writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &datagram) override;
QByteArray decryptDatagram(QUdpSocket *socket, const QByteArray &tlsdgram) override;
public:
unsigned pskClientCallback(const char *hint, char *identity, unsigned max_identity_len,
unsigned char *psk, unsigned max_psk_len);
unsigned pskServerCallback(const char *identity, unsigned char *psk,
@ -195,14 +222,18 @@ private:
QDtlsPrivateOpenSSL *dtlsConnection = nullptr;
};
QDtls *q = nullptr;
QDtls::HandshakeState handshakeState = QDtls::HandshakeNotStarted;
QList<QSslError> tlsErrors;
QList<QSslError> tlsErrorsToIgnore;
bool connectionEncrypted = false;
// We will initialize it 'lazily', just in case somebody wants to move
// QDtls to another thread.
QScopedPointer<TimeoutHandler> timeoutHandler;
bool connectionWasShutdown = false;
QSslPreSharedKeyAuthenticator pskAuthenticator;
QByteArray identityHint;
Q_DECLARE_PUBLIC(QDtls)
};

View File

@ -42,21 +42,9 @@
#include <private/qtnetworkglobal_p.h>
#include "qdtls.h"
#include <private/qsslconfiguration_p.h>
#include <private/qobject_p.h>
#include <QtNetwork/qabstractsocket.h>
#include <QtNetwork/qhostaddress.h>
#include <QtNetwork/qsslsocket.h>
#include <QtNetwork/qsslcipher.h>
#include <QtNetwork/qssl.h>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qstring.h>
#include "qtlsbackend_p.h"
#include <QtCore/private/qobject_p.h>
//
// W A R N I N G
// -------------
@ -74,80 +62,20 @@ QT_BEGIN_NAMESPACE
class QHostAddress;
class QDtlsBasePrivate : public QObjectPrivate
class QDtlsClientVerifierPrivate : public QObjectPrivate
{
public:
void setDtlsError(QDtlsError code, const QString &description)
{
errorCode = code;
errorDescription = description;
}
void clearDtlsError()
{
errorCode = QDtlsError::NoError;
errorDescription.clear();
}
void setConfiguration(const QSslConfiguration &configuration);
QSslConfiguration configuration() const;
bool setCookieGeneratorParameters(QCryptographicHash::Algorithm alg,
const QByteArray &secret);
static bool isDtlsProtocol(QSsl::SslProtocol protocol);
QHostAddress remoteAddress;
quint16 remotePort = 0;
quint16 mtuHint = 0;
QDtlsError errorCode = QDtlsError::NoError;
QString errorDescription;
QSslConfigurationPrivate dtlsConfiguration;
QSslSocket::SslMode mode = QSslSocket::SslClientMode;
QSslCipher sessionCipher;
QSsl::SslProtocol sessionProtocol = QSsl::UnknownProtocol;
QString peerVerificationName;
QByteArray secret;
#ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha1;
#else
QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha256;
#endif
QDtlsClientVerifierPrivate();
~QDtlsClientVerifierPrivate();
std::unique_ptr<QSsl::DtlsCookieVerifier> backend;
};
class QDtlsClientVerifierPrivate : public QDtlsBasePrivate
class QDtlsPrivate : public QObjectPrivate
{
public:
QByteArray verifiedClientHello;
virtual bool verifyClient(QUdpSocket *socket, const QByteArray &dgram,
const QHostAddress &address, quint16 port) = 0;
};
class QDtlsPrivate : public QDtlsBasePrivate
{
public:
virtual bool startHandshake(QUdpSocket *socket, const QByteArray &dgram) = 0;
virtual bool handleTimeout(QUdpSocket *socket) = 0;
virtual bool continueHandshake(QUdpSocket *socket, const QByteArray &dgram) = 0;
virtual bool resumeHandshake(QUdpSocket *socket) = 0;
virtual void abortHandshake(QUdpSocket *socket) = 0;
virtual void sendShutdownAlert(QUdpSocket *socket) = 0;
virtual qint64 writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram) = 0;
virtual QByteArray decryptDatagram(QUdpSocket *socket, const QByteArray &dgram) = 0;
QDtls::HandshakeState handshakeState = QDtls::HandshakeNotStarted;
QList<QSslError> tlsErrors;
QList<QSslError> tlsErrorsToIgnore;
bool connectionEncrypted = false;
QDtlsPrivate();
~QDtlsPrivate();
std::unique_ptr<QSsl::DtlsCryptograph> backend;
};
QT_END_NAMESPACE

View File

@ -199,6 +199,10 @@ TlsKey *X509Certificate::publicKey() const
return nullptr;
}
#if QT_CONFIG(dtls)
DtlsBase::~DtlsBase() = default;
#endif // QT_CONFIG(dtls)
} // namespace QSsl
const QString QTlsBackend::builtinBackendNames[] = {
@ -250,8 +254,10 @@ QSsl::TlsCryptograph *QTlsBackend::createTlsCryptograph() const
return nullptr;
}
QSsl::DtlsCryptograph *QTlsBackend::createDtlsCryptograph() const
QSsl::DtlsCryptograph *QTlsBackend::createDtlsCryptograph(QDtls *qObject, int mode) const
{
Q_UNUSED(qObject);
Q_UNUSED(mode);
REPORT_MISSING_SUPPORT("does not support QDtls");
return nullptr;
}

View File

@ -41,6 +41,10 @@
#include "qtlskey_openssl_p.h"
#include "qx509_openssl_p.h"
#if QT_CONFIG(dtls)
#include "qdtls_openssl_p.h"
#endif // QT_CONFIG(dtls)
// TLSTODO: Later, this code (ensure initialised, etc.)
// must move from the socket to backend.
#include "qsslsocket_p.h"
@ -163,6 +167,28 @@ QSsl::X509Certificate *QTlsBackendOpenSSL::createCertificate() const
return new QSsl::X509CertificateOpenSSL;
}
QSsl::DtlsCookieVerifier *QTlsBackendOpenSSL::createDtlsCookieVerifier() const
{
#if QT_CONFIG(dtls)
return new QDtlsClientVerifierOpenSSL;
#else
qCWarning(lcTlsBackend, "Feature 'dtls' is disabled, cannot verify DTLS cookies");
return nullptr;
#endif // QT_CONFIG(dtls)
}
QSsl::DtlsCryptograph *QTlsBackendOpenSSL::createDtlsCryptograph(QDtls *q, int mode) const
{
#if QT_CONFIG(dtls)
return new QDtlsPrivateOpenSSL(q, QSslSocket::SslMode(mode));
#else
Q_UNUSED(q);
Q_UNUSED(mode);
qCWarning(lcTlsBackend, "Feature 'dtls' is disabled, cannot encrypt UDP datagrams");
return nullptr;
#endif // QT_CONFIG(dtls)
}
QSsl::X509ChainVerifyPtr QTlsBackendOpenSSL::X509Verifier() const
{
return QSsl::X509CertificateOpenSSL::verify;

View File

@ -80,6 +80,10 @@ private:
// QSslCertificate:
QSsl::X509Certificate *createCertificate() const override;
QSsl::DtlsCookieVerifier *createDtlsCookieVerifier() const override;
QSsl::DtlsCryptograph *createDtlsCryptograph(QDtls *q, int mode) const override;
QSsl::X509ChainVerifyPtr X509Verifier() const override;
QSsl::X509PemReaderPtr X509PemReader() const override;
QSsl::X509DerReaderPtr X509DerReader() const override;

View File

@ -53,8 +53,14 @@
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qsslconfiguration.h"
#include "qsslerror.h"
#include "qssl_p.h"
#if QT_CONFIG(dtls)
#include "qdtls.h"
#endif
#include <QtNetwork/qsslcertificate.h>
#include <QtNetwork/qsslerror.h>
#include <QtNetwork/qsslkey.h>
@ -72,7 +78,10 @@
QT_BEGIN_NAMESPACE
class QHostAddress;
class QByteArray;
class QSslCipher;
class QUdpSocket;
class QIODevice;
class QSslKey;
@ -183,11 +192,81 @@ using X509Pkcs12ReaderPtr = bool (*)(QIODevice *device, QSslKey *key, QSslCertif
// TLS over TCP. Handshake, encryption/decryption.
class TlsCryptograph;
// TLS over UDP. Handshake, encryption/decryption.
class DtlsCryptograph;
#if QT_CONFIG(dtls)
class DtlsBase
{
public:
virtual ~DtlsBase();
virtual void setDtlsError(QDtlsError code, const QString &description) = 0;
virtual QDtlsError error() const = 0;
virtual QString errorString() const = 0;
virtual void clearDtlsError() = 0;
virtual void setConfiguration(const QSslConfiguration &configuration) = 0;
virtual QSslConfiguration configuration() const = 0;
using GenParams = QDtlsClientVerifier::GeneratorParameters;
virtual bool setCookieGeneratorParameters(const GenParams &params) = 0;
virtual GenParams cookieGeneratorParameters() const = 0;
};
// DTLS cookie: generation and verification.
class DtlsCookieVerifier : virtual public DtlsBase
{
public:
virtual bool verifyClient(QUdpSocket *socket, const QByteArray &dgram,
const QHostAddress &address, quint16 port) = 0;
virtual QByteArray verifiedHello() const = 0;
};
// TLS over UDP. Handshake, encryption/decryption.
class DtlsCryptograph : virtual public DtlsBase
{
public:
virtual QSslSocket::SslMode cryptographMode() const = 0;
virtual void setPeer(const QHostAddress &addr, quint16 port, const QString &name) = 0;
virtual QHostAddress peerAddress() const = 0;
virtual quint16 peerPort() const = 0;
virtual void setPeerVerificationName(const QString &name) = 0;
virtual QString peerVerificationName() const = 0;
virtual void setDtlsMtuHint(quint16 mtu) = 0;
virtual quint16 dtlsMtuHint() const = 0;
virtual QDtls::HandshakeState state() const = 0;
virtual bool isConnectionEncrypted() const = 0;
virtual bool startHandshake(QUdpSocket *socket, const QByteArray &dgram) = 0;
virtual bool handleTimeout(QUdpSocket *socket) = 0;
virtual bool continueHandshake(QUdpSocket *socket, const QByteArray &dgram) = 0;
virtual bool resumeHandshake(QUdpSocket *socket) = 0;
virtual void abortHandshake(QUdpSocket *socket) = 0;
virtual void sendShutdownAlert(QUdpSocket *socket) = 0;
virtual QList<QSslError> peerVerificationErrors() const = 0;
virtual void ignoreVerificationErrors(const QList<QSslError> &errorsToIgnore) = 0;
virtual QSslCipher dtlsSessionCipher() const = 0;
virtual QSsl::SslProtocol dtlsSessionProtocol() const = 0;
virtual qint64 writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram) = 0;
virtual QByteArray decryptDatagram(QUdpSocket *socket, const QByteArray &dgram) = 0;
};
#else
class DtlsCookieVerifier;
class DtlsCryptograph;
#endif // QT_CONFIG(dtls)
} // namespace QSsl
@ -213,7 +292,7 @@ public:
// TLS and DTLS:
virtual QSsl::TlsCryptograph *createTlsCryptograph() const;
virtual QSsl::DtlsCryptograph *createDtlsCryptograph() const;
virtual QSsl::DtlsCryptograph *createDtlsCryptograph(class QDtls *qObject, int mode) const;
virtual QSsl::DtlsCookieVerifier *createDtlsCookieVerifier() const;
// TLSTODO - get rid of these function pointers, make them virtuals in