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:
parent
fe9d7bf759
commit
7c1aa0c48c
@ -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
|
qt_internal_extend_target(Network CONDITION QT_FEATURE_dtls AND QT_FEATURE_ssl
|
||||||
SOURCES
|
SOURCES
|
||||||
ssl/qdtls.cpp ssl/qdtls.h ssl/qdtls_p.h
|
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
|
qt_internal_extend_target(Network CONDITION QT_FEATURE_openssl AND QT_FEATURE_ssl
|
||||||
|
@ -38,8 +38,9 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "qsslconfiguration.h"
|
#include "qsslconfiguration.h"
|
||||||
#include "qdtls_openssl_p.h"
|
#include "qsslsocket_p.h"
|
||||||
#include "qudpsocket.h"
|
#include "qudpsocket.h"
|
||||||
|
#include "qsslcipher.h"
|
||||||
#include "qdtls_p.h"
|
#include "qdtls_p.h"
|
||||||
#include "qssl_p.h"
|
#include "qssl_p.h"
|
||||||
#include "qdtls.h"
|
#include "qdtls.h"
|
||||||
@ -337,72 +338,6 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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()
|
static QString msgUnsupportedMulticastAddress()
|
||||||
{
|
{
|
||||||
return QDtls::tr("Multicast and broadcast addresses are not supported");
|
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
|
Constructs a QDtlsClientVerifier object, \a parent is passed to QObject's
|
||||||
constructor.
|
constructor.
|
||||||
*/
|
*/
|
||||||
QDtlsClientVerifier::QDtlsClientVerifier(QObject *parent)
|
QDtlsClientVerifier::QDtlsClientVerifier(QObject *parent)
|
||||||
: QObject(*new QDtlsClientVerifierOpenSSL, parent)
|
: QObject(*new QDtlsClientVerifierPrivate, parent)
|
||||||
{
|
{
|
||||||
Q_D(QDtlsClientVerifier);
|
Q_D(QDtlsClientVerifier);
|
||||||
|
|
||||||
d->mode = QSslSocket::SslServerMode;
|
if (auto *backend = d->backend.get()) {
|
||||||
// The default configuration suffices: verifier never does a full
|
// The default configuration suffices: verifier never does a full
|
||||||
// handshake and upon verifying a cookie in a client hello message,
|
// handshake and upon verifying a cookie in a client hello message,
|
||||||
// it reports success.
|
// it reports success.
|
||||||
auto conf = QSslConfiguration::defaultDtlsConfiguration();
|
auto conf = QSslConfiguration::defaultDtlsConfiguration();
|
||||||
conf.setPeerVerifyMode(QSslSocket::VerifyNone);
|
conf.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||||
d->setConfiguration(conf);
|
backend->setConfiguration(conf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -473,8 +423,10 @@ QDtlsClientVerifier::~QDtlsClientVerifier()
|
|||||||
bool QDtlsClientVerifier::setCookieGeneratorParameters(const GeneratorParameters ¶ms)
|
bool QDtlsClientVerifier::setCookieGeneratorParameters(const GeneratorParameters ¶ms)
|
||||||
{
|
{
|
||||||
Q_D(QDtlsClientVerifier);
|
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);
|
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);
|
Q_D(QDtlsClientVerifier);
|
||||||
|
|
||||||
|
auto *backend = d->backend.get();
|
||||||
|
if (!backend)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!socket || address.isNull() || !dgram.size()) {
|
if (!socket || address.isNull() || !dgram.size()) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters,
|
backend->setDtlsError(QDtlsError::InvalidInputParameters,
|
||||||
tr("A valid UDP socket, non-empty datagram, valid address/port were expected"));
|
tr("A valid UDP socket, non-empty datagram, and valid address/port were expected"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address.isBroadcast() || address.isMulticast()) {
|
if (address.isBroadcast() || address.isMulticast()) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters,
|
backend->setDtlsError(QDtlsError::InvalidInputParameters,
|
||||||
msgUnsupportedMulticastAddress());
|
msgUnsupportedMulticastAddress());
|
||||||
return false;
|
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);
|
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);
|
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
|
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.
|
Creates a QDtls object, \a parent is passed to the QObject constructor.
|
||||||
\a mode is QSslSocket::SslServerMode for a server-side DTLS connection or
|
\a mode is QSslSocket::SslServerMode for a server-side DTLS connection or
|
||||||
@ -574,11 +545,19 @@ QString QDtlsClientVerifier::dtlsErrorString() const
|
|||||||
\sa sslMode(), QSslSocket::SslMode
|
\sa sslMode(), QSslSocket::SslMode
|
||||||
*/
|
*/
|
||||||
QDtls::QDtls(QSslSocket::SslMode mode, QObject *parent)
|
QDtls::QDtls(QSslSocket::SslMode mode, QObject *parent)
|
||||||
: QObject(*new QDtlsPrivateOpenSSL, parent)
|
: QObject(*new QDtlsPrivate, parent)
|
||||||
{
|
{
|
||||||
Q_D(QDtls);
|
Q_D(QDtls);
|
||||||
|
const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse();
|
||||||
d->mode = mode;
|
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());
|
setDtlsConfiguration(QSslConfiguration::defaultDtlsConfiguration());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,29 +580,30 @@ bool QDtls::setPeer(const QHostAddress &address, quint16 port,
|
|||||||
{
|
{
|
||||||
Q_D(QDtls);
|
Q_D(QDtls);
|
||||||
|
|
||||||
if (d->handshakeState != HandshakeNotStarted) {
|
auto *backend = d->backend.get();
|
||||||
d->setDtlsError(QDtlsError::InvalidOperation,
|
if (!backend)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (backend->state() != HandshakeNotStarted) {
|
||||||
|
backend->setDtlsError(QDtlsError::InvalidOperation,
|
||||||
tr("Cannot set peer after handshake started"));
|
tr("Cannot set peer after handshake started"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address.isNull()) {
|
if (address.isNull()) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters,
|
backend->setDtlsError(QDtlsError::InvalidInputParameters,
|
||||||
tr("Invalid address"));
|
tr("Invalid address"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address.isBroadcast() || address.isMulticast()) {
|
if (address.isBroadcast() || address.isMulticast()) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters,
|
backend->setDtlsError(QDtlsError::InvalidInputParameters,
|
||||||
msgUnsupportedMulticastAddress());
|
msgUnsupportedMulticastAddress());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->clearDtlsError();
|
backend->clearDtlsError();
|
||||||
|
backend->setPeer(address, port, verificationName);
|
||||||
d->remoteAddress = address;
|
|
||||||
d->remotePort = port;
|
|
||||||
d->peerVerificationName = verificationName;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -640,14 +620,18 @@ bool QDtls::setPeerVerificationName(const QString &name)
|
|||||||
{
|
{
|
||||||
Q_D(QDtls);
|
Q_D(QDtls);
|
||||||
|
|
||||||
if (d->handshakeState != HandshakeNotStarted) {
|
auto *backend = d->backend.get();
|
||||||
d->setDtlsError(QDtlsError::InvalidOperation,
|
if (!backend)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (backend->state() != HandshakeNotStarted) {
|
||||||
|
backend->setDtlsError(QDtlsError::InvalidOperation,
|
||||||
tr("Cannot set verification name after handshake started"));
|
tr("Cannot set verification name after handshake started"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->clearDtlsError();
|
backend->clearDtlsError();
|
||||||
d->peerVerificationName = name;
|
backend->setPeerVerificationName(name);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -661,7 +645,10 @@ QHostAddress QDtls::peerAddress() const
|
|||||||
{
|
{
|
||||||
Q_D(const QDtls);
|
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
|
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);
|
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);
|
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);
|
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);
|
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 ¶ms)
|
|||||||
{
|
{
|
||||||
Q_D(QDtls);
|
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);
|
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);
|
Q_D(QDtls);
|
||||||
|
|
||||||
if (d->handshakeState != HandshakeNotStarted) {
|
auto *backend = d->backend.get();
|
||||||
d->setDtlsError(QDtlsError::InvalidOperation,
|
if (!backend)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (backend->state() != HandshakeNotStarted) {
|
||||||
|
backend->setDtlsError(QDtlsError::InvalidOperation,
|
||||||
tr("Cannot set configuration after handshake started"));
|
tr("Cannot set configuration after handshake started"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->setConfiguration(configuration);
|
backend->setConfiguration(configuration);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -793,8 +803,10 @@ bool QDtls::setDtlsConfiguration(const QSslConfiguration &configuration)
|
|||||||
QSslConfiguration QDtls::dtlsConfiguration() const
|
QSslConfiguration QDtls::dtlsConfiguration() const
|
||||||
{
|
{
|
||||||
Q_D(const QDtls);
|
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);
|
Q_D(const QDtls);
|
||||||
|
|
||||||
return d->handshakeState;
|
if (const auto *backend = d->backend.get())
|
||||||
|
return backend->state();
|
||||||
|
|
||||||
|
return QDtls::HandshakeNotStarted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -832,12 +847,16 @@ bool QDtls::doHandshake(QUdpSocket *socket, const QByteArray &dgram)
|
|||||||
{
|
{
|
||||||
Q_D(QDtls);
|
Q_D(QDtls);
|
||||||
|
|
||||||
if (d->handshakeState == HandshakeNotStarted)
|
auto *backend = d->backend.get();
|
||||||
|
if (!backend)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (backend->state() == HandshakeNotStarted)
|
||||||
return startHandshake(socket, dgram);
|
return startHandshake(socket, dgram);
|
||||||
else if (d->handshakeState == HandshakeInProgress)
|
else if (backend->state() == HandshakeInProgress)
|
||||||
return continueHandshake(socket, dgram);
|
return continueHandshake(socket, dgram);
|
||||||
|
|
||||||
d->setDtlsError(QDtlsError::InvalidOperation,
|
backend->setDtlsError(QDtlsError::InvalidOperation,
|
||||||
tr("Cannot start/continue handshake, invalid handshake state"));
|
tr("Cannot start/continue handshake, invalid handshake state"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -849,30 +868,34 @@ bool QDtls::startHandshake(QUdpSocket *socket, const QByteArray &datagram)
|
|||||||
{
|
{
|
||||||
Q_D(QDtls);
|
Q_D(QDtls);
|
||||||
|
|
||||||
|
auto *backend = d->backend.get();
|
||||||
|
if (!backend)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
|
backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->remoteAddress.isNull()) {
|
if (backend->peerAddress().isNull()) {
|
||||||
d->setDtlsError(QDtlsError::InvalidOperation,
|
backend->setDtlsError(QDtlsError::InvalidOperation,
|
||||||
tr("To start a handshake you must set peer's address and port first"));
|
tr("To start a handshake you must set peer's address and port first"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sslMode() == QSslSocket::SslServerMode && !datagram.size()) {
|
if (sslMode() == QSslSocket::SslServerMode && !datagram.size()) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters,
|
backend->setDtlsError(QDtlsError::InvalidInputParameters,
|
||||||
tr("To start a handshake, DTLS server requires non-empty datagram (client hello)"));
|
tr("To start a handshake, DTLS server requires non-empty datagram (client hello)"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->handshakeState != HandshakeNotStarted) {
|
if (backend->state() != HandshakeNotStarted) {
|
||||||
d->setDtlsError(QDtlsError::InvalidOperation,
|
backend->setDtlsError(QDtlsError::InvalidOperation,
|
||||||
tr("Cannot start handshake, already done/in progress"));
|
tr("Cannot start handshake, already done/in progress"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return d->startHandshake(socket, datagram);
|
return backend->startHandshake(socket, datagram);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -887,12 +910,16 @@ bool QDtls::handleTimeout(QUdpSocket *socket)
|
|||||||
{
|
{
|
||||||
Q_D(QDtls);
|
Q_D(QDtls);
|
||||||
|
|
||||||
|
auto *backend = d->backend.get();
|
||||||
|
if (!backend)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
|
backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
|
||||||
return false;
|
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);
|
Q_D(QDtls);
|
||||||
|
|
||||||
|
auto *backend = d->backend.get();
|
||||||
|
if (!backend)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!socket || !datagram.size()) {
|
if (!socket || !datagram.size()) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters,
|
backend->setDtlsError(QDtlsError::InvalidInputParameters,
|
||||||
tr("A valid QUdpSocket and non-empty datagram are needed to continue the handshake"));
|
tr("A valid QUdpSocket and non-empty datagram are needed to continue the handshake"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->handshakeState != HandshakeInProgress) {
|
if (backend->state() != HandshakeInProgress) {
|
||||||
d->setDtlsError(QDtlsError::InvalidOperation,
|
backend->setDtlsError(QDtlsError::InvalidOperation,
|
||||||
tr("Cannot continue handshake, not in InProgress state"));
|
tr("Cannot continue handshake, not in InProgress state"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return d->continueHandshake(socket, datagram);
|
return backend->continueHandshake(socket, datagram);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -929,18 +960,22 @@ bool QDtls::resumeHandshake(QUdpSocket *socket)
|
|||||||
{
|
{
|
||||||
Q_D(QDtls);
|
Q_D(QDtls);
|
||||||
|
|
||||||
|
auto *backend = d->backend.get();
|
||||||
|
if (!backend)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
|
backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->handshakeState != PeerVerificationFailed) {
|
if (backend->state() != PeerVerificationFailed) {
|
||||||
d->setDtlsError(QDtlsError::InvalidOperation,
|
backend->setDtlsError(QDtlsError::InvalidOperation,
|
||||||
tr("Cannot resume, not in VerificationError state"));
|
tr("Cannot resume, not in VerificationError state"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return d->resumeHandshake(socket);
|
return backend->resumeHandshake(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -953,18 +988,22 @@ bool QDtls::abortHandshake(QUdpSocket *socket)
|
|||||||
{
|
{
|
||||||
Q_D(QDtls);
|
Q_D(QDtls);
|
||||||
|
|
||||||
|
auto *backend = d->backend.get();
|
||||||
|
if (!backend)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
|
backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->handshakeState != PeerVerificationFailed && d->handshakeState != HandshakeInProgress) {
|
if (backend->state() != PeerVerificationFailed && backend->state() != HandshakeInProgress) {
|
||||||
d->setDtlsError(QDtlsError::InvalidOperation,
|
backend->setDtlsError(QDtlsError::InvalidOperation,
|
||||||
tr("No handshake in progress, nothing to abort"));
|
tr("No handshake in progress, nothing to abort"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->abortHandshake(socket);
|
backend->abortHandshake(socket);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -979,19 +1018,23 @@ bool QDtls::shutdown(QUdpSocket *socket)
|
|||||||
{
|
{
|
||||||
Q_D(QDtls);
|
Q_D(QDtls);
|
||||||
|
|
||||||
|
auto *backend = d->backend.get();
|
||||||
|
if (!backend)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters,
|
backend->setDtlsError(QDtlsError::InvalidInputParameters,
|
||||||
tr("Invalid (nullptr) socket"));
|
tr("Invalid (nullptr) socket"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!d->connectionEncrypted) {
|
if (!backend->isConnectionEncrypted()) {
|
||||||
d->setDtlsError(QDtlsError::InvalidOperation,
|
backend->setDtlsError(QDtlsError::InvalidOperation,
|
||||||
tr("Cannot send shutdown alert, not encrypted"));
|
tr("Cannot send shutdown alert, not encrypted"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->sendShutdownAlert(socket);
|
backend->sendShutdownAlert(socket);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1004,7 +1047,11 @@ bool QDtls::isConnectionEncrypted() const
|
|||||||
{
|
{
|
||||||
Q_D(const QDtls);
|
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);
|
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);
|
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);
|
Q_D(QDtls);
|
||||||
|
|
||||||
|
auto *backend = d->backend.get();
|
||||||
|
if (!backend)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
|
backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isConnectionEncrypted()) {
|
if (!isConnectionEncrypted()) {
|
||||||
d->setDtlsError(QDtlsError::InvalidOperation,
|
backend->setDtlsError(QDtlsError::InvalidOperation,
|
||||||
tr("Cannot write a datagram, not in encrypted state"));
|
tr("Cannot write a datagram, not in encrypted state"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return d->writeDatagramEncrypted(socket, dgram);
|
return backend->writeDatagramEncrypted(socket, dgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1079,13 +1136,17 @@ QByteArray QDtls::decryptDatagram(QUdpSocket *socket, const QByteArray &dgram)
|
|||||||
{
|
{
|
||||||
Q_D(QDtls);
|
Q_D(QDtls);
|
||||||
|
|
||||||
|
auto *backend = d->backend.get();
|
||||||
|
if (!backend)
|
||||||
|
return {};
|
||||||
|
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
|
backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isConnectionEncrypted()) {
|
if (!isConnectionEncrypted()) {
|
||||||
d->setDtlsError(QDtlsError::InvalidOperation,
|
backend->setDtlsError(QDtlsError::InvalidOperation,
|
||||||
tr("Cannot read a datagram, not in encrypted state"));
|
tr("Cannot read a datagram, not in encrypted state"));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -1093,7 +1154,7 @@ QByteArray QDtls::decryptDatagram(QUdpSocket *socket, const QByteArray &dgram)
|
|||||||
if (!dgram.size())
|
if (!dgram.size())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return d->decryptDatagram(socket, dgram);
|
return backend->decryptDatagram(socket, dgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1105,7 +1166,10 @@ QDtlsError QDtls::dtlsError() const
|
|||||||
{
|
{
|
||||||
Q_D(const QDtls);
|
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);
|
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);
|
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);
|
Q_D(QDtls);
|
||||||
|
|
||||||
d->tlsErrorsToIgnore = errorsToIgnore;
|
if (auto *backend = d->backend.get())
|
||||||
|
backend->ignoreVerificationErrors(errorsToIgnore);
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
137
src/network/ssl/qdtls_base.cpp
Normal file
137
src/network/ssl/qdtls_base.cpp
Normal 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 ¶ms)
|
||||||
|
{
|
||||||
|
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
|
115
src/network/ssl/qdtls_base_p.h
Normal file
115
src/network/ssl/qdtls_base_p.h
Normal 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
|
@ -783,8 +783,8 @@ void DtlsState::setLinkMtu(QDtlsBasePrivate *dtlsBase)
|
|||||||
} // namespace dtlsopenssl
|
} // namespace dtlsopenssl
|
||||||
|
|
||||||
QDtlsClientVerifierOpenSSL::QDtlsClientVerifierOpenSSL()
|
QDtlsClientVerifierOpenSSL::QDtlsClientVerifierOpenSSL()
|
||||||
|
: QDtlsBasePrivate(QSslSocket::SslServerMode, dtlsutil::fallbackSecret())
|
||||||
{
|
{
|
||||||
secret = dtlsutil::fallbackSecret();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QDtlsClientVerifierOpenSSL::verifyClient(QUdpSocket *socket, const QByteArray &dgram,
|
bool QDtlsClientVerifierOpenSSL::verifyClient(QUdpSocket *socket, const QByteArray &dgram,
|
||||||
@ -827,6 +827,11 @@ bool QDtlsClientVerifierOpenSSL::verifyClient(QUdpSocket *socket, const QByteArr
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray QDtlsClientVerifierOpenSSL::verifiedHello() const
|
||||||
|
{
|
||||||
|
return verifiedClientHello;
|
||||||
|
}
|
||||||
|
|
||||||
void QDtlsPrivateOpenSSL::TimeoutHandler::start(int hintMs)
|
void QDtlsPrivateOpenSSL::TimeoutHandler::start(int hintMs)
|
||||||
{
|
{
|
||||||
Q_ASSERT(timerId == -1);
|
Q_ASSERT(timerId == -1);
|
||||||
@ -861,12 +866,66 @@ void QDtlsPrivateOpenSSL::TimeoutHandler::timerEvent(QTimerEvent *event)
|
|||||||
dtlsConnection->reportTimeout();
|
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;
|
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)
|
bool QDtlsPrivateOpenSSL::startHandshake(QUdpSocket *socket, const QByteArray &dgram)
|
||||||
{
|
{
|
||||||
Q_ASSERT(socket);
|
Q_ASSERT(socket);
|
||||||
@ -1070,6 +1129,26 @@ void QDtlsPrivateOpenSSL::sendShutdownAlert(QUdpSocket *socket)
|
|||||||
resetDtls();
|
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,
|
qint64 QDtlsPrivateOpenSSL::writeDatagramEncrypted(QUdpSocket *socket,
|
||||||
const QByteArray &dgram)
|
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
|
// The code below is taken (with some modifications) from qsslsocket_openssl
|
||||||
// - alas, we cannot simply re-use it, it's in QSslSocketPrivate.
|
// - alas, we cannot simply re-use it, it's in QSslSocketPrivate.
|
||||||
|
|
||||||
Q_Q(QDtls);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
QSslPreSharedKeyAuthenticator authenticator;
|
QSslPreSharedKeyAuthenticator authenticator;
|
||||||
// Fill in some read-only fields (for client code)
|
// 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 QDtlsPrivateOpenSSL::pskServerCallback(const char *identity, unsigned char *psk,
|
||||||
unsigned max_psk_len)
|
unsigned max_psk_len)
|
||||||
{
|
{
|
||||||
Q_Q(QDtls);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
QSslPreSharedKeyAuthenticator authenticator;
|
QSslPreSharedKeyAuthenticator authenticator;
|
||||||
// Fill in some read-only fields (for the user)
|
// Fill in some read-only fields (for the user)
|
||||||
@ -1287,7 +1361,7 @@ bool QDtlsPrivateOpenSSL::verifyPeer()
|
|||||||
// is empty, we call QAbstractSocket::peerName(), which returns
|
// is empty, we call QAbstractSocket::peerName(), which returns
|
||||||
// either peerName (can be set by setPeerName) or host name
|
// either peerName (can be set by setPeerName) or host name
|
||||||
// (can be set as a result of connectToHost).
|
// (can be set as a result of connectToHost).
|
||||||
QString name = peerVerificationName;
|
QString name = peerVfyName;
|
||||||
if (name.isEmpty()) {
|
if (name.isEmpty()) {
|
||||||
Q_ASSERT(dtls.udpSocket);
|
Q_ASSERT(dtls.udpSocket);
|
||||||
name = dtls.udpSocket->peerName();
|
name = dtls.udpSocket->peerName();
|
||||||
@ -1366,8 +1440,6 @@ void QDtlsPrivateOpenSSL::fetchNegotiatedParameters()
|
|||||||
|
|
||||||
void QDtlsPrivateOpenSSL::reportTimeout()
|
void QDtlsPrivateOpenSSL::reportTimeout()
|
||||||
{
|
{
|
||||||
Q_Q(QDtls);
|
|
||||||
|
|
||||||
emit q->handshakeTimeout();
|
emit q->handshakeTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2018 The Qt Company Ltd.
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the QtNetwork module of the Qt Toolkit.
|
** This file is part of the QtNetwork module of the Qt Toolkit.
|
||||||
@ -46,6 +46,8 @@
|
|||||||
|
|
||||||
#include <openssl/ossl_typ.h>
|
#include <openssl/ossl_typ.h>
|
||||||
|
|
||||||
|
#include "qtlsbackend_openssl_p.h"
|
||||||
|
#include "qdtls_base_p.h"
|
||||||
#include "qdtls_p.h"
|
#include "qdtls_p.h"
|
||||||
|
|
||||||
#include <private/qsslcontext_openssl_p.h>
|
#include <private/qsslcontext_openssl_p.h>
|
||||||
@ -55,7 +57,6 @@
|
|||||||
#include <QtNetwork/qhostaddress.h>
|
#include <QtNetwork/qhostaddress.h>
|
||||||
|
|
||||||
#include <QtCore/qbytearray.h>
|
#include <QtCore/qbytearray.h>
|
||||||
#include <QtCore/qcryptographichash.h>
|
|
||||||
#include <QtCore/qlist.h>
|
#include <QtCore/qlist.h>
|
||||||
#include <QtCore/qsharedpointer.h>
|
#include <QtCore/qsharedpointer.h>
|
||||||
|
|
||||||
@ -76,6 +77,7 @@ QT_REQUIRE_CONFIG(dtls);
|
|||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QDtlsPrivateOpenSSL;
|
class QDtlsPrivateOpenSSL;
|
||||||
|
class QDtlsBasePrivate;
|
||||||
class QUdpSocket;
|
class QUdpSocket;
|
||||||
|
|
||||||
namespace dtlsopenssl
|
namespace dtlsopenssl
|
||||||
@ -131,23 +133,40 @@ private:
|
|||||||
|
|
||||||
} // namespace dtlsopenssl
|
} // namespace dtlsopenssl
|
||||||
|
|
||||||
class QDtlsClientVerifierOpenSSL : public QDtlsClientVerifierPrivate
|
class QDtlsClientVerifierOpenSSL : public QSsl::DtlsCookieVerifier, public QDtlsBasePrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
QDtlsClientVerifierOpenSSL();
|
QDtlsClientVerifierOpenSSL();
|
||||||
|
|
||||||
bool verifyClient(QUdpSocket *socket, const QByteArray &dgram,
|
bool verifyClient(QUdpSocket *socket, const QByteArray &dgram,
|
||||||
const QHostAddress &address, quint16 port) override;
|
const QHostAddress &address, quint16 port) override;
|
||||||
|
QByteArray verifiedHello() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
dtlsopenssl::DtlsState dtls;
|
dtlsopenssl::DtlsState dtls;
|
||||||
|
QByteArray verifiedClientHello;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QDtlsPrivateOpenSSL : public QDtlsPrivate
|
class QDtlsPrivateOpenSSL : public QSsl::DtlsCryptograph, public QDtlsBasePrivate
|
||||||
{
|
{
|
||||||
public:
|
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 startHandshake(QUdpSocket *socket, const QByteArray &datagram) override;
|
||||||
bool continueHandshake(QUdpSocket *socket, const QByteArray &datagram) override;
|
bool continueHandshake(QUdpSocket *socket, const QByteArray &datagram) override;
|
||||||
@ -156,9 +175,17 @@ public:
|
|||||||
bool handleTimeout(QUdpSocket *socket) override;
|
bool handleTimeout(QUdpSocket *socket) override;
|
||||||
void sendShutdownAlert(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;
|
qint64 writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &datagram) override;
|
||||||
QByteArray decryptDatagram(QUdpSocket *socket, const QByteArray &tlsdgram) override;
|
QByteArray decryptDatagram(QUdpSocket *socket, const QByteArray &tlsdgram) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
unsigned pskClientCallback(const char *hint, char *identity, unsigned max_identity_len,
|
unsigned pskClientCallback(const char *hint, char *identity, unsigned max_identity_len,
|
||||||
unsigned char *psk, unsigned max_psk_len);
|
unsigned char *psk, unsigned max_psk_len);
|
||||||
unsigned pskServerCallback(const char *identity, unsigned char *psk,
|
unsigned pskServerCallback(const char *identity, unsigned char *psk,
|
||||||
@ -195,14 +222,18 @@ private:
|
|||||||
QDtlsPrivateOpenSSL *dtlsConnection = nullptr;
|
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
|
// We will initialize it 'lazily', just in case somebody wants to move
|
||||||
// QDtls to another thread.
|
// QDtls to another thread.
|
||||||
QScopedPointer<TimeoutHandler> timeoutHandler;
|
QScopedPointer<TimeoutHandler> timeoutHandler;
|
||||||
bool connectionWasShutdown = false;
|
bool connectionWasShutdown = false;
|
||||||
QSslPreSharedKeyAuthenticator pskAuthenticator;
|
QSslPreSharedKeyAuthenticator pskAuthenticator;
|
||||||
QByteArray identityHint;
|
QByteArray identityHint;
|
||||||
|
|
||||||
Q_DECLARE_PUBLIC(QDtls)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,21 +42,9 @@
|
|||||||
|
|
||||||
#include <private/qtnetworkglobal_p.h>
|
#include <private/qtnetworkglobal_p.h>
|
||||||
|
|
||||||
#include "qdtls.h"
|
#include "qtlsbackend_p.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 <QtCore/private/qobject_p.h>
|
||||||
//
|
//
|
||||||
// W A R N I N G
|
// W A R N I N G
|
||||||
// -------------
|
// -------------
|
||||||
@ -74,80 +62,20 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
class QHostAddress;
|
class QHostAddress;
|
||||||
|
|
||||||
class QDtlsBasePrivate : public QObjectPrivate
|
class QDtlsClientVerifierPrivate : public QObjectPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
QDtlsClientVerifierPrivate();
|
||||||
void setDtlsError(QDtlsError code, const QString &description)
|
~QDtlsClientVerifierPrivate();
|
||||||
{
|
std::unique_ptr<QSsl::DtlsCookieVerifier> backend;
|
||||||
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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class QDtlsClientVerifierPrivate : public QDtlsBasePrivate
|
class QDtlsPrivate : public QObjectPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
QDtlsPrivate();
|
||||||
QByteArray verifiedClientHello;
|
~QDtlsPrivate();
|
||||||
|
std::unique_ptr<QSsl::DtlsCryptograph> backend;
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -199,6 +199,10 @@ TlsKey *X509Certificate::publicKey() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_CONFIG(dtls)
|
||||||
|
DtlsBase::~DtlsBase() = default;
|
||||||
|
#endif // QT_CONFIG(dtls)
|
||||||
|
|
||||||
} // namespace QSsl
|
} // namespace QSsl
|
||||||
|
|
||||||
const QString QTlsBackend::builtinBackendNames[] = {
|
const QString QTlsBackend::builtinBackendNames[] = {
|
||||||
@ -250,8 +254,10 @@ QSsl::TlsCryptograph *QTlsBackend::createTlsCryptograph() const
|
|||||||
return nullptr;
|
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");
|
REPORT_MISSING_SUPPORT("does not support QDtls");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,10 @@
|
|||||||
#include "qtlskey_openssl_p.h"
|
#include "qtlskey_openssl_p.h"
|
||||||
#include "qx509_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.)
|
// TLSTODO: Later, this code (ensure initialised, etc.)
|
||||||
// must move from the socket to backend.
|
// must move from the socket to backend.
|
||||||
#include "qsslsocket_p.h"
|
#include "qsslsocket_p.h"
|
||||||
@ -163,6 +167,28 @@ QSsl::X509Certificate *QTlsBackendOpenSSL::createCertificate() const
|
|||||||
return new QSsl::X509CertificateOpenSSL;
|
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
|
QSsl::X509ChainVerifyPtr QTlsBackendOpenSSL::X509Verifier() const
|
||||||
{
|
{
|
||||||
return QSsl::X509CertificateOpenSSL::verify;
|
return QSsl::X509CertificateOpenSSL::verify;
|
||||||
|
@ -80,6 +80,10 @@ private:
|
|||||||
|
|
||||||
// QSslCertificate:
|
// QSslCertificate:
|
||||||
QSsl::X509Certificate *createCertificate() const override;
|
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::X509ChainVerifyPtr X509Verifier() const override;
|
||||||
QSsl::X509PemReaderPtr X509PemReader() const override;
|
QSsl::X509PemReaderPtr X509PemReader() const override;
|
||||||
QSsl::X509DerReaderPtr X509DerReader() const override;
|
QSsl::X509DerReaderPtr X509DerReader() const override;
|
||||||
|
@ -53,8 +53,14 @@
|
|||||||
|
|
||||||
#include <QtNetwork/private/qtnetworkglobal_p.h>
|
#include <QtNetwork/private/qtnetworkglobal_p.h>
|
||||||
|
|
||||||
|
#include "qsslconfiguration.h"
|
||||||
|
#include "qsslerror.h"
|
||||||
#include "qssl_p.h"
|
#include "qssl_p.h"
|
||||||
|
|
||||||
|
#if QT_CONFIG(dtls)
|
||||||
|
#include "qdtls.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <QtNetwork/qsslcertificate.h>
|
#include <QtNetwork/qsslcertificate.h>
|
||||||
#include <QtNetwork/qsslerror.h>
|
#include <QtNetwork/qsslerror.h>
|
||||||
#include <QtNetwork/qsslkey.h>
|
#include <QtNetwork/qsslkey.h>
|
||||||
@ -72,7 +78,10 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QHostAddress;
|
||||||
class QByteArray;
|
class QByteArray;
|
||||||
|
class QSslCipher;
|
||||||
|
class QUdpSocket;
|
||||||
class QIODevice;
|
class QIODevice;
|
||||||
class QSslKey;
|
class QSslKey;
|
||||||
|
|
||||||
@ -183,11 +192,81 @@ using X509Pkcs12ReaderPtr = bool (*)(QIODevice *device, QSslKey *key, QSslCertif
|
|||||||
// TLS over TCP. Handshake, encryption/decryption.
|
// TLS over TCP. Handshake, encryption/decryption.
|
||||||
class TlsCryptograph;
|
class TlsCryptograph;
|
||||||
|
|
||||||
// TLS over UDP. Handshake, encryption/decryption.
|
#if QT_CONFIG(dtls)
|
||||||
class DtlsCryptograph;
|
|
||||||
|
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 ¶ms) = 0;
|
||||||
|
virtual GenParams cookieGeneratorParameters() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// DTLS cookie: generation and verification.
|
// 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 DtlsCookieVerifier;
|
||||||
|
class DtlsCryptograph;
|
||||||
|
|
||||||
|
#endif // QT_CONFIG(dtls)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace QSsl
|
} // namespace QSsl
|
||||||
|
|
||||||
@ -213,7 +292,7 @@ public:
|
|||||||
|
|
||||||
// TLS and DTLS:
|
// TLS and DTLS:
|
||||||
virtual QSsl::TlsCryptograph *createTlsCryptograph() const;
|
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;
|
virtual QSsl::DtlsCookieVerifier *createDtlsCookieVerifier() const;
|
||||||
|
|
||||||
// TLSTODO - get rid of these function pointers, make them virtuals in
|
// TLSTODO - get rid of these function pointers, make them virtuals in
|
||||||
|
Loading…
x
Reference in New Issue
Block a user