QtBase  v6.3.1
qdtls.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2018 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qsslconfiguration.h"
41 #include "qsslsocket_p.h"
42 #include "qudpsocket.h"
43 #include "qsslcipher.h"
44 #include "qdtls_p.h"
45 #include "qssl_p.h"
46 #include "qdtls.h"
47 
48 #include "qglobal.h"
49 
340 
341 static QString msgUnsupportedMulticastAddress()
342 {
343  return QDtls::tr("Multicast and broadcast addresses are not supported");
344 }
345 
356 {
357 }
358 
368  : hash(algorithm), secret(secret)
369 {
370 }
371 
373 {
374  const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse();
375  if (!tlsBackend) {
376  qCWarning(lcSsl, "No TLS backend is available, cannot verify DTLS client");
377  return;
378  }
379  backend.reset(tlsBackend->createDtlsCookieVerifier());
380  if (!backend.get())
381  qCWarning(lcSsl) << "The backend" << tlsBackend->backendName() << "does not support DTLS cookies";
382 }
383 
385 
392 {
393  Q_D(QDtlsClientVerifier);
394 
395  if (auto *backend = d->backend.get()) {
396  // The default configuration suffices: verifier never does a full
397  // handshake and upon verifying a cookie in a client hello message,
398  // it reports success.
399  auto conf = QSslConfiguration::defaultDtlsConfiguration();
400  conf.setPeerVerifyMode(QSslSocket::VerifyNone);
401  backend->setConfiguration(conf);
402  }
403 }
404 
409 {
410 }
411 
424 {
425  Q_D(QDtlsClientVerifier);
426  if (auto *backend = d->backend.get())
427  return backend->setCookieGeneratorParameters(params);
428 
429  return false;
430 }
431 
443 {
444  Q_D(const QDtlsClientVerifier);
445 
446  if (const auto *backend = d->backend.get())
447  return backend->cookieGeneratorParameters();
448 
449  return {};
450 }
451 
469 {
470  Q_D(QDtlsClientVerifier);
471 
472  auto *backend = d->backend.get();
473  if (!backend)
474  return false;
475 
476  if (!socket || address.isNull() || !dgram.size()) {
477  backend->setDtlsError(QDtlsError::InvalidInputParameters,
478  tr("A valid UDP socket, non-empty datagram, and valid address/port were expected"));
479  return false;
480  }
481 
482  if (address.isBroadcast() || address.isMulticast()) {
483  backend->setDtlsError(QDtlsError::InvalidInputParameters,
484  msgUnsupportedMulticastAddress());
485  return false;
486  }
487 
488  return backend->verifyClient(socket, dgram, address, port);
489 }
490 
498 {
499  Q_D(const QDtlsClientVerifier);
500 
501  if (const auto *backend = d->backend.get())
502  return backend->verifiedHello();
503 
504  return {};
505 }
506 
513 {
514  Q_D(const QDtlsClientVerifier);
515 
516  if (const auto *backend = d->backend.get())
517  return backend->error();
518 
520 }
521 
528 {
529  Q_D(const QDtlsClientVerifier);
530 
531  if (const auto *backend = d->backend.get())
532  return backend->errorString();
533 
534  return QStringLiteral("No TLS backend is available, no client verification");
535 }
536 
537 QDtlsPrivate::QDtlsPrivate() = default;
538 QDtlsPrivate::~QDtlsPrivate() = default;
539 
548  : QObject(*new QDtlsPrivate, parent)
549 {
550  Q_D(QDtls);
551  const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse();
552  if (!tlsBackend) {
553  qCWarning(lcSsl, "No TLS backend found, QDtls is unsupported");
554  return;
555  }
556  d->backend.reset(tlsBackend->createDtlsCryptograph(this, mode));
557  if (!d->backend.get()) {
558  qCWarning(lcSsl) << "TLS backend" << tlsBackend->backendName()
559  << "does not support the protocol DTLS";
560  }
561  setDtlsConfiguration(QSslConfiguration::defaultDtlsConfiguration());
562 }
563 
568 {
569 }
570 
579  const QString &verificationName)
580 {
581  Q_D(QDtls);
582 
583  auto *backend = d->backend.get();
584  if (!backend)
585  return false;
586 
587  if (backend->state() != HandshakeNotStarted) {
588  backend->setDtlsError(QDtlsError::InvalidOperation,
589  tr("Cannot set peer after handshake started"));
590  return false;
591  }
592 
593  if (address.isNull()) {
594  backend->setDtlsError(QDtlsError::InvalidInputParameters,
595  tr("Invalid address"));
596  return false;
597  }
598 
599  if (address.isBroadcast() || address.isMulticast()) {
600  backend->setDtlsError(QDtlsError::InvalidInputParameters,
601  msgUnsupportedMulticastAddress());
602  return false;
603  }
604 
605  backend->clearDtlsError();
606  backend->setPeer(address, port, verificationName);
607 
608  return true;
609 }
610 
620 {
621  Q_D(QDtls);
622 
623  auto *backend = d->backend.get();
624  if (!backend)
625  return false;
626 
627  if (backend->state() != HandshakeNotStarted) {
628  backend->setDtlsError(QDtlsError::InvalidOperation,
629  tr("Cannot set verification name after handshake started"));
630  return false;
631  }
632 
633  backend->clearDtlsError();
634  backend->setPeerVerificationName(name);
635 
636  return true;
637 }
638 
645 {
646  Q_D(const QDtls);
647 
648  if (const auto *backend = d->backend.get())
649  return backend->peerAddress();
650 
651  return {};
652 }
653 
660 {
661  Q_D(const QDtls);
662 
663  if (const auto *backend = d->backend.get())
664  return backend->peerPort();
665 
666  return 0;
667 }
668 
676 {
677  Q_D(const QDtls);
678 
679  if (const auto *backend = d->backend.get())
680  return backend->peerVerificationName();
681 
682  return {};
683 }
684 
692 {
693  Q_D(const QDtls);
694 
695  if (const auto *backend = d->backend.get())
696  return backend->cryptographMode();
697 
699 }
700 
708 {
709  Q_D(QDtls);
710 
711  if (auto *backend = d->backend.get())
712  backend->setDtlsMtuHint(mtuHint);
713 }
714 
721 {
722  Q_D(const QDtls);
723 
724  if (const auto *backend = d->backend.get())
725  return backend->dtlsMtuHint();
726 
727  return 0;
728 }
729 
741 {
742  Q_D(QDtls);
743 
744  if (auto *backend = d->backend.get())
745  backend->setCookieGeneratorParameters(params);
746 
747  return false;
748 }
749 
762 {
763  Q_D(const QDtls);
764 
765  if (const auto *backend = d->backend.get())
766  return backend->cookieGeneratorParameters();
767 
768  return {};
769 }
770 
780 {
781  Q_D(QDtls);
782 
783  auto *backend = d->backend.get();
784  if (!backend)
785  return false;
786 
787  if (backend->state() != HandshakeNotStarted) {
788  backend->setDtlsError(QDtlsError::InvalidOperation,
789  tr("Cannot set configuration after handshake started"));
790  return false;
791  }
792 
793  backend->setConfiguration(configuration);
794  return true;
795 }
796 
804 {
805  Q_D(const QDtls);
806  if (const auto *backend = d->backend.get())
807  return backend->configuration();
808 
809  return {};
810 }
811 
818 {
819  Q_D(const QDtls);
820 
821  if (const auto *backend = d->backend.get())
822  return backend->state();
823 
825 }
826 
847 {
848  Q_D(QDtls);
849 
850  auto *backend = d->backend.get();
851  if (!backend)
852  return false;
853 
854  if (backend->state() == HandshakeNotStarted)
855  return startHandshake(socket, dgram);
856  else if (backend->state() == HandshakeInProgress)
857  return continueHandshake(socket, dgram);
858 
859  backend->setDtlsError(QDtlsError::InvalidOperation,
860  tr("Cannot start/continue handshake, invalid handshake state"));
861  return false;
862 }
863 
867 bool QDtls::startHandshake(QUdpSocket *socket, const QByteArray &datagram)
868 {
869  Q_D(QDtls);
870 
871  auto *backend = d->backend.get();
872  if (!backend)
873  return false;
874 
875  if (!socket) {
876  backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
877  return false;
878  }
879 
880  if (backend->peerAddress().isNull()) {
881  backend->setDtlsError(QDtlsError::InvalidOperation,
882  tr("To start a handshake you must set peer's address and port first"));
883  return false;
884  }
885 
886  if (sslMode() == QSslSocket::SslServerMode && !datagram.size()) {
887  backend->setDtlsError(QDtlsError::InvalidInputParameters,
888  tr("To start a handshake, DTLS server requires non-empty datagram (client hello)"));
889  return false;
890  }
891 
892  if (backend->state() != HandshakeNotStarted) {
893  backend->setDtlsError(QDtlsError::InvalidOperation,
894  tr("Cannot start handshake, already done/in progress"));
895  return false;
896  }
897 
898  return backend->startHandshake(socket, datagram);
899 }
900 
910 {
911  Q_D(QDtls);
912 
913  auto *backend = d->backend.get();
914  if (!backend)
915  return false;
916 
917  if (!socket) {
918  backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
919  return false;
920  }
921 
922  return backend->handleTimeout(socket);
923 }
924 
928 bool QDtls::continueHandshake(QUdpSocket *socket, const QByteArray &datagram)
929 {
930  Q_D(QDtls);
931 
932  auto *backend = d->backend.get();
933  if (!backend)
934  return false;
935 
936  if (!socket || !datagram.size()) {
937  backend->setDtlsError(QDtlsError::InvalidInputParameters,
938  tr("A valid QUdpSocket and non-empty datagram are needed to continue the handshake"));
939  return false;
940  }
941 
942  if (backend->state() != HandshakeInProgress) {
943  backend->setDtlsError(QDtlsError::InvalidOperation,
944  tr("Cannot continue handshake, not in InProgress state"));
945  return false;
946  }
947 
948  return backend->continueHandshake(socket, datagram);
949 }
950 
960 {
961  Q_D(QDtls);
962 
963  auto *backend = d->backend.get();
964  if (!backend)
965  return false;
966 
967  if (!socket) {
968  backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
969  return false;
970  }
971 
972  if (backend->state() != PeerVerificationFailed) {
973  backend->setDtlsError(QDtlsError::InvalidOperation,
974  tr("Cannot resume, not in VerificationError state"));
975  return false;
976  }
977 
978  return backend->resumeHandshake(socket);
979 }
980 
988 {
989  Q_D(QDtls);
990 
991  auto *backend = d->backend.get();
992  if (!backend)
993  return false;
994 
995  if (!socket) {
996  backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
997  return false;
998  }
999 
1000  if (backend->state() != PeerVerificationFailed && backend->state() != HandshakeInProgress) {
1001  backend->setDtlsError(QDtlsError::InvalidOperation,
1002  tr("No handshake in progress, nothing to abort"));
1003  return false;
1004  }
1005 
1006  backend->abortHandshake(socket);
1007  return true;
1008 }
1009 
1018 {
1019  Q_D(QDtls);
1020 
1021  auto *backend = d->backend.get();
1022  if (!backend)
1023  return false;
1024 
1025  if (!socket) {
1026  backend->setDtlsError(QDtlsError::InvalidInputParameters,
1027  tr("Invalid (nullptr) socket"));
1028  return false;
1029  }
1030 
1031  if (!backend->isConnectionEncrypted()) {
1032  backend->setDtlsError(QDtlsError::InvalidOperation,
1033  tr("Cannot send shutdown alert, not encrypted"));
1034  return false;
1035  }
1036 
1037  backend->sendShutdownAlert(socket);
1038  return true;
1039 }
1040 
1047 {
1048  Q_D(const QDtls);
1049 
1050 
1051  if (const auto *backend = d->backend.get())
1052  return backend->isConnectionEncrypted();
1053 
1054  return false;
1055 }
1056 
1070 {
1071  Q_D(const QDtls);
1072 
1073  if (const auto *backend = d->backend.get())
1074  return backend->dtlsSessionCipher();
1075 
1076  return {};
1077 }
1078 
1090 {
1091  Q_D(const QDtls);
1092 
1093  if (const auto *backend = d->backend.get())
1094  return backend->dtlsSessionProtocol();
1095 
1096  return QSsl::UnknownProtocol;
1097 }
1098 
1108 {
1109  Q_D(QDtls);
1110 
1111  auto *backend = d->backend.get();
1112  if (!backend)
1113  return -1;
1114 
1115  if (!socket) {
1116  backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
1117  return -1;
1118  }
1119 
1120  if (!isConnectionEncrypted()) {
1121  backend->setDtlsError(QDtlsError::InvalidOperation,
1122  tr("Cannot write a datagram, not in encrypted state"));
1123  return -1;
1124  }
1125 
1126  return backend->writeDatagramEncrypted(socket, dgram);
1127 }
1128 
1136 {
1137  Q_D(QDtls);
1138 
1139  auto *backend = d->backend.get();
1140  if (!backend)
1141  return {};
1142 
1143  if (!socket) {
1144  backend->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
1145  return {};
1146  }
1147 
1148  if (!isConnectionEncrypted()) {
1149  backend->setDtlsError(QDtlsError::InvalidOperation,
1150  tr("Cannot read a datagram, not in encrypted state"));
1151  return {};
1152  }
1153 
1154  if (!dgram.size())
1155  return {};
1156 
1157  return backend->decryptDatagram(socket, dgram);
1158 }
1159 
1166 {
1167  Q_D(const QDtls);
1168 
1169  if (const auto *backend = d->backend.get())
1170  return backend->error();
1171 
1172  return QDtlsError::NoError;
1173 }
1174 
1182 {
1183  Q_D(const QDtls);
1184 
1185  if (const auto *backend = d->backend.get())
1186  return backend->errorString();
1187 
1188  return {};
1189 }
1190 
1198 {
1199  Q_D(const QDtls);
1200 
1201  if (const auto *backend = d->backend.get())
1202  return backend->peerVerificationErrors();
1203 
1204  //return d->tlsErrors;
1205  return {};
1206 }
1207 
1227 {
1228  Q_D(QDtls);
1229 
1230  if (auto *backend = d->backend.get())
1231  backend->ignoreVerificationErrors(errorsToIgnore);
1232 }
1233 
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
qsizetype size() const noexcept
Definition: qbytearray.h:470
This class implements server-side DTLS cookie generation and verification.
Definition: qdtls.h:80
QString dtlsErrorString() const
Definition: qdtls.cpp:527
GeneratorParameters cookieGeneratorParameters() const
Definition: qdtls.cpp:442
QByteArray verifiedHello() const
Definition: qdtls.cpp:497
bool verifyClient(QUdpSocket *socket, const QByteArray &dgram, const QHostAddress &address, quint16 port)
Definition: qdtls.cpp:467
QDtlsError dtlsError() const
Definition: qdtls.cpp:512
bool setCookieGeneratorParameters(const GeneratorParameters &params)
Definition: qdtls.cpp:423
QDtlsClientVerifier(QObject *parent=nullptr)
Definition: qdtls.cpp:390
This class provides encryption for UDP sockets.
Definition: qdtls.h:119
HandshakeState
Describes the current state of DTLS handshake.
Definition: qdtls.h:125
@ PeerVerificationFailed
Definition: qdtls.h:128
@ HandshakeNotStarted
Definition: qdtls.h:126
@ HandshakeInProgress
Definition: qdtls.h:127
bool setPeer(const QHostAddress &address, quint16 port, const QString &verificationName={})
Definition: qdtls.cpp:578
bool handleTimeout(QUdpSocket *socket)
Definition: qdtls.cpp:909
QSslConfiguration dtlsConfiguration() const
Definition: qdtls.cpp:803
qint64 writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram)
Definition: qdtls.cpp:1107
bool setDtlsConfiguration(const QSslConfiguration &configuration)
Definition: qdtls.cpp:779
bool doHandshake(QUdpSocket *socket, const QByteArray &dgram={})
Definition: qdtls.cpp:846
QString peerVerificationName() const
Definition: qdtls.cpp:675
bool shutdown(QUdpSocket *socket)
Definition: qdtls.cpp:1017
bool resumeHandshake(QUdpSocket *socket)
Definition: qdtls.cpp:959
quint16 peerPort() const
Definition: qdtls.cpp:659
void ignoreVerificationErrors(const QList< QSslError > &errorsToIgnore)
Definition: qdtls.cpp:1226
QString dtlsErrorString() const
Definition: qdtls.cpp:1181
~QDtls()
Definition: qdtls.cpp:567
QDtls(QSslSocket::SslMode mode, QObject *parent=nullptr)
Definition: qdtls.cpp:547
QByteArray decryptDatagram(QUdpSocket *socket, const QByteArray &dgram)
Definition: qdtls.cpp:1135
bool setCookieGeneratorParameters(const GeneratorParameters &params)
Definition: qdtls.cpp:740
bool isConnectionEncrypted() const
Definition: qdtls.cpp:1046
QList< QSslError > peerVerificationErrors() const
Definition: qdtls.cpp:1197
void setMtuHint(quint16 mtuHint)
Definition: qdtls.cpp:707
QSslSocket::SslMode sslMode() const
Definition: qdtls.cpp:691
HandshakeState handshakeState() const
Definition: qdtls.cpp:817
QDtlsError dtlsError() const
Definition: qdtls.cpp:1165
quint16 mtuHint() const
Definition: qdtls.cpp:720
QHostAddress peerAddress() const
Definition: qdtls.cpp:644
QSslCipher sessionCipher() const
Definition: qdtls.cpp:1069
bool abortHandshake(QUdpSocket *socket)
Definition: qdtls.cpp:987
GeneratorParameters cookieGeneratorParameters() const
Definition: qdtls.cpp:761
QSsl::SslProtocol sessionProtocol() const
Definition: qdtls.cpp:1089
bool setPeerVerificationName(const QString &name)
Definition: qdtls.cpp:619
The QHostAddress class provides an IP address.\inmodule QtNetwork.
Definition: qhostaddress.h:74
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
QObject * parent() const
Definition: qobject.h:409
The QSslCipher class represents an SSL cryptographic cipher.
Definition: qsslcipher.h:58
The QSslConfiguration class holds the configuration and state of an SSL connection.
@ SslServerMode
Definition: qsslsocket.h:72
@ UnencryptedMode
Definition: qsslsocket.h:70
static QTlsBackend * tlsBackendInUse()
The QString class provides a Unicode character string.
Definition: qstring.h:388
The QUdpSocket class provides a UDP socket.
Definition: qudpsocket.h:57
QHash< int, QWidget * > hash
[35multi]
SslProtocol
Definition: qssl.h:75
@ UnknownProtocol
Definition: qssl.h:94
QDtlsError
Definition: qdtls.h:61
@ TlsInitializationError
@ InvalidInputParameters
EGLOutputPortEXT port
unsigned short quint16
Definition: qglobal.h:286
long long qint64
Definition: qglobal.h:298
#define qCWarning(category,...)
GLenum mode
GLuint name
void ** params
GLuint GLuint64EXT address
Definition: qopenglext.h:11428
#define QStringLiteral(str)
#define tr(X)
QTcpSocket * socket
[1]
This class defines parameters for DTLS cookie generator.
Definition: qdtls.h:89
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent