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>
This commit is contained in:
parent
977c8a4d18
commit
4c089601d7
37
examples/network/doc/src/secureudpclient.qdoc
Normal file
37
examples/network/doc/src/secureudpclient.qdoc
Normal file
@ -0,0 +1,37 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the documentation of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:FDL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Free Documentation License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Free
|
||||
** Documentation License version 1.3 as published by the Free Software
|
||||
** Foundation and appearing in the file included in the packaging of
|
||||
** this file. Please review the following information to ensure
|
||||
** the GNU Free Documentation License version 1.3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example secureudpclient
|
||||
\title DTLS client
|
||||
\ingroup examples-network
|
||||
\brief Demonstrates how to implement a simple DTLS client
|
||||
|
||||
This example uses QUdpSocket, QDtlsClientVerifier, and QDtls to securely
|
||||
communicate over the User Datagram Protocol with DTLS servers.
|
||||
*/
|
||||
|
36
examples/network/doc/src/secureudpserver.qdoc
Normal file
36
examples/network/doc/src/secureudpserver.qdoc
Normal file
@ -0,0 +1,36 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the documentation of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:FDL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Free Documentation License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Free
|
||||
** Documentation License version 1.3 as published by the Free Software
|
||||
** Foundation and appearing in the file included in the packaging of
|
||||
** this file. Please review the following information to ensure
|
||||
** the GNU Free Documentation License version 1.3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
/*!
|
||||
\example secureudpserver
|
||||
\title DTLS server
|
||||
\ingroup examples-network
|
||||
\brief Demonstrates how to implement a simple DTLS server
|
||||
|
||||
This example uses QUdpSocket, QDtlsClientVerifier, and QDtls to securely respond
|
||||
to DTLS client requests over the User Datagram Protocol.
|
||||
*/
|
138
src/network/doc/snippets/code/src_network_ssl_qdtls.cpp
Normal file
138
src/network/doc/snippets/code/src_network_ssl_qdtls.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the documentation of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** BSD License Usage
|
||||
** Alternatively, you may use this file under the terms of the BSD license
|
||||
** as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
//! [0]
|
||||
// A client initiates a handshake:
|
||||
QUdpSocket clientSocket;
|
||||
QDtls clientDtls;
|
||||
clientDtls.setPeer(address, port, peerName);
|
||||
clientDtls.doHandshake(&clientSocket);
|
||||
|
||||
// A server accepting an incoming connection; address, port, clientHello are
|
||||
// read by QUdpSocket::readDatagram():
|
||||
QByteArray clientHello(serverSocket.pendingDatagramSize(), Qt::Uninitialized);
|
||||
QHostAddress address;
|
||||
quin16 port = {};
|
||||
serverSocket.readDatagram(clientHello.data(), clientHello.size(), &address, &port);
|
||||
|
||||
QDtls serverDtls;
|
||||
serverDtls.setPeer(address, port);
|
||||
serverDtls.doHandshake(&serverSocket, clientHello);
|
||||
|
||||
// Handshake completion, both for server and client:
|
||||
void DtlsConnection::continueHandshake(const QByteArray &datagram)
|
||||
{
|
||||
if (dtls.doHandshake(&udpSocket, datagram)) {
|
||||
// Check handshake status:
|
||||
if (dtls.handshakeStatus() == QDlts::HandshakeComplete) {
|
||||
// Secure DTLS connection is now established.
|
||||
}
|
||||
} else {
|
||||
// Error handling.
|
||||
}
|
||||
}
|
||||
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
DtlsClient::DtlsClient()
|
||||
{
|
||||
// Some initialization code here ...
|
||||
connect(&clientDtls, &QDtls::handshakeTimeout, this, &DtlsClient::handleTimeout);
|
||||
}
|
||||
|
||||
void DtlsClient::handleTimeout()
|
||||
{
|
||||
clientDtls.handleTimeout(&clientSocket);
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
// Sending an encrypted datagram:
|
||||
dtlsConnection.writeDatagramEncrypted(&clientSocket, "Hello DTLS server!");
|
||||
|
||||
// Decryption:
|
||||
QByteArray encryptedMessage(dgramSize);
|
||||
socket.readDatagram(encryptedMessage.data(), dgramSize);
|
||||
const QByteArray plainText = dtlsConnection.decryptDatagram(&socket, encryptedMessage);
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
DtlsClient::~DtlsClient()
|
||||
{
|
||||
clientDtls.shutdown(&clientSocket);
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
auto config = QSslConfiguration::defaultDtlsConfiguration();
|
||||
config.setDtlsCookieVerificationEnabled(false);
|
||||
// Some other customization ...
|
||||
dtlsConnection.setDtlsConfiguration(config);
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
if (!dtls.doHandshake(&socket, dgram)) {
|
||||
if (dtls.dtlsError() == QDtlsError::PeerVerificationError)
|
||||
dtls.abortAfterError(&socket);
|
||||
}
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
QList<QSslCertificate> cert = QSslCertificate::fromPath(QLatin1String("server-certificate.pem"));
|
||||
QSslError error(QSslError::SelfSignedCertificate, cert.at(0));
|
||||
QList<QSslError> expectedSslErrors;
|
||||
expectedSslErrors.append(error);
|
||||
|
||||
QDtls dtls;
|
||||
dtls.ignoreVerificationErrors(expectedSslErrors);
|
||||
dtls.doHandshake(udpSocket);
|
||||
//! [6]
|
||||
|
125
src/network/doc/snippets/code/src_network_ssl_qdtlscookie.cpp
Normal file
125
src/network/doc/snippets/code/src_network_ssl_qdtlscookie.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the documentation of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** BSD License Usage
|
||||
** Alternatively, you may use this file under the terms of the BSD license
|
||||
** as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
//! [0]
|
||||
class DtlsServer : public QObject
|
||||
{
|
||||
public:
|
||||
bool listen(const QHostAddress &address, quint16 port);
|
||||
// ...
|
||||
|
||||
private:
|
||||
void readyRead();
|
||||
// ...
|
||||
|
||||
QUdpSocket serverSocket;
|
||||
QDtlsClientVerifier verifier;
|
||||
// ...
|
||||
};
|
||||
|
||||
bool DtlsServer::listen(const QHostAddress &serverAddress, quint16 serverPort)
|
||||
{
|
||||
if (serverSocket.bind(serverAddress, serverPort))
|
||||
connect(&serverSocket, &QUdpSocket::readyRead, this, &DtlsServer::readyRead);
|
||||
return serverSocket.state() == QAbstractSocket::BoundState;
|
||||
}
|
||||
|
||||
void DtlsServer::readyRead()
|
||||
{
|
||||
QByteArray dgram(serverSocket.pendingDatagramSize(), Qt::Uninitialized);
|
||||
QHostAddress address;
|
||||
quint16 port = {};
|
||||
serverSocket.readDatagram(dgram.data(), dgram.size(), &address, &port);
|
||||
if (verifiedClients.contains({address, port}) {
|
||||
// This client was verified previously, we either continue the
|
||||
// handshake or decrypt the incoming message.
|
||||
} else if (verifier.verifyClient(&serverSocket, dgram, address, port)) {
|
||||
// Apparently we have a real DTLS client who wants to send us
|
||||
// encrypted datagrams. Remember this client as verified
|
||||
// and proceed with a handshake.
|
||||
} else {
|
||||
// No matching cookie was found in the incoming datagram,
|
||||
// verifyClient() has sent a ClientVerify message.
|
||||
// We'll hear from the client again soon, if they're real.
|
||||
}
|
||||
}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
void DtlsServer::updateServerSecret()
|
||||
{
|
||||
const QByteArray newSecret(generateCryptoStrongSecret());
|
||||
if (newSecret.size()) {
|
||||
usedCookies.append(newSecret);
|
||||
verifier.setCookieGeneratorParameters({QCryptographicHash::Sha1, newSecret});
|
||||
}
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
if (!verifier.verifyClient(&socket, message, address, port)) {
|
||||
switch (verifyClient.dtlsError()) {
|
||||
case QDtlsError::NoError:
|
||||
// Not verified yet, but no errors found and we have to wait for the next
|
||||
// message from this client.
|
||||
return;
|
||||
case QDtlsError::TlsInitializationError:
|
||||
// This error is fatal, nothing we can do about it.
|
||||
// Probably, quit the server after reporting the error.
|
||||
return;
|
||||
case QDtlsError::UnderlyingSocketError:
|
||||
// There is some problem in QUdpSocket, handle it (see QUdpSocket::error())
|
||||
return;
|
||||
case QDtlsError::InvalidInputParameters:
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
//! [2]
|
@ -67,6 +67,15 @@
|
||||
To disable SSL support in a Qt build, configure Qt with the \c{-no-openssl}
|
||||
option.
|
||||
|
||||
\section1 Datagram Transport Layer Security
|
||||
|
||||
Datagram Transport Layer Security (DTLS) is a protocol that enables security
|
||||
for datagram-based applications, providing them with protection against
|
||||
eavesdropping, tampering, or message forgery. The DTLS protocol is based on the
|
||||
stream-oriented Transport Layer Security (TLS) protocol. QtNetwork enables
|
||||
the use of DTLS with User Datagram Protocol (UDP), as defined by
|
||||
\l {https://tools.ietf.org/html/rfc6347}{RFC 6347}.
|
||||
|
||||
\section1 Import and Export Restrictions
|
||||
|
||||
Due to import and export restrictions in some parts of the world, we
|
||||
|
@ -46,12 +46,294 @@
|
||||
|
||||
#include "qglobal.h"
|
||||
|
||||
/*!
|
||||
\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()
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
bool isDtlsProtocol(QSsl::SslProtocol protocol)
|
||||
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 ¶ms)
|
||||
{
|
||||
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 ¶ms)
|
||||
{
|
||||
Q_D(QDtls);
|
||||
@ -298,6 +720,17 @@ bool QDtls::setCookieGeneratorParameters(const GeneratorParameters ¶ms)
|
||||
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);
|
||||
|
@ -79,13 +79,10 @@ public:
|
||||
|
||||
explicit QDtlsClientVerifier(QObject *parent = nullptr);
|
||||
|
||||
struct GeneratorParameters
|
||||
struct Q_NETWORK_EXPORT GeneratorParameters
|
||||
{
|
||||
GeneratorParameters() = default;
|
||||
GeneratorParameters(QCryptographicHash::Algorithm a, const QByteArray &s)
|
||||
: hash(a), secret(s)
|
||||
{
|
||||
}
|
||||
GeneratorParameters();
|
||||
GeneratorParameters(QCryptographicHash::Algorithm a, const QByteArray &s);
|
||||
QCryptographicHash::Algorithm hash = QCryptographicHash::Sha1;
|
||||
QByteArray secret;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user