summaryrefslogtreecommitdiffstats
path: root/src/network/ssl/qdtls.cpp
diff options
context:
space:
mode:
authorTimur Pocheptsov <timur.pocheptsov@qt.io>2018-06-04 16:42:13 +0200
committerTimur Pocheptsov <timur.pocheptsov@qt.io>2018-08-09 03:52:02 +0000
commit4c089601d7982bb45080d57b3399ed0653f69dd1 (patch)
tree5b7349c66f514997e03744a500b79ed72d4cf718 /src/network/ssl/qdtls.cpp
parent977c8a4d18a1833c90ba1051d022434755216e0c (diff)
Document the DTLS API
Task-number: QTBUG-68070 Change-Id: Ifd08ecb7c2c1a6dc352952a10ad56259bd1ecf10 Reviewed-by: Paul Wicking <paul.wicking@qt.io> Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/network/ssl/qdtls.cpp')
-rw-r--r--src/network/ssl/qdtls.cpp599
1 files changed, 589 insertions, 10 deletions
diff --git a/src/network/ssl/qdtls.cpp b/src/network/ssl/qdtls.cpp
index afa135845a..3759662505 100644
--- a/src/network/ssl/qdtls.cpp
+++ b/src/network/ssl/qdtls.cpp
@@ -46,12 +46,294 @@
#include "qglobal.h"
-QT_BEGIN_NAMESPACE
+/*!
+ \class QDtlsClientVerifier
+ \brief This class implements server-side DTLS cookie generation and verification.
+ \since 5.12
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ The QDtlsClientVerifier class implements server-side DTLS cookie generation
+ and verification. Datagram security protocols are highly susceptible to a
+ variety of Denial-of-Service attacks. According to \l {https://tools.ietf.org/html/rfc6347#section-4.2.1}{RFC 6347, section 4.2.1},
+ these are two of the more common types of attack:
+
+ \list
+ \li An attacker transmits a series of handshake initiation requests, causing
+ a server to allocate excessive resources and potentially perform expensive
+ cryptographic operations.
+ \li An attacker transmits a series of handshake initiation requests with
+ a forged source of the victim, making the server act as an amplifier.
+ Normally, the server would reply to the victim machine with a Certificate message,
+ which can be quite large, thus flooding the victim machine with datagrams.
+ \endlist
+
+ As a countermeasure to these attacks, \l {https://tools.ietf.org/html/rfc6347#section-4.2.1}{RFC 6347, section 4.2.1}
+ proposes a stateless cookie technique that a server may deploy:
+
+ \list
+ \li In response to the initial ClientHello message, the server sends a HelloVerifyRequest,
+ which contains a cookie. This cookie is a cryptographic hash and is generated using the
+ client's address, port number, and the server's secret (which is a cryptographically strong
+ pseudo-random sequence of bytes).
+ \li A reachable DTLS client is expected to reply with a new ClientHello message
+ containing this cookie.
+ \li When the server receives the ClientHello message with a cookie, it
+ generates a new cookie as described above. This new cookie is compared to the
+ one found in the ClientHello message.
+ \li In the cookies are equal, the client is considered to be real, and the
+ server can continue with a TLS handshake procedure.
+ \endlist
+
+ \note A DTLS server is not required to use DTLS cookies.
+
+ QDtlsClientVerifier is designed to work in pair with QUdpSocket, as shown in
+ the following code-excerpt:
+
+ \snippet code/src_network_ssl_qdtlscookie.cpp 0
+
+ QDtlsClientVerifier does not impose any restrictions on how the application uses
+ QUdpSocket. For example, it is possible to have a server with a single QUdpSocket
+ in state QAbstractSocket::BoundState, handling multiple DTLS clients
+ simultaneously:
+
+ \list
+ \li Testing if new clients are real DTLS-capable clients.
+ \li Completing TLS handshakes with the verified clients (see QDtls).
+ \li Decrypting datagrams coming from the connected clients (see QDtls).
+ \li Sending encrypted datagrams to the connected clients (see QDtls).
+ \endlist
+
+ This implies that QDtlsClientVerifier does not read directly from a socket,
+ instead it expects the application to read an incoming datagram, extract the
+ sender's address, and port, and then pass this data to verifyClient().
+ To send a HelloVerifyRequest message, verifyClient() can write to the QUdpSocket.
+
+ \note QDtlsClientVerifier does not take ownership of the QUdpSocket object.
+
+ By default QDtlsClientVerifier obtains its secret from a cryptographically
+ strong pseudorandom number generator.
+
+ \note The default secret is shared by all objects of the classes QDtlsClientVerifier
+ and QDtls. Since this can impose security risks, RFC 6347 recommends to change
+ the server's secret frequently. Please see \l {https://tools.ietf.org/html/rfc6347}{RFC 6347, section 4.2.1}
+ for hints about possible server implementations. Cookie generator parameters
+ can be set using the class QDtlsClientVerifier::GeneratorParameters and
+ setCookieGeneratorParameters():
+
+ \snippet code/src_network_ssl_qdtlscookie.cpp 1
+
+ The \l{secureudpserver}{DTLS server} example illustrates how to use
+ QDtlsClientVerifier in a server application.
+
+ \sa QUdpSocket, QAbstractSocket::BoundState, QDtls, verifyClient(),
+ GeneratorParameters, setCookieGeneratorParameters(), cookieGeneratorParameters(),
+ QDtls::setCookieGeneratorParameters(),
+ QDtls::cookieGeneratorParameters(),
+ QCryptographicHash::Algorithm,
+ QDtlsError, dtlsError(), dtlsErrorString()
+*/
+
+/*!
+ \class QDtlsClientVerifier::GeneratorParameters
+ \brief This class defines parameters for DTLS cookie generator.
+ \since 5.12
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ An object of this class provides the parameters that QDtlsClientVerifier
+ will use to generate DTLS cookies. They include a cryptographic hash
+ algorithm and a secret.
+
+ \note An empty secret is considered to be invalid by
+ QDtlsClientVerifier::setCookieGeneratorParameters().
+
+ \sa QDtlsClientVerifier::setCookieGeneratorParameters(),
+ QDtlsClientVerifier::cookieGeneratorParameters(),
+ QDtls::setCookieGeneratorParameters(),
+ QDtls::cookieGeneratorParameters(),
+ QCryptographicHash::Algorithm
+*/
+
+/*!
+ \enum QDtlsError
+ \brief Describes errors that can be found by QDtls and QDtlsClientVerifier.
+ \relates QDtls
+ \since 5.12
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ This enum describes general and TLS-specific errors that can be encountered
+ by objects of the classes QDtlsClientVerifier and QDtls.
+
+ \value NoError No error occurred, the last operation was successful.
+ \value InvalidInputParameters Input parameters provided by a caller were
+ invalid.
+ \value InvalidOperation An operation was attempted in a state that did not
+ permit it.
+ \value UnderlyingSocketError QUdpSocket::writeDatagram() failed, QUdpSocket::error()
+ and QUdpSocket::errorString() can provide more specific information.
+ \value RemoteClosedConnectionError TLS shutdown alert message was received.
+ \value PeerVerificationError Peer's identity could not be verified during the
+ TLS handshake.
+ \value TlsInitializationError An error occurred while initializing an underlying
+ TLS backend.
+ \value TlsFatalError A fatal error occurred during TLS handshake, other
+ than peer verification error or TLS initialization error.
+ \value TlsNonFatalError A failure to encrypt or decrypt a datagram, non-fatal,
+ meaning QDtls can continue working after this error.
+*/
+
+/*!
+ \class QDtls
+ \brief This class provides encryption for UDP sockets.
+ \since 5.12
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ The QDtls class can be used to establish a secure connection with a network
+ peer using User Datagram Protocol (UDP). DTLS connection over essentially
+ connectionless UDP means that two peers first have to successfully complete
+ a TLS handshake by calling doHandshake(). After the handshake has completed,
+ encrypted datagrams can be sent to the peer using writeDatagramEncrypted().
+ Encrypted datagrams coming from the peer can be decrypted by decryptDatagram().
+
+ QDtls is designed to work with QUdpSocket. Since QUdpSocket can receive
+ datagrams coming from different peers, an application must implement
+ demultiplexing, forwarding datagrams coming from different peers to their
+ corresponding instances of QDtls. An association between a network peer
+ and its QDtls object can be established using the peer's address and port
+ number. Before starting a handshake, the application must set the peer's
+ address and port number using setPeer().
+
+ QDtls does not read datagrams from QUdpSocket, this is expected to be done by
+ the application, for example, in a slot attached to the QUdpSocket::readyRead()
+ signal. Then, these datagrams must be processed by QDtls.
+
+ \note QDtls does \e not take ownership of the QUdpSocket object.
+
+ Normally, several datagrams are to be received and sent by both peers during
+ the handshake phase. Upon reading datagrams, server and client must pass these
+ datagrams to doHandshake() until some error is found or handshakeState()
+ returns HandshakeComplete:
+
+ \snippet code/src_network_ssl_qdtls.cpp 0
+
+ For a server, the first call to doHandshake() requires a non-empty datagram
+ containing a ClientHello message. If the server also deploys QDtlsClientVerifier,
+ the first ClientHello message is expected to be the one verified by QDtlsClientVerifier.
+
+ In case the peer's identity cannot be validated during the handshake, the application
+ must inspect errors returned by peerVerificationErrors() and then either
+ ignore errors by calling ignoreVerificationErrors() or abort the handshake
+ by calling abortHandshake(). If errors were ignored, the handshake can be
+ resumed by calling resumeHandshake().
+
+ After the handshake has been completed, datagrams can be sent to and received
+ from the network peer securely:
+
+ \snippet code/src_network_ssl_qdtls.cpp 2
+
+ A DTLS connection may be closed using shutdown().
+
+ \snippet code/src_network_ssl_qdtls.cpp 3
+
+ \warning It's recommended to call shutdown() before destroying the client's QDtls
+ object if you are planning to re-use the same port number to connect to the
+ server later. Otherwise, the server may drop incoming ClientHello messages,
+ see \l{https://tools.ietf.org/html/rfc6347#page-25}{RFC 6347, section 4.2.8}
+ for more details and implementation hints.
+
+ If the server does not use QDtlsClientVerifier, it \e must configure its
+ QDtls objects to disable the cookie verification procedure:
+
+ \snippet code/src_network_ssl_qdtls.cpp 4
+
+ A server that uses cookie verification with non-default generator parameters
+ \e must set the same parameters for its QDtls object before starting the handshake.
+
+ \note The DTLS protocol leaves Path Maximum Transmission Unit (PMTU) discovery
+ to the application. The application may provide QDtls with the MTU using
+ setMtuHint(). This hint affects only the handshake phase, since only handshake
+ messages can be fragmented and reassembled by the DTLS. All other messages sent
+ by the application must fit into a single datagram.
+ \note DTLS-specific headers add some overhead to application data further
+ reducing the possible message size.
+ \warning A server configured to reply with HelloVerifyRequest will drop
+ all fragmented ClientHello messages, never starting a handshake.
+
+ The \l{secureudpserver}{DTLS server} and \l{secureudpclient}{DTLS client}
+ examples illustrate how to use QDtls in applications.
+
+ \sa QUdpSocket, QDtlsClientVerifier, HandshakeState, QDtlsError, QSslConfiguration
+*/
+
+/*!
+ \fn void QDtls::handshakeTimeout()
-namespace
-{
+ Packet loss can result in timeouts during the handshake phase. In this case
+ QDtls emits a handshakeTimeout() signal. Call handleTimeout() to retransmit
+ the handshake messages:
+
+ \snippet code/src_network_ssl_qdtls.cpp 1
+
+ \sa handleTimeout()
+*/
+
+/*!
+ \fn void QDtls::pskRequired(QSslPreSharedKeyAuthenticator *authenticator)
+
+ QDtls emits this signal when it negotiates a PSK ciphersuite, and therefore
+ a PSK authentication is then required.
+
+ When using PSK, the client must send to the server a valid identity and a
+ valid pre shared key, in order for the TLS handshake to continue.
+ Applications can provide this information in a slot connected to this
+ signal, by filling in the passed \a authenticator object according to their
+ needs.
+
+ \note Ignoring this signal, or failing to provide the required credentials,
+ will cause the handshake to fail, and therefore the connection to be aborted.
+
+ \note The \a authenticator object is owned by QDtls and must not be deleted
+ by the application.
+
+ \sa QSslPreSharedKeyAuthenticator
+*/
-bool isDtlsProtocol(QSsl::SslProtocol protocol)
+/*!
+ \enum QDtls::HandshakeState
+ \brief Describes the current state of DTLS handshake.
+ \since 5.12
+
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ This enum describes the current state of DTLS handshake for a QDtls
+ connection.
+
+ \value HandshakeNotStarted Nothing done yet.
+ \value HandshakeInProgress Handshake was initiated and no errors were found so far.
+ \value PeerVerificationFailed The identity of the peer can't be established.
+ \value HandshakeComplete Handshake completed successfully and encrypted connection
+ was established.
+
+ \sa QDtls::doHandshake(), QDtls::handshakeState()
+*/
+
+
+QT_BEGIN_NAMESPACE
+
+static bool isDtlsProtocol(QSsl::SslProtocol protocol)
{
switch (protocol) {
case QSsl::DtlsV1_0:
@@ -64,8 +346,6 @@ bool isDtlsProtocol(QSsl::SslProtocol protocol)
}
}
-}
-
QSslConfiguration QDtlsBasePrivate::configuration() const
{
auto copyPrivate = new QSslConfigurationPrivate(dtlsConfiguration);
@@ -118,6 +398,41 @@ bool QDtlsBasePrivate::setCookieGeneratorParameters(QCryptographicHash::Algorith
return true;
}
+static QString msgUnsupportedMulticastAddress()
+{
+ return QDtls::tr("Multicast and broadcast addresses are not supported");
+}
+
+/*!
+ Default constructs GeneratorParameters object with QCryptographicHash::Sha1
+ as its algorithm and an empty secret.
+
+ \sa QDtlsClientVerifier::setCookieGeneratorParameters(),
+ QDtlsClientVerifier::cookieGeneratorParameters(),
+ QDtls::setCookieGeneratorParameters(),
+ QDtls::cookieGeneratorParameters()
+ */
+QDtlsClientVerifier::GeneratorParameters::GeneratorParameters()
+{
+}
+
+/*!
+ Constructs GeneratorParameters object from \a algorithm and \a secret.
+
+ \sa QDtlsClientVerifier::setCookieGeneratorParameters(),
+ QDtlsClientVerifier::cookieGeneratorParameters(),
+ QDtls::setCookieGeneratorParameters(),
+ QDtls::cookieGeneratorParameters()
+ */
+QDtlsClientVerifier::GeneratorParameters::GeneratorParameters(QCryptographicHash::Algorithm algorithm, const QByteArray &secret)
+ : hash(algorithm), secret(secret)
+{
+}
+
+/*!
+ Constructs a QDtlsClientVerifier object, \a parent is passed to QObject's
+ constructor.
+*/
QDtlsClientVerifier::QDtlsClientVerifier(QObject *parent)
: QObject(*new QDtlsClientVerifierOpenSSL, parent)
{
@@ -132,6 +447,16 @@ QDtlsClientVerifier::QDtlsClientVerifier(QObject *parent)
d->setConfiguration(conf);
}
+/*!
+ Sets the secret and cryptographic hash algorithm that this QDtlsClientVerifier
+ will use to generate cookies. If the new secret has size zero, this function
+ returns \c false and does not change the previous generator parameters.
+
+ \note The secret is supposed to be a cryptographically secure sequence of bytes.
+
+ \sa QDtlsClientVerifier::GeneratorParameters, cookieGeneratorParameters(),
+ QCryptographicHash::Algorithm
+*/
bool QDtlsClientVerifier::setCookieGeneratorParameters(const GeneratorParameters &params)
{
Q_D(QDtlsClientVerifier);
@@ -139,6 +464,16 @@ bool QDtlsClientVerifier::setCookieGeneratorParameters(const GeneratorParameters
return d->setCookieGeneratorParameters(params.hash, params.secret);
}
+/*!
+ Returns the current secret and hash algorithm used to generate cookies.
+ The default hash algorithm is QCryptographicHash::Sha256 if Qt was configured
+ to support it, QCryptographicHash::Sha1 otherwise. The default secret is
+ obtained from the backend-specific cryptographically strong pseudorandom
+ number generator.
+
+ \sa QCryptographicHash::Algorithm, QDtlsClientVerifier::GeneratorParameters,
+ setCookieGeneratorParameters()
+*/
QDtlsClientVerifier::GeneratorParameters QDtlsClientVerifier::cookieGeneratorParameters() const
{
Q_D(const QDtlsClientVerifier);
@@ -146,11 +481,20 @@ QDtlsClientVerifier::GeneratorParameters QDtlsClientVerifier::cookieGeneratorPar
return {d->hashAlgorithm, d->secret};
}
-static QString msgUnsupportedMulticastAddress()
-{
- return QDtls::tr("Multicast and broadcast addresses are not supported");
-}
+/*!
+ \a socket must be a valid pointer, \a dgram must be a non-empty datagram,
+ \a address cannot be null, broadcast, or multicast. This function returns
+ \c true if \a dgram contains a ClientHello message with a valid cookie.
+ If no matching cookie is found, verifyClient() will send a HelloVerifyRequest
+ message using \a socket and will return \c false.
+ The following snippet shows how a server application may check for errors:
+
+ \snippet code/src_network_ssl_qdtlscookie.cpp 2
+
+ \sa QHostAddress::isNull(), QHostAddress::isBroadcast(), QHostAddress::isMulticast(),
+ setCookieGeneratorParameters(), cookieGeneratorParameters()
+*/
bool QDtlsClientVerifier::verifyClient(QUdpSocket *socket, const QByteArray &dgram,
const QHostAddress &address, quint16 port)
{
@@ -171,6 +515,12 @@ bool QDtlsClientVerifier::verifyClient(QUdpSocket *socket, const QByteArray &dgr
return d->verifyClient(socket, dgram, address, port);
}
+/*!
+ Convenience function. Returns the last ClientHello message that was successfully
+ verified, or an empty QByteArray if no verification has completed.
+
+ \sa verifyClient()
+*/
QByteArray QDtlsClientVerifier::verifiedHello() const
{
Q_D(const QDtlsClientVerifier);
@@ -178,6 +528,11 @@ QByteArray QDtlsClientVerifier::verifiedHello() const
return d->verifiedClientHello;
}
+/*!
+ Returns the last error that occurred or QDtlsError::NoError.
+
+ \sa QDtlsError, dtlsErrorString()
+*/
QDtlsError QDtlsClientVerifier::dtlsError() const
{
Q_D(const QDtlsClientVerifier);
@@ -185,6 +540,11 @@ QDtlsError QDtlsClientVerifier::dtlsError() const
return d->errorCode;
}
+/*!
+ Returns a textual description of the last error, or an empty string.
+
+ \sa dtlsError()
+ */
QString QDtlsClientVerifier::dtlsErrorString() const
{
Q_D(const QDtlsBase);
@@ -192,6 +552,13 @@ QString QDtlsClientVerifier::dtlsErrorString() const
return d->errorDescription;
}
+/*!
+ Creates a QDtls object, \a parent is passed to the QObject constructor.
+ \a mode is QSslSocket::SslServerMode for a server-side DTLS connection or
+ QSslSocket::SslClientMode for a client.
+
+ \sa sslMode(), QSslSocket::SslSocket
+*/
QDtls::QDtls(QSslSocket::SslMode mode, QObject *parent)
: QObject(*new QDtlsPrivateOpenSSL, parent)
{
@@ -201,6 +568,13 @@ QDtls::QDtls(QSslSocket::SslMode mode, QObject *parent)
setDtlsConfiguration(QSslConfiguration::defaultDtlsConfiguration());
}
+/*!
+ Sets the peer's address, \a port, and host name. \a address must not be
+ null, multicast, or broadcast. \a verificationName is the host name used
+ for the certificate validation.
+
+ \sa peerAddress(), peerPort(), peerVerificationName()
+ */
bool QDtls::setPeer(const QHostAddress &address, quint16 port,
const QString &verificationName)
{
@@ -233,6 +607,12 @@ bool QDtls::setPeer(const QHostAddress &address, quint16 port,
return true;
}
+/*!
+ Sets the host name that will be used for the certificate validation.
+ \note This function must be called before the handshake starts.
+
+ \sa peerVerificationName(), setPeer()
+*/
bool QDtls::setPeerVerificationName(const QString &name)
{
Q_D(QDtls);
@@ -249,6 +629,11 @@ bool QDtls::setPeerVerificationName(const QString &name)
return true;
}
+/*!
+ Returns the peer's address, set by setPeer(), or QHostAddress::Null.
+
+ \sa setPeer()
+*/
QHostAddress QDtls::peerAddress() const
{
Q_D(const QDtls);
@@ -256,6 +641,11 @@ QHostAddress QDtls::peerAddress() const
return d->remoteAddress;
}
+/*!
+ Returns the peer's port number, set by setPeer(), or 0.
+
+ \sa setPeer()
+*/
quint16 QDtls::peerPort() const
{
Q_D(const QDtlsBase);
@@ -263,6 +653,12 @@ quint16 QDtls::peerPort() const
return d->remotePort;
}
+/*!
+ Returns the host name set by setPeer() or setPeerVerificationName().
+ The default value is an empty string.
+
+ \sa setPeerVerificationName(), setPeer()
+*/
QString QDtls::peerVerificationName() const
{
Q_D(const QDtls);
@@ -270,6 +666,12 @@ QString QDtls::peerVerificationName() const
return d->peerVerificationName;
}
+/*!
+ Returns QSslSocket::SslServerMode for a server-side connection and
+ QSslSocket::SslClientMode for a client.
+
+ \sa QDtls(), QSslSocket::SslMode
+*/
QSslSocket::SslMode QDtls::sslMode() const
{
Q_D(const QDtls);
@@ -277,6 +679,12 @@ QSslSocket::SslMode QDtls::sslMode() const
return d->mode;
}
+/*!
+ \a mtuHint is the maximum transmission unit (MTU), either discovered or guessed
+ by the application. The application is not required to set this value.
+
+ \sa mtuHint(), QAbstractSocket::PathMtuSocketOption
+ */
void QDtls::setMtuHint(quint16 mtuHint)
{
Q_D(QDtls);
@@ -284,6 +692,11 @@ void QDtls::setMtuHint(quint16 mtuHint)
d->mtuHint = mtuHint;
}
+/*!
+ Returns the value previously set by setMtuHint(). The default value is 0.
+
+ \sa setMtuHint()
+ */
quint16 QDtls::mtuHint() const
{
Q_D(const QDtls);
@@ -291,6 +704,15 @@ quint16 QDtls::mtuHint() const
return d->mtuHint;
}
+/*!
+ Sets the cryptographic hash algorithm and the secret. This function is only
+ needed for a server-side QDtls connection.
+
+ \note This function must be called before the handshake starts.
+
+ \sa cookieGeneratorParameters(), doHandshake(), QDtlsClientVerifier,
+ QDtlsClientVerifier::cookieGeneratorParameters()
+*/
bool QDtls::setCookieGeneratorParameters(const GeneratorParameters &params)
{
Q_D(QDtls);
@@ -298,6 +720,17 @@ bool QDtls::setCookieGeneratorParameters(const GeneratorParameters &params)
return d->setCookieGeneratorParameters(params.hash, params.secret);
}
+/*!
+ Returns the current hash algorithm and secret, either default ones or previously
+ set by a call to setCookieGeneratorParameters().
+
+ The default hash algorithm is QCryptographicHash::Sha256 if Qt was
+ configured to support it, QCryptographicHash::Sha1 otherwise. The default
+ secret is obtained from the backend-specific cryptographically strong
+ pseudorandom number generator.
+
+ \sa QDtlsClientVerifier, cookieGeneratorParameters()
+*/
QDtls::GeneratorParameters QDtls::cookieGeneratorParameters() const
{
Q_D(const QDtls);
@@ -305,6 +738,13 @@ QDtls::GeneratorParameters QDtls::cookieGeneratorParameters() const
return {d->hashAlgorithm, d->secret};
}
+/*!
+ Sets the connection's TLS configuration from \a configuration.
+
+ \note This function must be called before the handshake starts.
+
+ \sa dtlsConfiguration(), doHandshake()
+*/
bool QDtls::setDtlsConfiguration(const QSslConfiguration &configuration)
{
Q_D(QDtls);
@@ -324,6 +764,12 @@ bool QDtls::setDtlsConfiguration(const QSslConfiguration &configuration)
return false;
}
+/*!
+ Returns either the default DTLS configuration or the configuration set by an
+ earlier call to setDtlsConfiguration().
+
+ \sa setDtlsConfiguration(), QSslConfiguration::defaultDtlsConfiguration()
+*/
QSslConfiguration QDtls::dtlsConfiguration() const
{
Q_D(const QDtls);
@@ -331,6 +777,11 @@ QSslConfiguration QDtls::dtlsConfiguration() const
return d->configuration();
}
+/*!
+ Returns the current handshake state for this QDtls.
+
+ \sa doHandshake(), QDtls::HandshakeState
+ */
QDtls::HandshakeState QDtls::handshakeState()const
{
Q_D(const QDtls);
@@ -338,6 +789,25 @@ QDtls::HandshakeState QDtls::handshakeState()const
return d->handshakeState;
}
+/*!
+ Starts or continues a DTLS handshake. \a socket must be a valid pointer.
+ When starting a server-side DTLS handshake, \a dgram must contain the initial
+ ClientHello message read from QUdpSocket. This function returns \c true if
+ no error was found. Handshake state can be tested using handshakeState().
+ \c false return means some error occurred, use dtlsError() for more
+ detailed information.
+
+ \note If the identity of the peer can't be established, the error is set to
+ QDtlsError::PeerVerificationError. If you want to ignore verification errors
+ and continue connecting, you must call ignoreVerificationErrors() and then
+ resumeHandshake(). If the errors cannot be ignored, you must call
+ abortHandshake().
+
+ \snippet code/src_network_ssl_qdtls.cpp 5
+
+ \sa handshakeState(), dtlsError(), ignoreVerificationErrors(), resumeHandshake(),
+ abortHandshake()
+*/
bool QDtls::doHandshake(QUdpSocket *socket, const QByteArray &dgram)
{
Q_D(QDtls);
@@ -352,6 +822,9 @@ bool QDtls::doHandshake(QUdpSocket *socket, const QByteArray &dgram)
return false;
}
+/*!
+ \internal
+*/
bool QDtls::startHandshake(QUdpSocket *socket, const QByteArray &datagram)
{
Q_D(QDtls);
@@ -382,6 +855,14 @@ bool QDtls::startHandshake(QUdpSocket *socket, const QByteArray &datagram)
return d->startHandshake(socket, datagram);
}
+/*!
+ If a timeout occures during the handshake, the handshakeTimeout() signal
+ is emitted. The application must call handleTimeout() to retransmit handshake
+ messages; handleTimeout() returns \c true if a timeout has occurred, false
+ otherwise. \a socket must be a valid pointer.
+
+ \sa handshakeTimeout()
+*/
bool QDtls::handleTimeout(QUdpSocket *socket)
{
Q_D(QDtls);
@@ -394,6 +875,9 @@ bool QDtls::handleTimeout(QUdpSocket *socket)
return d->handleTimeout(socket);
}
+/*!
+ \internal
+*/
bool QDtls::continueHandshake(QUdpSocket *socket, const QByteArray &datagram)
{
Q_D(QDtls);
@@ -413,6 +897,12 @@ bool QDtls::continueHandshake(QUdpSocket *socket, const QByteArray &datagram)
return d->continueHandshake(socket, datagram);
}
+/*!
+ If peer verification errors were ignored during the handshake, resumeHandshake()
+ resumes and completes the handshake. \a socket must be a valid pointer.
+
+ \sa doHandshake(), abortHandshake() peerVerificationErrors(), ignoreVerificationErrors()
+*/
bool QDtls::resumeHandshake(QUdpSocket *socket)
{
Q_D(QDtls);
@@ -431,6 +921,12 @@ bool QDtls::resumeHandshake(QUdpSocket *socket)
return d->resumeHandshake(socket);
}
+/*!
+ Aborts the handshake in case peer verification errors could not be ignored.
+ \a socket must be a valid pointer.
+
+ \sa doHandshake(), resumeHandshakeAfterError()
+ */
bool QDtls::abortHandshake(QUdpSocket *socket)
{
Q_D(QDtls);
@@ -450,6 +946,13 @@ bool QDtls::abortHandshake(QUdpSocket *socket)
return true;
}
+/*!
+ Sends an encrypted shutdown alert message and closes the DTLS connection.
+ Handshake state changes to QDtls::HandshakeNotStarted. \a socket must be a
+ valid pointer. This function returns \c true on success.
+
+ \sa doHandshake()
+ */
bool QDtls::shutdown(QUdpSocket *socket)
{
Q_D(QDtls);
@@ -470,6 +973,11 @@ bool QDtls::shutdown(QUdpSocket *socket)
return true;
}
+/*!
+ Returns \c true if DTLS handshake completed successfully.
+
+ \sa doHandshake(), handshakeState()
+ */
bool QDtls::isConnectionEncrypted() const
{
Q_D(const QDtls);
@@ -477,6 +985,18 @@ bool QDtls::isConnectionEncrypted() const
return d->connectionEncrypted;
}
+/*!
+ Returns the cryptographic \l {QSslCipher} {cipher} used by this connection,
+ or a null cipher if the connection isn't encrypted. The cipher for the
+ session is selected during the handshake phase. The cipher is used to encrypt
+ and decrypt data.
+
+ QSslConfiguration provides functions for setting the ordered list of ciphers
+ from which the handshake phase will eventually select the session cipher.
+ This ordered list must be in place before the handshake phase begins.
+
+ \sa QSslConfiguration, setDtlsConfiguration(), dtlsConfiguration()
+*/
QSslCipher QDtls::sessionCipher() const
{
Q_D(const QDtls);
@@ -484,6 +1004,16 @@ QSslCipher QDtls::sessionCipher() const
return d->sessionCipher;
}
+/*!
+ Returns the DTLS protocol version used by this connection, or UnknownProtocol
+ if the connection isn't encrypted yet. The protocol for the connection is selected
+ during the handshake phase.
+
+ setDtlsConfiguration() can set the preferred version before the handshake starts.
+
+ \sa setDtlsConfiguration(), QSslConfiguration, QSslConfiguration::defaultDtlsConfiguration(),
+ QSslConfiguration::setProtocol()
+*/
QSsl::SslProtocol QDtls::sessionProtocol() const
{
Q_D(const QDtls);
@@ -491,6 +1021,14 @@ QSsl::SslProtocol QDtls::sessionProtocol() const
return d->sessionProtocol;
}
+/*!
+ Encrypts \a dgram and writes the encrypted data into \a socket. Returns the
+ number of bytes written, or -1 in case of error. The handshake must be completed
+ before writing encrypted data. \a socket must be a valid
+ pointer.
+
+ \sa doHandshake(), handshakeState(), connectionEncrypted(), dtlsError()
+*/
qint64 QDtls::writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram)
{
Q_D(QDtls);
@@ -509,6 +1047,12 @@ qint64 QDtls::writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram
return d->writeDatagramEncrypted(socket, dgram);
}
+/*!
+ Decrypts \a dgram and returns its contents as plain text. The handshake must
+ be completed before datagrams can be decrypted. Depending on the type of the
+ TLS message the connection may write into \a socket, which must be a valid
+ pointer.
+*/
QByteArray QDtls::decryptDatagram(QUdpSocket *socket, const QByteArray &dgram)
{
Q_D(QDtls);
@@ -530,6 +1074,11 @@ QByteArray QDtls::decryptDatagram(QUdpSocket *socket, const QByteArray &dgram)
return d->decryptDatagram(socket, dgram);
}
+/*!
+ Returns the last error encountered by the connection or QDtlsError::NoError.
+
+ \sa dtlsErrorString(), QDtlsError
+*/
QDtlsError QDtls::dtlsError() const
{
Q_D(const QDtls);
@@ -537,6 +1086,12 @@ QDtlsError QDtls::dtlsError() const
return d->errorCode;
}
+/*!
+ Returns a textual description for the last error encountered by the connection
+ or empty string.
+
+ \sa dtlsError()
+*/
QString QDtls::dtlsErrorString() const
{
Q_D(const QDtls);
@@ -544,6 +1099,12 @@ QString QDtls::dtlsErrorString() const
return d->errorDescription;
}
+/*!
+ Returns errors found while establishing the identity of the peer.
+
+ If you want to continue connecting despite the errors that have occurred,
+ you must call ignoreVerificationErrors().
+*/
QVector<QSslError> QDtls::peerVerificationErrors() const
{
Q_D(const QDtls);
@@ -551,6 +1112,24 @@ QVector<QSslError> QDtls::peerVerificationErrors() const
return d->tlsErrors;
}
+/*!
+ This method tells QDtls to ignore only the errors given in \a errors.
+
+ If, for instance, you want to connect to a server that uses a self-signed
+ certificate, consider the following snippet:
+
+ \snippet code/src_network_ssl_qdtls.cpp 6
+
+ You can also call this function after doHandshake() encountered the
+ QDtlsError::PeerVerificationError error, and then resume the handshake by
+ calling resumeHandshake().
+
+ Later calls to this function will replace the list of errors that were
+ passed in previous calls. You can clear the list of errors you want to ignore
+ by calling this function with an empty list.
+
+ \sa doHandshake(), resumeHandshake(), QSslError
+*/
void QDtls::ignoreVerificationErrors(const QVector<QSslError> &errorsToIgnore)
{
Q_D(QDtls);