1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2018 The Qt Company Ltd. 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of the QtNetwork module of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see https://www.qt.io/terms-conditions. For further 15 ** information use the contact form at https://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 3 as published by the Free Software 20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 21 ** packaging of this file. Please review the following information to 22 ** ensure the GNU Lesser General Public License version 3 requirements 23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24 ** 25 ** GNU General Public License Usage 26 ** Alternatively, this file may be used under the terms of the GNU 27 ** General Public License version 2.0 or (at your option) the GNU General 28 ** Public license version 3 or any later version approved by the KDE Free 29 ** Qt Foundation. The licenses are as published by the Free Software 30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31 ** included in the packaging of this file. Please review the following 32 ** information to ensure the GNU General Public License requirements will 33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and 34 ** https://www.gnu.org/licenses/gpl-3.0.html. 35 ** 36 ** $QT_END_LICENSE$ 37 ** 38 ****************************************************************************/ 39 40 #ifndef QDTLS_OPENSSL_P_H 41 #define QDTLS_OPENSSL_P_H 42 43 #include <private/qtnetworkglobal_p.h> 44 45 #include <QtCore/qglobal.h> 46 47 #include <openssl/ossl_typ.h> 48 49 #include "qdtls_p.h" 50 51 #include <private/qsslcontext_openssl_p.h> 52 #include <private/qsslsocket_openssl_p.h> 53 54 #include <QtNetwork/qsslpresharedkeyauthenticator.h> 55 #include <QtNetwork/qhostaddress.h> 56 57 #include <QtCore/qcryptographichash.h> 58 #include <QtCore/qsharedpointer.h> 59 #include <QtCore/qbytearray.h> 60 #include <QtCore/qvector.h> 61 62 // 63 // W A R N I N G 64 // ------------- 65 // 66 // This file is not part of the Qt API. It exists purely as an 67 // implementation detail. This header file may change from version to 68 // version without notice, or even be removed. 69 // 70 // We mean it. 71 // 72 73 QT_REQUIRE_CONFIG(openssl); 74 QT_REQUIRE_CONFIG(dtls); 75 76 QT_BEGIN_NAMESPACE 77 78 class QDtlsPrivateOpenSSL; 79 class QUdpSocket; 80 81 namespace dtlsopenssl 82 { 83 84 class DtlsState 85 { 86 public: 87 // Note, bioMethod _must_ outlive BIOs it was used to create. Thus 88 // the order of declarations here matters. 89 using BioMethod = QSharedPointer<BIO_METHOD>; 90 BioMethod bioMethod; 91 92 using TlsContext = QSharedPointer<QSslContext>; 93 TlsContext tlsContext; 94 95 using TlsConnection = QSharedPointer<SSL>; 96 TlsConnection tlsConnection; 97 98 QByteArray dgram; 99 100 QHostAddress remoteAddress; 101 quint16 remotePort = 0; 102 103 QVector<QSslErrorEntry> x509Errors; 104 105 long peeking = false; 106 QUdpSocket *udpSocket = nullptr; 107 bool writeSuppressed = false; 108 109 bool init(QDtlsBasePrivate *dtlsBase, QUdpSocket *socket, 110 const QHostAddress &remote, quint16 port, 111 const QByteArray &receivedMessage); 112 113 void reset(); 114 115 QDtlsPrivateOpenSSL *dtlsPrivate = nullptr; 116 QByteArray secret; 117 118 #ifdef QT_CRYPTOGRAPHICHASH_ONLY_SHA1 119 QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha1; 120 #else 121 QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha256; 122 #endif 123 124 private: 125 126 bool initTls(QDtlsBasePrivate *dtlsBase); 127 bool initCtxAndConnection(QDtlsBasePrivate *dtlsBase); 128 bool initBIO(QDtlsBasePrivate *dtlsBase); 129 void setLinkMtu(QDtlsBasePrivate *dtlsBase); 130 }; 131 132 } // namespace dtlsopenssl 133 134 class QDtlsClientVerifierOpenSSL : public QDtlsClientVerifierPrivate 135 { 136 public: 137 138 QDtlsClientVerifierOpenSSL(); 139 140 bool verifyClient(QUdpSocket *socket, const QByteArray &dgram, 141 const QHostAddress &address, quint16 port) override; 142 143 private: 144 dtlsopenssl::DtlsState dtls; 145 }; 146 147 class QDtlsPrivateOpenSSL : public QDtlsPrivate 148 { 149 public: 150 QDtlsPrivateOpenSSL(); 151 152 bool startHandshake(QUdpSocket *socket, const QByteArray &datagram) override; 153 bool continueHandshake(QUdpSocket *socket, const QByteArray &datagram) override; 154 bool resumeHandshake(QUdpSocket *socket) override; 155 void abortHandshake(QUdpSocket *socket) override; 156 bool handleTimeout(QUdpSocket *socket) override; 157 void sendShutdownAlert(QUdpSocket *socket) override; 158 159 qint64 writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &datagram) override; 160 QByteArray decryptDatagram(QUdpSocket *socket, const QByteArray &tlsdgram) override; 161 162 unsigned pskClientCallback(const char *hint, char *identity, unsigned max_identity_len, 163 unsigned char *psk, unsigned max_psk_len); 164 unsigned pskServerCallback(const char *identity, unsigned char *psk, 165 unsigned max_psk_len); 166 167 private: 168 169 bool verifyPeer(); 170 void storePeerCertificates(); 171 bool tlsErrorsWereIgnored() const; 172 void fetchNegotiatedParameters(); 173 void reportTimeout(); 174 void resetDtls(); 175 176 QVector<QSslErrorEntry> opensslErrors; 177 dtlsopenssl::DtlsState dtls; 178 179 // We have to externally handle timeouts since we have non-blocking 180 // sockets and OpenSSL(DTLS) with non-blocking UDP sockets does not 181 // know if a timeout has occurred. 182 struct TimeoutHandler : QObject 183 { 184 TimeoutHandler() = default; 185 186 void start(int hintMs = 0); 187 void doubleTimeout(); resetTimeoutTimeoutHandler188 void resetTimeout() {timeoutMs = 1000;} 189 void stop(); 190 void timerEvent(QTimerEvent *event); 191 192 int timerId = -1; 193 int timeoutMs = 1000; 194 195 QDtlsPrivateOpenSSL *dtlsConnection = nullptr; 196 }; 197 198 // We will initialize it 'lazily', just in case somebody wants to move 199 // QDtls to another thread. 200 QScopedPointer<TimeoutHandler> timeoutHandler; 201 bool connectionWasShutdown = false; 202 QSslPreSharedKeyAuthenticator pskAuthenticator; 203 QByteArray identityHint; 204 205 Q_DECLARE_PUBLIC(QDtls) 206 }; 207 208 209 210 QT_END_NAMESPACE 211 212 #endif // QDTLS_OPENSSL_P_H 213