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 "qdtls_openssl_p.h"
42 #include "qudpsocket.h"
43 #include "qdtls_p.h"
44 #include "qssl_p.h"
45 #include "qdtls.h"
46 
47 #include "qglobal.h"
48 
49 /*!
50     \class QDtlsClientVerifier
51     \brief This class implements server-side DTLS cookie generation and verification.
52     \since 5.12
53 
54     \ingroup network
55     \ingroup ssl
56     \inmodule QtNetwork
57 
58     The QDtlsClientVerifier class implements server-side DTLS cookie generation
59     and verification. Datagram security protocols are highly susceptible to a
60     variety of Denial-of-Service attacks. According to \l {https://tools.ietf.org/html/rfc6347#section-4.2.1}{RFC 6347, section 4.2.1},
61     these are two of the more common types of attack:
62 
63     \list
64     \li An attacker transmits a series of handshake initiation requests, causing
65     a server to allocate excessive resources and potentially perform expensive
66     cryptographic operations.
67     \li An attacker transmits a series of handshake initiation requests with
68     a forged source of the victim, making the server act as an amplifier.
69     Normally, the server would reply to the victim machine with a Certificate message,
70     which can be quite large, thus flooding the victim machine with datagrams.
71     \endlist
72 
73     As a countermeasure to these attacks, \l {https://tools.ietf.org/html/rfc6347#section-4.2.1}{RFC 6347, section 4.2.1}
74     proposes a stateless cookie technique that a server may deploy:
75 
76     \list
77     \li In response to the initial ClientHello message, the server sends a HelloVerifyRequest,
78     which contains a cookie. This cookie is a cryptographic hash and is generated using the
79     client's address, port number, and the server's secret (which is a cryptographically strong
80     pseudo-random sequence of bytes).
81     \li A reachable DTLS client is expected to reply with a new ClientHello message
82     containing this cookie.
83     \li When the server receives the ClientHello message with a cookie, it
84     generates a new cookie as described above. This new cookie is compared to the
85     one found in the ClientHello message.
86     \li In the cookies are equal, the client is considered to be real, and the
87     server can continue with a TLS handshake procedure.
88     \endlist
89 
90     \note A DTLS server is not required to use DTLS cookies.
91 
92     QDtlsClientVerifier is designed to work in pair with QUdpSocket, as shown in
93     the following code-excerpt:
94 
95     \snippet code/src_network_ssl_qdtlscookie.cpp 0
96 
97     QDtlsClientVerifier does not impose any restrictions on how the application uses
98     QUdpSocket. For example, it is possible to have a server with a single QUdpSocket
99     in state QAbstractSocket::BoundState, handling multiple DTLS clients
100     simultaneously:
101 
102     \list
103     \li Testing if new clients are real DTLS-capable clients.
104     \li Completing TLS handshakes with the verified clients (see QDtls).
105     \li Decrypting datagrams coming from the connected clients (see QDtls).
106     \li Sending encrypted datagrams to the connected clients (see QDtls).
107     \endlist
108 
109     This implies that QDtlsClientVerifier does not read directly from a socket,
110     instead it expects the application to read an incoming datagram, extract the
111     sender's address, and port, and then pass this data to verifyClient().
112     To send a HelloVerifyRequest message, verifyClient() can write to the QUdpSocket.
113 
114     \note QDtlsClientVerifier does not take ownership of the QUdpSocket object.
115 
116     By default QDtlsClientVerifier obtains its secret from a cryptographically
117     strong pseudorandom number generator.
118 
119     \note The default secret is shared by all objects of the classes QDtlsClientVerifier
120     and QDtls. Since this can impose security risks, RFC 6347 recommends to change
121     the server's secret frequently. Please see \l {https://tools.ietf.org/html/rfc6347}{RFC 6347, section 4.2.1}
122     for hints about possible server implementations. Cookie generator parameters
123     can be set using the class QDtlsClientVerifier::GeneratorParameters and
124     setCookieGeneratorParameters():
125 
126     \snippet code/src_network_ssl_qdtlscookie.cpp 1
127 
128     The \l{secureudpserver}{DTLS server} example illustrates how to use
129     QDtlsClientVerifier in a server application.
130 
131     \sa QUdpSocket, QAbstractSocket::BoundState, QDtls, verifyClient(),
132     GeneratorParameters, setCookieGeneratorParameters(), cookieGeneratorParameters(),
133     QDtls::setCookieGeneratorParameters(),
134     QDtls::cookieGeneratorParameters(),
135     QCryptographicHash::Algorithm,
136     QDtlsError, dtlsError(), dtlsErrorString()
137 */
138 
139 /*!
140     \class QDtlsClientVerifier::GeneratorParameters
141     \brief This class defines parameters for DTLS cookie generator.
142     \since 5.12
143 
144     \ingroup network
145     \ingroup ssl
146     \inmodule QtNetwork
147 
148     An object of this class provides the parameters that QDtlsClientVerifier
149     will use to generate DTLS cookies. They include a cryptographic hash
150     algorithm and a secret.
151 
152     \note An empty secret is considered to be invalid by
153     QDtlsClientVerifier::setCookieGeneratorParameters().
154 
155     \sa QDtlsClientVerifier::setCookieGeneratorParameters(),
156     QDtlsClientVerifier::cookieGeneratorParameters(),
157     QDtls::setCookieGeneratorParameters(),
158     QDtls::cookieGeneratorParameters(),
159     QCryptographicHash::Algorithm
160 */
161 
162 /*!
163     \enum QDtlsError
164     \brief Describes errors that can be found by QDtls and QDtlsClientVerifier.
165     \relates QDtls
166     \since 5.12
167 
168     \ingroup network
169     \ingroup ssl
170     \inmodule QtNetwork
171 
172     This enum describes general and TLS-specific errors that can be encountered
173     by objects of the classes QDtlsClientVerifier and QDtls.
174 
175     \value NoError No error occurred, the last operation was successful.
176     \value InvalidInputParameters Input parameters provided by a caller were
177            invalid.
178     \value InvalidOperation An operation was attempted in a state that did not
179            permit it.
180     \value UnderlyingSocketError QUdpSocket::writeDatagram() failed, QUdpSocket::error()
181            and QUdpSocket::errorString() can provide more specific information.
182     \value RemoteClosedConnectionError TLS shutdown alert message was received.
183     \value PeerVerificationError Peer's identity could not be verified during the
184            TLS handshake.
185     \value TlsInitializationError An error occurred while initializing an underlying
186            TLS backend.
187     \value TlsFatalError A fatal error occurred during TLS handshake, other
188            than peer verification error or TLS initialization error.
189     \value TlsNonFatalError A failure to encrypt or decrypt a datagram, non-fatal,
190            meaning QDtls can continue working after this error.
191 */
192 
193 /*!
194     \class QDtls
195     \brief This class provides encryption for UDP sockets.
196     \since 5.12
197 
198     \ingroup network
199     \ingroup ssl
200     \inmodule QtNetwork
201 
202     The QDtls class can be used to establish a secure connection with a network
203     peer using User Datagram Protocol (UDP). DTLS connection over essentially
204     connectionless UDP means that two peers first have to successfully complete
205     a TLS handshake by calling doHandshake(). After the handshake has completed,
206     encrypted datagrams can be sent to the peer using writeDatagramEncrypted().
207     Encrypted datagrams coming from the peer can be decrypted by decryptDatagram().
208 
209     QDtls is designed to work with QUdpSocket. Since QUdpSocket can receive
210     datagrams coming from different peers, an application must implement
211     demultiplexing, forwarding datagrams coming from different peers to their
212     corresponding instances of QDtls. An association between a network peer
213     and its QDtls object can be established using the peer's address and port
214     number. Before starting a handshake, the application must set the peer's
215     address and port number using setPeer().
216 
217     QDtls does not read datagrams from QUdpSocket, this is expected to be done by
218     the application, for example, in a slot attached to the QUdpSocket::readyRead()
219     signal. Then, these datagrams must be processed by QDtls.
220 
221     \note QDtls does \e not take ownership of the QUdpSocket object.
222 
223     Normally, several datagrams are to be received and sent by both peers during
224     the handshake phase. Upon reading datagrams, server and client must pass these
225     datagrams to doHandshake() until some error is found or handshakeState()
226     returns HandshakeComplete:
227 
228     \snippet code/src_network_ssl_qdtls.cpp 0
229 
230     For a server, the first call to doHandshake() requires a non-empty datagram
231     containing a ClientHello message. If the server also deploys QDtlsClientVerifier,
232     the first ClientHello message is expected to be the one verified by QDtlsClientVerifier.
233 
234     In case the peer's identity cannot be validated during the handshake, the application
235     must inspect errors returned by peerVerificationErrors() and then either
236     ignore errors by calling ignoreVerificationErrors() or abort the handshake
237     by calling abortHandshake(). If errors were ignored, the handshake can be
238     resumed by calling resumeHandshake().
239 
240     After the handshake has been completed, datagrams can be sent to and received
241     from the network peer securely:
242 
243     \snippet code/src_network_ssl_qdtls.cpp 2
244 
245     A DTLS connection may be closed using shutdown().
246 
247     \snippet code/src_network_ssl_qdtls.cpp 3
248 
249     \warning It's recommended to call shutdown() before destroying the client's QDtls
250     object if you are planning to re-use the same port number to connect to the
251     server later. Otherwise, the server may drop incoming ClientHello messages,
252     see \l{https://tools.ietf.org/html/rfc6347#page-25}{RFC 6347, section 4.2.8}
253     for more details and implementation hints.
254 
255     If the server does not use QDtlsClientVerifier, it \e must configure its
256     QDtls objects to disable the cookie verification procedure:
257 
258     \snippet code/src_network_ssl_qdtls.cpp 4
259 
260     A server that uses cookie verification with non-default generator parameters
261     \e must set the same parameters for its QDtls object before starting the handshake.
262 
263     \note The DTLS protocol leaves Path Maximum Transmission Unit (PMTU) discovery
264     to the application. The application may provide QDtls with the MTU using
265     setMtuHint(). This hint affects only the handshake phase, since only handshake
266     messages can be fragmented and reassembled by the DTLS. All other messages sent
267     by the application must fit into a single datagram.
268     \note DTLS-specific headers add some overhead to application data further
269     reducing the possible message size.
270     \warning A server configured to reply with HelloVerifyRequest will drop
271     all fragmented ClientHello messages, never starting a handshake.
272 
273     The \l{secureudpserver}{DTLS server} and \l{secureudpclient}{DTLS client}
274     examples illustrate how to use QDtls in applications.
275 
276     \sa QUdpSocket, QDtlsClientVerifier, HandshakeState, QDtlsError, QSslConfiguration
277 */
278 
279 /*!
280     \typedef QDtls::GeneratorParameters
281 */
282 
283 /*!
284     \fn void QDtls::handshakeTimeout()
285 
286     Packet loss can result in timeouts during the handshake phase. In this case
287     QDtls emits a handshakeTimeout() signal. Call handleTimeout() to retransmit
288     the handshake messages:
289 
290     \snippet code/src_network_ssl_qdtls.cpp 1
291 
292     \sa handleTimeout()
293 */
294 
295 /*!
296     \fn void QDtls::pskRequired(QSslPreSharedKeyAuthenticator *authenticator)
297 
298     QDtls emits this signal when it negotiates a PSK ciphersuite, and therefore
299     a PSK authentication is then required.
300 
301     When using PSK, the client must send to the server a valid identity and a
302     valid pre shared key, in order for the TLS handshake to continue.
303     Applications can provide this information in a slot connected to this
304     signal, by filling in the passed \a authenticator object according to their
305     needs.
306 
307     \note Ignoring this signal, or failing to provide the required credentials,
308     will cause the handshake to fail, and therefore the connection to be aborted.
309 
310     \note The \a authenticator object is owned by QDtls and must not be deleted
311     by the application.
312 
313     \sa QSslPreSharedKeyAuthenticator
314 */
315 
316 /*!
317     \enum QDtls::HandshakeState
318     \brief Describes the current state of DTLS handshake.
319     \since 5.12
320 
321     \ingroup network
322     \ingroup ssl
323     \inmodule QtNetwork
324 
325     This enum describes the current state of DTLS handshake for a QDtls
326     connection.
327 
328     \value HandshakeNotStarted Nothing done yet.
329     \value HandshakeInProgress Handshake was initiated and no errors were found so far.
330     \value PeerVerificationFailed The identity of the peer can't be established.
331     \value HandshakeComplete Handshake completed successfully and encrypted connection
332            was established.
333 
334     \sa QDtls::doHandshake(), QDtls::handshakeState()
335 */
336 
337 
338 QT_BEGIN_NAMESPACE
339 
configuration() const340 QSslConfiguration QDtlsBasePrivate::configuration() const
341 {
342     auto copyPrivate = new QSslConfigurationPrivate(dtlsConfiguration);
343     copyPrivate->ref.storeRelaxed(0); // the QSslConfiguration constructor refs up
344     QSslConfiguration copy(copyPrivate);
345     copyPrivate->sessionCipher = sessionCipher;
346     copyPrivate->sessionProtocol = sessionProtocol;
347 
348     return copy;
349 }
350 
setConfiguration(const QSslConfiguration & configuration)351 void QDtlsBasePrivate::setConfiguration(const QSslConfiguration &configuration)
352 {
353     dtlsConfiguration.localCertificateChain = configuration.localCertificateChain();
354     dtlsConfiguration.privateKey = configuration.privateKey();
355     dtlsConfiguration.ciphers = configuration.ciphers();
356     dtlsConfiguration.ellipticCurves = configuration.ellipticCurves();
357     dtlsConfiguration.preSharedKeyIdentityHint = configuration.preSharedKeyIdentityHint();
358     dtlsConfiguration.dhParams = configuration.diffieHellmanParameters();
359     dtlsConfiguration.caCertificates = configuration.caCertificates();
360     dtlsConfiguration.peerVerifyDepth = configuration.peerVerifyDepth();
361     dtlsConfiguration.peerVerifyMode = configuration.peerVerifyMode();
362     dtlsConfiguration.protocol = configuration.protocol();
363     dtlsConfiguration.sslOptions = configuration.d->sslOptions;
364     dtlsConfiguration.sslSession = configuration.sessionTicket();
365     dtlsConfiguration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint();
366     dtlsConfiguration.nextAllowedProtocols = configuration.allowedNextProtocols();
367     dtlsConfiguration.nextNegotiatedProtocol = configuration.nextNegotiatedProtocol();
368     dtlsConfiguration.nextProtocolNegotiationStatus = configuration.nextProtocolNegotiationStatus();
369     dtlsConfiguration.dtlsCookieEnabled = configuration.dtlsCookieVerificationEnabled();
370     dtlsConfiguration.allowRootCertOnDemandLoading = configuration.d->allowRootCertOnDemandLoading;
371     dtlsConfiguration.backendConfig = configuration.backendConfiguration();
372 
373     clearDtlsError();
374 }
375 
setCookieGeneratorParameters(QCryptographicHash::Algorithm alg,const QByteArray & key)376 bool QDtlsBasePrivate::setCookieGeneratorParameters(QCryptographicHash::Algorithm alg,
377                                                     const QByteArray &key)
378 {
379     if (!key.size()) {
380         setDtlsError(QDtlsError::InvalidInputParameters,
381                      QDtls::tr("Invalid (empty) secret"));
382         return false;
383     }
384 
385     clearDtlsError();
386 
387     hashAlgorithm = alg;
388     secret = key;
389 
390     return true;
391 }
392 
isDtlsProtocol(QSsl::SslProtocol protocol)393 bool QDtlsBasePrivate::isDtlsProtocol(QSsl::SslProtocol protocol)
394 {
395     switch (protocol) {
396     case QSsl::DtlsV1_0:
397     case QSsl::DtlsV1_0OrLater:
398     case QSsl::DtlsV1_2:
399     case QSsl::DtlsV1_2OrLater:
400         return true;
401     default:
402         return false;
403     }
404 }
405 
msgUnsupportedMulticastAddress()406 static QString msgUnsupportedMulticastAddress()
407 {
408     return QDtls::tr("Multicast and broadcast addresses are not supported");
409 }
410 
411 /*!
412     Default constructs GeneratorParameters object with QCryptographicHash::Sha1
413     as its algorithm and an empty secret.
414 
415     \sa QDtlsClientVerifier::setCookieGeneratorParameters(),
416     QDtlsClientVerifier::cookieGeneratorParameters(),
417     QDtls::setCookieGeneratorParameters(),
418     QDtls::cookieGeneratorParameters()
419  */
GeneratorParameters()420 QDtlsClientVerifier::GeneratorParameters::GeneratorParameters()
421 {
422 }
423 
424 /*!
425     Constructs GeneratorParameters object from \a algorithm and \a secret.
426 
427     \sa QDtlsClientVerifier::setCookieGeneratorParameters(),
428     QDtlsClientVerifier::cookieGeneratorParameters(),
429     QDtls::setCookieGeneratorParameters(),
430     QDtls::cookieGeneratorParameters()
431  */
GeneratorParameters(QCryptographicHash::Algorithm algorithm,const QByteArray & secret)432 QDtlsClientVerifier::GeneratorParameters::GeneratorParameters(QCryptographicHash::Algorithm algorithm, const QByteArray &secret)
433     : hash(algorithm), secret(secret)
434 {
435 }
436 
437 /*!
438     Constructs a QDtlsClientVerifier object, \a parent is passed to QObject's
439     constructor.
440 */
QDtlsClientVerifier(QObject * parent)441 QDtlsClientVerifier::QDtlsClientVerifier(QObject *parent)
442     : QObject(*new QDtlsClientVerifierOpenSSL, parent)
443 {
444     Q_D(QDtlsClientVerifier);
445 
446     d->mode = QSslSocket::SslServerMode;
447     // The default configuration suffices: verifier never does a full
448     // handshake and upon verifying a cookie in a client hello message,
449     // it reports success.
450     auto conf = QSslConfiguration::defaultDtlsConfiguration();
451     conf.setPeerVerifyMode(QSslSocket::VerifyNone);
452     d->setConfiguration(conf);
453 }
454 
455 /*!
456     Destroys the QDtlsClientVerifier object.
457 */
~QDtlsClientVerifier()458 QDtlsClientVerifier::~QDtlsClientVerifier()
459 {
460 }
461 
462 /*!
463     Sets the secret and the cryptographic hash algorithm from \a params. This
464     QDtlsClientVerifier will use these to generate cookies. If the new secret
465     has size zero, this function returns \c false and does not change the
466     cookie generator parameters.
467 
468     \note The secret is supposed to be a cryptographically secure sequence of bytes.
469 
470     \sa QDtlsClientVerifier::GeneratorParameters, cookieGeneratorParameters(),
471     QCryptographicHash::Algorithm
472 */
setCookieGeneratorParameters(const GeneratorParameters & params)473 bool QDtlsClientVerifier::setCookieGeneratorParameters(const GeneratorParameters &params)
474 {
475     Q_D(QDtlsClientVerifier);
476 
477     return d->setCookieGeneratorParameters(params.hash, params.secret);
478 }
479 
480 /*!
481     Returns the current secret and hash algorithm used to generate cookies.
482     The default hash algorithm is QCryptographicHash::Sha256 if Qt was configured
483     to support it, QCryptographicHash::Sha1 otherwise. The default secret is
484     obtained from the backend-specific cryptographically strong pseudorandom
485     number generator.
486 
487     \sa QCryptographicHash::Algorithm, QDtlsClientVerifier::GeneratorParameters,
488     setCookieGeneratorParameters()
489 */
cookieGeneratorParameters() const490 QDtlsClientVerifier::GeneratorParameters QDtlsClientVerifier::cookieGeneratorParameters() const
491 {
492     Q_D(const QDtlsClientVerifier);
493 
494     return {d->hashAlgorithm, d->secret};
495 }
496 
497 /*!
498     \a socket must be a valid pointer, \a dgram must be a non-empty
499     datagram, \a address cannot be null, broadcast, or multicast.
500     \a port is the remote peer's port. This function returns \c true
501     if \a dgram contains a ClientHello message with a valid cookie.
502     If no matching cookie is found, verifyClient() will send a
503     HelloVerifyRequest message using \a socket and return \c false.
504 
505     The following snippet shows how a server application may check for errors:
506 
507     \snippet code/src_network_ssl_qdtlscookie.cpp 2
508 
509     \sa QHostAddress::isNull(), QHostAddress::isBroadcast(), QHostAddress::isMulticast(),
510     setCookieGeneratorParameters(), cookieGeneratorParameters()
511 */
verifyClient(QUdpSocket * socket,const QByteArray & dgram,const QHostAddress & address,quint16 port)512 bool QDtlsClientVerifier::verifyClient(QUdpSocket *socket, const QByteArray &dgram,
513                                        const QHostAddress &address, quint16 port)
514 {
515     Q_D(QDtlsClientVerifier);
516 
517     if (!socket || address.isNull() || !dgram.size()) {
518         d->setDtlsError(QDtlsError::InvalidInputParameters,
519                         tr("A valid UDP socket, non-empty datagram, valid address/port were expected"));
520         return false;
521     }
522 
523     if (address.isBroadcast() || address.isMulticast()) {
524         d->setDtlsError(QDtlsError::InvalidInputParameters,
525                         msgUnsupportedMulticastAddress());
526         return false;
527     }
528 
529     return d->verifyClient(socket, dgram, address, port);
530 }
531 
532 /*!
533     Convenience function. Returns the last ClientHello message that was successfully
534     verified, or an empty QByteArray if no verification has completed.
535 
536     \sa verifyClient()
537 */
verifiedHello() const538 QByteArray QDtlsClientVerifier::verifiedHello() const
539 {
540     Q_D(const QDtlsClientVerifier);
541 
542     return d->verifiedClientHello;
543 }
544 
545 /*!
546     Returns the last error that occurred or QDtlsError::NoError.
547 
548     \sa QDtlsError, dtlsErrorString()
549 */
dtlsError() const550 QDtlsError QDtlsClientVerifier::dtlsError() const
551 {
552     Q_D(const QDtlsClientVerifier);
553 
554     return d->errorCode;
555 }
556 
557 /*!
558     Returns a textual description of the last error, or an empty string.
559 
560     \sa dtlsError()
561  */
dtlsErrorString() const562 QString QDtlsClientVerifier::dtlsErrorString() const
563 {
564     Q_D(const QDtlsBase);
565 
566     return d->errorDescription;
567 }
568 
569 /*!
570     Creates a QDtls object, \a parent is passed to the QObject constructor.
571     \a mode is QSslSocket::SslServerMode for a server-side DTLS connection or
572     QSslSocket::SslClientMode for a client.
573 
574     \sa sslMode(), QSslSocket::SslMode
575 */
QDtls(QSslSocket::SslMode mode,QObject * parent)576 QDtls::QDtls(QSslSocket::SslMode mode, QObject *parent)
577     : QObject(*new QDtlsPrivateOpenSSL, parent)
578 {
579     Q_D(QDtls);
580 
581     d->mode = mode;
582     setDtlsConfiguration(QSslConfiguration::defaultDtlsConfiguration());
583 }
584 
585 /*!
586     Destroys the QDtls object.
587 */
~QDtls()588 QDtls::~QDtls()
589 {
590 }
591 
592 /*!
593     Sets the peer's address, \a port, and host name and returns \c true
594     if successful. \a address must not be null, multicast, or broadcast.
595     \a verificationName is the host name used for the certificate validation.
596 
597     \sa peerAddress(), peerPort(), peerVerificationName()
598  */
setPeer(const QHostAddress & address,quint16 port,const QString & verificationName)599 bool QDtls::setPeer(const QHostAddress &address, quint16 port,
600                     const QString &verificationName)
601 {
602     Q_D(QDtls);
603 
604     if (d->handshakeState != HandshakeNotStarted) {
605         d->setDtlsError(QDtlsError::InvalidOperation,
606                         tr("Cannot set peer after handshake started"));
607         return false;
608     }
609 
610     if (address.isNull()) {
611         d->setDtlsError(QDtlsError::InvalidInputParameters,
612                         tr("Invalid address"));
613         return false;
614     }
615 
616     if (address.isBroadcast() || address.isMulticast()) {
617         d->setDtlsError(QDtlsError::InvalidInputParameters,
618                         msgUnsupportedMulticastAddress());
619         return false;
620     }
621 
622     d->clearDtlsError();
623 
624     d->remoteAddress = address;
625     d->remotePort = port;
626     d->peerVerificationName = verificationName;
627 
628     return true;
629 }
630 
631 /*!
632     Sets the host \a name that will be used for the certificate validation
633     and returns \c true if successful.
634 
635     \note This function must be called before the handshake starts.
636 
637     \sa peerVerificationName(), setPeer()
638 */
setPeerVerificationName(const QString & name)639 bool QDtls::setPeerVerificationName(const QString &name)
640 {
641     Q_D(QDtls);
642 
643     if (d->handshakeState != HandshakeNotStarted) {
644         d->setDtlsError(QDtlsError::InvalidOperation,
645                         tr("Cannot set verification name after handshake started"));
646         return false;
647     }
648 
649     d->clearDtlsError();
650     d->peerVerificationName = name;
651 
652     return true;
653 }
654 
655 /*!
656     Returns the peer's address, set by setPeer(), or QHostAddress::Null.
657 
658     \sa setPeer()
659 */
peerAddress() const660 QHostAddress QDtls::peerAddress() const
661 {
662     Q_D(const QDtls);
663 
664     return d->remoteAddress;
665 }
666 
667 /*!
668     Returns the peer's port number, set by setPeer(), or 0.
669 
670     \sa setPeer()
671 */
peerPort() const672 quint16 QDtls::peerPort() const
673 {
674     Q_D(const QDtlsBase);
675 
676     return d->remotePort;
677 }
678 
679 /*!
680     Returns the host name set by setPeer() or setPeerVerificationName().
681     The default value is an empty string.
682 
683     \sa setPeerVerificationName(), setPeer()
684 */
peerVerificationName() const685 QString QDtls::peerVerificationName() const
686 {
687     Q_D(const QDtls);
688 
689     return d->peerVerificationName;
690 }
691 
692 /*!
693     Returns QSslSocket::SslServerMode for a server-side connection and
694     QSslSocket::SslClientMode for a client.
695 
696     \sa QDtls(), QSslSocket::SslMode
697 */
sslMode() const698 QSslSocket::SslMode QDtls::sslMode() const
699 {
700     Q_D(const QDtls);
701 
702     return d->mode;
703 }
704 
705 /*!
706     \a mtuHint is the maximum transmission unit (MTU), either discovered or guessed
707     by the application. The application is not required to set this value.
708 
709     \sa mtuHint(), QAbstractSocket::PathMtuSocketOption
710  */
setMtuHint(quint16 mtuHint)711 void QDtls::setMtuHint(quint16 mtuHint)
712 {
713     Q_D(QDtls);
714 
715     d->mtuHint = mtuHint;
716 }
717 
718 /*!
719     Returns the value previously set by setMtuHint(). The default value is 0.
720 
721     \sa setMtuHint()
722  */
mtuHint() const723 quint16 QDtls::mtuHint() const
724 {
725     Q_D(const QDtls);
726 
727     return d->mtuHint;
728 }
729 
730 /*!
731     Sets the cryptographic hash algorithm and the secret from \a params.
732     This function is only needed for a server-side QDtls connection.
733     Returns \c true if successful.
734 
735     \note This function must be called before the handshake starts.
736 
737     \sa cookieGeneratorParameters(), doHandshake(), QDtlsClientVerifier,
738     QDtlsClientVerifier::cookieGeneratorParameters()
739 */
setCookieGeneratorParameters(const GeneratorParameters & params)740 bool QDtls::setCookieGeneratorParameters(const GeneratorParameters &params)
741 {
742     Q_D(QDtls);
743 
744     return d->setCookieGeneratorParameters(params.hash, params.secret);
745 }
746 
747 /*!
748     Returns the current hash algorithm and secret, either default ones or previously
749     set by a call to setCookieGeneratorParameters().
750 
751     The default hash algorithm is QCryptographicHash::Sha256 if Qt was
752     configured to support it, QCryptographicHash::Sha1 otherwise. The default
753     secret is obtained from the backend-specific cryptographically strong
754     pseudorandom number generator.
755 
756     \sa QDtlsClientVerifier, cookieGeneratorParameters()
757 */
cookieGeneratorParameters() const758 QDtls::GeneratorParameters QDtls::cookieGeneratorParameters() const
759 {
760     Q_D(const QDtls);
761 
762     return {d->hashAlgorithm, d->secret};
763 }
764 
765 /*!
766     Sets the connection's TLS configuration from \a configuration
767     and returns \c true if successful.
768 
769     \note This function must be called before the handshake starts.
770 
771     \sa dtlsConfiguration(), doHandshake()
772 */
setDtlsConfiguration(const QSslConfiguration & configuration)773 bool QDtls::setDtlsConfiguration(const QSslConfiguration &configuration)
774 {
775     Q_D(QDtls);
776 
777     if (d->handshakeState != HandshakeNotStarted) {
778         d->setDtlsError(QDtlsError::InvalidOperation,
779                         tr("Cannot set configuration after handshake started"));
780         return false;
781     }
782 
783     d->setConfiguration(configuration);
784     return true;
785 }
786 
787 /*!
788     Returns either the default DTLS configuration or the configuration set by an
789     earlier call to setDtlsConfiguration().
790 
791     \sa setDtlsConfiguration(), QSslConfiguration::defaultDtlsConfiguration()
792 */
dtlsConfiguration() const793 QSslConfiguration QDtls::dtlsConfiguration() const
794 {
795     Q_D(const QDtls);
796 
797     return d->configuration();
798 }
799 
800 /*!
801     Returns the current handshake state for this QDtls.
802 
803     \sa doHandshake(), QDtls::HandshakeState
804  */
handshakeState() const805 QDtls::HandshakeState QDtls::handshakeState()const
806 {
807     Q_D(const QDtls);
808 
809     return d->handshakeState;
810 }
811 
812 /*!
813     Starts or continues a DTLS handshake. \a socket must be a valid pointer.
814     When starting a server-side DTLS handshake, \a dgram must contain the initial
815     ClientHello message read from QUdpSocket. This function returns \c true if
816     no error was found. Handshake state can be tested using handshakeState().
817     \c false return means some error occurred, use dtlsError() for more
818     detailed information.
819 
820     \note If the identity of the peer can't be established, the error is set to
821     QDtlsError::PeerVerificationError. If you want to ignore verification errors
822     and continue connecting, you must call ignoreVerificationErrors() and then
823     resumeHandshake(). If the errors cannot be ignored, you must call
824     abortHandshake().
825 
826     \snippet code/src_network_ssl_qdtls.cpp 5
827 
828     \sa handshakeState(), dtlsError(), ignoreVerificationErrors(), resumeHandshake(),
829     abortHandshake()
830 */
doHandshake(QUdpSocket * socket,const QByteArray & dgram)831 bool QDtls::doHandshake(QUdpSocket *socket, const QByteArray &dgram)
832 {
833     Q_D(QDtls);
834 
835     if (d->handshakeState == HandshakeNotStarted)
836         return startHandshake(socket, dgram);
837     else if (d->handshakeState == HandshakeInProgress)
838         return continueHandshake(socket, dgram);
839 
840     d->setDtlsError(QDtlsError::InvalidOperation,
841                     tr("Cannot start/continue handshake, invalid handshake state"));
842     return false;
843 }
844 
845 /*!
846     \internal
847 */
startHandshake(QUdpSocket * socket,const QByteArray & datagram)848 bool QDtls::startHandshake(QUdpSocket *socket, const QByteArray &datagram)
849 {
850     Q_D(QDtls);
851 
852     if (!socket) {
853         d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
854         return false;
855     }
856 
857     if (d->remoteAddress.isNull()) {
858         d->setDtlsError(QDtlsError::InvalidOperation,
859                         tr("To start a handshake you must set peer's address and port first"));
860         return false;
861     }
862 
863     if (sslMode() == QSslSocket::SslServerMode && !datagram.size()) {
864         d->setDtlsError(QDtlsError::InvalidInputParameters,
865                         tr("To start a handshake, DTLS server requires non-empty datagram (client hello)"));
866         return false;
867     }
868 
869     if (d->handshakeState != HandshakeNotStarted) {
870         d->setDtlsError(QDtlsError::InvalidOperation,
871                         tr("Cannot start handshake, already done/in progress"));
872         return false;
873     }
874 
875     return d->startHandshake(socket, datagram);
876 }
877 
878 /*!
879     If a timeout occures during the handshake, the handshakeTimeout() signal
880     is emitted. The application must call handleTimeout() to retransmit handshake
881     messages; handleTimeout() returns \c true if a timeout has occurred, false
882     otherwise. \a socket must be a valid pointer.
883 
884     \sa handshakeTimeout()
885 */
handleTimeout(QUdpSocket * socket)886 bool QDtls::handleTimeout(QUdpSocket *socket)
887 {
888     Q_D(QDtls);
889 
890     if (!socket) {
891         d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
892         return false;
893     }
894 
895     return d->handleTimeout(socket);
896 }
897 
898 /*!
899     \internal
900 */
continueHandshake(QUdpSocket * socket,const QByteArray & datagram)901 bool QDtls::continueHandshake(QUdpSocket *socket, const QByteArray &datagram)
902 {
903     Q_D(QDtls);
904 
905     if (!socket || !datagram.size()) {
906         d->setDtlsError(QDtlsError::InvalidInputParameters,
907                         tr("A valid QUdpSocket and non-empty datagram are needed to continue the handshake"));
908         return false;
909     }
910 
911     if (d->handshakeState != HandshakeInProgress) {
912         d->setDtlsError(QDtlsError::InvalidOperation,
913                         tr("Cannot continue handshake, not in InProgress state"));
914         return false;
915     }
916 
917     return d->continueHandshake(socket, datagram);
918 }
919 
920 /*!
921     If peer verification errors were ignored during the handshake,
922     resumeHandshake() resumes and completes the handshake and returns
923     \c true. \a socket must be a valid pointer. Returns \c false if
924     the handshake could not be resumed.
925 
926     \sa doHandshake(), abortHandshake() peerVerificationErrors(), ignoreVerificationErrors()
927 */
resumeHandshake(QUdpSocket * socket)928 bool QDtls::resumeHandshake(QUdpSocket *socket)
929 {
930     Q_D(QDtls);
931 
932     if (!socket) {
933         d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
934         return false;
935     }
936 
937     if (d->handshakeState != PeerVerificationFailed) {
938         d->setDtlsError(QDtlsError::InvalidOperation,
939                         tr("Cannot resume, not in VerificationError state"));
940         return false;
941     }
942 
943     return d->resumeHandshake(socket);
944 }
945 
946 /*!
947     Aborts the ongoing handshake. Returns true if one was on-going on \a socket;
948     otherwise, sets a suitable error and returns false.
949 
950     \sa doHandshake(), resumeHandshake()
951  */
abortHandshake(QUdpSocket * socket)952 bool QDtls::abortHandshake(QUdpSocket *socket)
953 {
954     Q_D(QDtls);
955 
956     if (!socket) {
957         d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
958         return false;
959     }
960 
961     if (d->handshakeState != PeerVerificationFailed && d->handshakeState != HandshakeInProgress) {
962         d->setDtlsError(QDtlsError::InvalidOperation,
963                         tr("No handshake in progress, nothing to abort"));
964         return false;
965     }
966 
967     d->abortHandshake(socket);
968     return true;
969 }
970 
971 /*!
972     Sends an encrypted shutdown alert message and closes the DTLS connection.
973     Handshake state changes to QDtls::HandshakeNotStarted. \a socket must be a
974     valid pointer. This function returns \c true on success.
975 
976     \sa doHandshake()
977  */
shutdown(QUdpSocket * socket)978 bool QDtls::shutdown(QUdpSocket *socket)
979 {
980     Q_D(QDtls);
981 
982     if (!socket) {
983         d->setDtlsError(QDtlsError::InvalidInputParameters,
984                         tr("Invalid (nullptr) socket"));
985         return false;
986     }
987 
988     if (!d->connectionEncrypted) {
989         d->setDtlsError(QDtlsError::InvalidOperation,
990                         tr("Cannot send shutdown alert, not encrypted"));
991         return false;
992     }
993 
994     d->sendShutdownAlert(socket);
995     return true;
996 }
997 
998 /*!
999     Returns \c true if DTLS handshake completed successfully.
1000 
1001     \sa doHandshake(), handshakeState()
1002  */
isConnectionEncrypted() const1003 bool QDtls::isConnectionEncrypted() const
1004 {
1005     Q_D(const QDtls);
1006 
1007     return d->connectionEncrypted;
1008 }
1009 
1010 /*!
1011     Returns the cryptographic \l {QSslCipher} {cipher} used by this connection,
1012     or a null cipher if the connection isn't encrypted. The cipher for the
1013     session is selected during the handshake phase. The cipher is used to encrypt
1014     and decrypt data.
1015 
1016     QSslConfiguration provides functions for setting the ordered list of ciphers
1017     from which the handshake phase will eventually select the session cipher.
1018     This ordered list must be in place before the handshake phase begins.
1019 
1020     \sa QSslConfiguration, setDtlsConfiguration(), dtlsConfiguration()
1021 */
sessionCipher() const1022 QSslCipher QDtls::sessionCipher() const
1023 {
1024     Q_D(const QDtls);
1025 
1026     return d->sessionCipher;
1027 }
1028 
1029 /*!
1030     Returns the DTLS protocol version used by this connection, or UnknownProtocol
1031     if the connection isn't encrypted yet. The protocol for the connection is selected
1032     during the handshake phase.
1033 
1034     setDtlsConfiguration() can set the preferred version before the handshake starts.
1035 
1036     \sa setDtlsConfiguration(), QSslConfiguration, QSslConfiguration::defaultDtlsConfiguration(),
1037     QSslConfiguration::setProtocol()
1038 */
sessionProtocol() const1039 QSsl::SslProtocol QDtls::sessionProtocol() const
1040 {
1041     Q_D(const QDtls);
1042 
1043     return d->sessionProtocol;
1044 }
1045 
1046 /*!
1047     Encrypts \a dgram and writes the encrypted data into \a socket. Returns the
1048     number of bytes written, or -1 in case of error. The handshake must be completed
1049     before writing encrypted data. \a socket must be a valid
1050     pointer.
1051 
1052     \sa doHandshake(), handshakeState(), isConnectionEncrypted(), dtlsError()
1053 */
writeDatagramEncrypted(QUdpSocket * socket,const QByteArray & dgram)1054 qint64 QDtls::writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram)
1055 {
1056     Q_D(QDtls);
1057 
1058     if (!socket) {
1059         d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
1060         return -1;
1061     }
1062 
1063     if (!isConnectionEncrypted()) {
1064         d->setDtlsError(QDtlsError::InvalidOperation,
1065                         tr("Cannot write a datagram, not in encrypted state"));
1066         return -1;
1067     }
1068 
1069     return d->writeDatagramEncrypted(socket, dgram);
1070 }
1071 
1072 /*!
1073     Decrypts \a dgram and returns its contents as plain text. The handshake must
1074     be completed before datagrams can be decrypted. Depending on the type of the
1075     TLS message the connection may write into \a socket, which must be a valid
1076     pointer.
1077 */
decryptDatagram(QUdpSocket * socket,const QByteArray & dgram)1078 QByteArray QDtls::decryptDatagram(QUdpSocket *socket, const QByteArray &dgram)
1079 {
1080     Q_D(QDtls);
1081 
1082     if (!socket) {
1083         d->setDtlsError(QDtlsError::InvalidInputParameters, tr("Invalid (nullptr) socket"));
1084         return {};
1085     }
1086 
1087     if (!isConnectionEncrypted()) {
1088         d->setDtlsError(QDtlsError::InvalidOperation,
1089                         tr("Cannot read a datagram, not in encrypted state"));
1090         return {};
1091     }
1092 
1093     if (!dgram.size())
1094         return {};
1095 
1096     return d->decryptDatagram(socket, dgram);
1097 }
1098 
1099 /*!
1100     Returns the last error encountered by the connection or QDtlsError::NoError.
1101 
1102     \sa dtlsErrorString(), QDtlsError
1103 */
dtlsError() const1104 QDtlsError QDtls::dtlsError() const
1105 {
1106     Q_D(const QDtls);
1107 
1108     return d->errorCode;
1109 }
1110 
1111 /*!
1112     Returns a textual description for the last error encountered by the connection
1113     or empty string.
1114 
1115     \sa dtlsError()
1116 */
dtlsErrorString() const1117 QString QDtls::dtlsErrorString() const
1118 {
1119     Q_D(const QDtls);
1120 
1121     return d->errorDescription;
1122 }
1123 
1124 /*!
1125     Returns errors found while establishing the identity of the peer.
1126 
1127     If you want to continue connecting despite the errors that have occurred,
1128     you must call ignoreVerificationErrors().
1129 */
peerVerificationErrors() const1130 QVector<QSslError> QDtls::peerVerificationErrors() const
1131 {
1132     Q_D(const QDtls);
1133 
1134     return d->tlsErrors;
1135 }
1136 
1137 /*!
1138     This method tells QDtls to ignore only the errors given in \a errorsToIgnore.
1139 
1140     If, for instance, you want to connect to a server that uses a self-signed
1141     certificate, consider the following snippet:
1142 
1143     \snippet code/src_network_ssl_qdtls.cpp 6
1144 
1145     You can also call this function after doHandshake() encountered the
1146     QDtlsError::PeerVerificationError error, and then resume the handshake by
1147     calling resumeHandshake().
1148 
1149     Later calls to this function will replace the list of errors that were
1150     passed in previous calls. You can clear the list of errors you want to ignore
1151     by calling this function with an empty list.
1152 
1153     \sa doHandshake(), resumeHandshake(), QSslError
1154 */
ignoreVerificationErrors(const QVector<QSslError> & errorsToIgnore)1155 void QDtls::ignoreVerificationErrors(const QVector<QSslError> &errorsToIgnore)
1156 {
1157     Q_D(QDtls);
1158 
1159     d->tlsErrorsToIgnore = errorsToIgnore;
1160 }
1161 
1162 QT_END_NAMESPACE
1163