QDtls

This class provides encryption for UDP sockets. More

Inheritance diagram of PySide2.QtNetwork.QDtls

New in version 5.12.

Synopsis

Functions

Signals

Detailed Description

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 readyRead() signal. Then, these datagrams must be processed by QDtls .

Note

QDtls does 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 :

// 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.
    }
}

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:

// 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);

A DTLS connection may be closed using shutdown() .

DtlsClient::~DtlsClient()
{
    clientDtls.shutdown(&clientSocket);
}

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 RFC 6347, section 4.2.8 for more details and implementation hints.

If the server does not use QDtlsClientVerifier , it must configure its QDtls objects to disable the cookie verification procedure:

auto config = QSslConfiguration::defaultDtlsConfiguration();
config.setDtlsCookieVerificationEnabled(false);
// Some other customization ...
dtlsConnection.setDtlsConfiguration(config);

A server that uses cookie verification with non-default generator parameters 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 DTLS server and DTLS client examples illustrate how to use QDtls in applications.

See also

QUdpSocket QDtlsClientVerifier HandshakeState QDtlsError QSslConfiguration

class PySide2.QtNetwork.QDtls(mode[, parent=None])
param parent:

PySide2.QtCore.QObject

param mode:

SslMode

Creates a QDtls object, parent is passed to the QObject constructor. mode is SslServerMode for a server-side DTLS connection or SslClientMode for a client.

See also

sslMode() SslMode

PySide2.QtNetwork.QDtls.HandshakeState

Describes the current state of DTLS handshake.

This enum describes the current state of DTLS handshake for a QDtls connection.

Constant

Description

QDtls.HandshakeNotStarted

Nothing done yet.

QDtls.HandshakeInProgress

Handshake was initiated and no errors were found so far.

QDtls.PeerVerificationFailed

The identity of the peer can’t be established.

QDtls.HandshakeComplete

Handshake completed successfully and encrypted connection was established.

PySide2.QtNetwork.QDtls.abortHandshake(socket)
Parameters:

socketPySide2.QtNetwork.QUdpSocket

Return type:

bool

Aborts the ongoing handshake. Returns true if one was on-going on socket ; otherwise, sets a suitable error and returns false.

PySide2.QtNetwork.QDtls.decryptDatagram(socket, dgram)
Parameters:
Return type:

PySide2.QtCore.QByteArray

Decrypts 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 socket , which must be a valid pointer.

PySide2.QtNetwork.QDtls.doHandshake(socket[, dgram={}])
Parameters:
Return type:

bool

Starts or continues a DTLS handshake. socket must be a valid pointer. When starting a server-side DTLS handshake, dgram must contain the initial ClientHello message read from QUdpSocket . This function returns true if no error was found. Handshake state can be tested using handshakeState() . 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() .

if (!dtls.doHandshake(&socket, dgram)) {
    if (dtls.dtlsError() == QDtlsError::PeerVerificationError)
        dtls.abortAfterError(&socket);
}
PySide2.QtNetwork.QDtls.dtlsConfiguration()
Return type:

PySide2.QtNetwork.QSslConfiguration

Returns either the default DTLS configuration or the configuration set by an earlier call to setDtlsConfiguration() .

PySide2.QtNetwork.QDtls.dtlsError()
Return type:

QDtlsError

Returns the last error encountered by the connection or QDtlsError::NoError.

See also

dtlsErrorString() QDtlsError

PySide2.QtNetwork.QDtls.dtlsErrorString()
Return type:

str

Returns a textual description for the last error encountered by the connection or empty string.

See also

dtlsError()

PySide2.QtNetwork.QDtls.handleTimeout(socket)
Parameters:

socketPySide2.QtNetwork.QUdpSocket

Return type:

bool

If a timeout occurs during the handshake, the handshakeTimeout() signal is emitted. The application must call to retransmit handshake messages; returns true if a timeout has occurred, false otherwise. socket must be a valid pointer.

PySide2.QtNetwork.QDtls.handshakeState()
Return type:

HandshakeState

Returns the current handshake state for this QDtls .

See also

doHandshake() HandshakeState

PySide2.QtNetwork.QDtls.handshakeTimeout()
PySide2.QtNetwork.QDtls.ignoreVerificationErrors(errorsToIgnore)
Parameters:

errorsToIgnore

This method tells QDtls to ignore only the errors given in errorsToIgnore .

If, for instance, you want to connect to a server that uses a self-signed certificate, consider the following snippet:

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);

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.

PySide2.QtNetwork.QDtls.isConnectionEncrypted()
Return type:

bool

Returns true if DTLS handshake completed successfully.

PySide2.QtNetwork.QDtls.mtuHint()
Return type:

quint16

Returns the value previously set by setMtuHint() . The default value is 0.

See also

setMtuHint()

PySide2.QtNetwork.QDtls.peerAddress()
Return type:

PySide2.QtNetwork.QHostAddress

Returns the peer’s address, set by setPeer() , or Null .

See also

setPeer()

PySide2.QtNetwork.QDtls.peerPort()
Return type:

quint16

Returns the peer’s port number, set by setPeer() , or 0.

See also

setPeer()

PySide2.QtNetwork.QDtls.peerVerificationErrors()
Return type:

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() .

PySide2.QtNetwork.QDtls.peerVerificationName()
Return type:

str

Returns the host name set by setPeer() or setPeerVerificationName() . The default value is an empty string.

PySide2.QtNetwork.QDtls.pskRequired(authenticator)
Parameters:

authenticatorPySide2.QtNetwork.QSslPreSharedKeyAuthenticator

PySide2.QtNetwork.QDtls.resumeHandshake(socket)
Parameters:

socketPySide2.QtNetwork.QUdpSocket

Return type:

bool

If peer verification errors were ignored during the handshake, resumes and completes the handshake and returns true . socket must be a valid pointer. Returns false if the handshake could not be resumed.

PySide2.QtNetwork.QDtls.sessionCipher()
Return type:

PySide2.QtNetwork.QSslCipher

Returns the cryptographic 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.

PySide2.QtNetwork.QDtls.sessionProtocol()
Return type:

SslProtocol

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.

PySide2.QtNetwork.QDtls.setDtlsConfiguration(configuration)
Parameters:

configurationPySide2.QtNetwork.QSslConfiguration

Return type:

bool

Sets the connection’s TLS configuration from configuration and returns true if successful.

Note

This function must be called before the handshake starts.

PySide2.QtNetwork.QDtls.setMtuHint(mtuHint)
Parameters:

mtuHintquint16

mtuHint is the maximum transmission unit (MTU), either discovered or guessed by the application. The application is not required to set this value.

See also

mtuHint() PathMtuSocketOption

PySide2.QtNetwork.QDtls.setPeer(address, port[, verificationName={}])
Parameters:
Return type:

bool

Sets the peer’s address, port , and host name and returns true if successful. address must not be null, multicast, or broadcast. verificationName is the host name used for the certificate validation.

PySide2.QtNetwork.QDtls.setPeerVerificationName(name)
Parameters:

name – str

Return type:

bool

Sets the host name that will be used for the certificate validation and returns true if successful.

Note

This function must be called before the handshake starts.

PySide2.QtNetwork.QDtls.shutdown(socket)
Parameters:

socketPySide2.QtNetwork.QUdpSocket

Return type:

bool

Sends an encrypted shutdown alert message and closes the DTLS connection. Handshake state changes to HandshakeNotStarted . socket must be a valid pointer. This function returns true on success.

See also

doHandshake()

PySide2.QtNetwork.QDtls.sslMode()
Return type:

SslMode

Returns SslServerMode for a server-side connection and SslClientMode for a client.

See also

QDtls() SslMode

PySide2.QtNetwork.QDtls.writeDatagramEncrypted(socket, dgram)
Parameters:
Return type:

int

Encrypts dgram and writes the encrypted data into socket . Returns the number of bytes written, or -1 in case of error. The handshake must be completed before writing encrypted data. socket must be a valid pointer.