7#include <QtNetwork/qsslsocket.h>
8#include <QtNetwork/qssldiffiehellmanparameters.h>
16#include <QtNetwork/private/qssl_p.h>
17#include <QtNetwork/private/qsslsocket_p.h>
18#include <QtNetwork/private/qtlsbackend_p.h>
20#include <QtNetwork/private/qssldiffiehellmanparameters_p.h>
35extern "C" int qt_OCSP_status_server_callback(SSL *ssl,
void *);
46 unsigned *cookieLength);
48 unsigned cookieLength);
53extern "C" int q_ssl_sess_set_new_cb(SSL *
context, SSL_SESSION *session);
58 return QSslSocket::tr(
"Error when setting the OpenSSL configuration (%1)").
arg(why);
63 return QSslSocket::tr(
"Error when setting the elliptic curves (%1)").
arg(why);
72 case QSsl::TlsV1_0OrLater:
73 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
75 case QSsl::TlsV1_1OrLater:
76 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
81 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
84 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2;
92 options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
94 options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
96#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
99 options &= ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
101 options |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
104#ifdef SSL_OP_NO_TICKET
106 options |= SSL_OP_NO_TICKET;
108#ifdef SSL_OP_NO_COMPRESSION
110 options |= SSL_OP_NO_COMPRESSION;
114 options |= SSL_OP_CIPHER_SERVER_PREFERENCE;
123 m_sessionTicketLifeTimeHint(-1)
143 std::shared_ptr<QSslContext> sslContext = std::make_shared<AccessToPrivateCtor>();
144 initSslContext(sslContext.get(),
mode, configuration, allowRootCertOnDemandLoading);
149 bool allowRootCertOnDemandLoading)
154#ifndef OPENSSL_NO_NEXTPROTONEG
157 const unsigned char *
in,
unsigned int inlen,
void *
arg)
171 case OPENSSL_NPN_UNSUPPORTED:
174 case OPENSSL_NPN_NEGOTIATED:
177 case OPENSSL_NPN_NO_OVERLAP:
181 qCWarning(lcTlsBackend,
"OpenSSL sent unknown NPN status");
184 return SSL_TLSEXT_ERR_OK;
203 const unsigned char *
data =
reinterpret_cast<const unsigned char *
>(m_sessionASN1.
constData());
211 qCWarning(lcTlsBackend,
"could not set SSL session");
217#ifndef OPENSSL_NO_NEXTPROTONEG
220 m_supportedNPNVersions.
clear();
221 for (
int a = 0;
a < protocols.
size(); ++
a) {
222 if (protocols.
at(
a).size() > 255) {
223 qCWarning(lcTlsBackend) <<
"TLS NPN extension" << protocols.
at(
a)
224 <<
"is too long and will be ignored.";
226 }
else if (protocols.
at(
a).isEmpty()) {
231 if (m_supportedNPNVersions.
size()) {
232 m_npnContext.
data =
reinterpret_cast<unsigned char *
>(m_supportedNPNVersions.
data());
233 m_npnContext.
len = m_supportedNPNVersions.
size();
239 typedef int (*alpn_callback_t) (SSL *,
const unsigned char **,
unsigned char *,
240 const unsigned char *,
unsigned int,
void *);
272 if (sessionSize > 0) {
273 m_sessionASN1.
resize(sessionSize);
274 unsigned char *
data =
reinterpret_cast<unsigned char *
>(m_sessionASN1.
data());
276 qCWarning(lcTlsBackend,
"could not store persistent version of SSL session");
281 return (session !=
nullptr);
286 return m_sessionASN1;
291 m_sessionASN1 = session;
296 return m_sessionTicketLifeTimeHint;
301 *forceSecurityLevel() =
true;
316 bool allowRootCertOnDemandLoading)
318 sslContext->sslConfiguration = configuration;
323 bool reinitialized =
false;
324 bool unsupportedProtocol =
false;
327 switch (sslContext->sslConfiguration.
protocol()) {
331 case QSsl::DtlsV1_0OrLater:
337 sslContext->ctx =
q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
339 sslContext->ctx =
nullptr;
340 unsupportedProtocol =
true;
341 qCWarning(lcTlsBackend,
"DTLS protocol requested, but feature 'dtls' is disabled");
346#if !defined(TLS1_3_VERSION)
347 qCWarning(lcTlsBackend,
"TLS 1.3 is not supported");
348 sslContext->ctx =
nullptr;
349 unsupportedProtocol =
true;
357 if (!sslContext->ctx) {
360 if (!reinitialized) {
361 reinitialized =
true;
366 sslContext->errorStr = QSslSocket::tr(
"Error creating SSL context (%1)").
arg(
367 unsupportedProtocol ? QSslSocket::tr(
"unsupported protocol") :
QTlsBackendOpenSSL::getErrorsFromOpenSsl()
377 const long anyVersion =
379 isDtls ? DTLS_ANY_VERSION : TLS_ANY_VERSION;
383 long minVersion = anyVersion;
384 long maxVersion = anyVersion;
386 switch (sslContext->sslConfiguration.
protocol()) {
390 minVersion = TLS1_VERSION;
391 maxVersion = TLS1_VERSION;
394 minVersion = TLS1_1_VERSION;
395 maxVersion = TLS1_1_VERSION;
399 minVersion = TLS1_2_VERSION;
400 maxVersion = TLS1_2_VERSION;
404 minVersion = TLS1_3_VERSION;
405 maxVersion = TLS1_3_VERSION;
416 case QSsl::TlsV1_0OrLater:
417 minVersion = TLS1_VERSION;
420 case QSsl::TlsV1_1OrLater:
421 minVersion = TLS1_1_VERSION;
427 minVersion = TLS1_2_VERSION;
433 minVersion = DTLS1_VERSION;
434 maxVersion = DTLS1_VERSION;
436 case QSsl::DtlsV1_0OrLater:
437 minVersion = DTLS1_VERSION;
442 minVersion = DTLS1_2_VERSION;
443 maxVersion = DTLS1_2_VERSION;
446 minVersion = DTLS1_2_VERSION;
451 minVersion = TLS1_3_VERSION;
464 if (minVersion != anyVersion
466 sslContext->errorStr = QSslSocket::tr(
"Error while setting the minimal protocol version");
471 if (maxVersion != anyVersion
473 sslContext->errorStr = QSslSocket::tr(
"Error while setting the maximum protocol version");
492 if (selectTls13 != isTls13Cipher)
495 if (cipherString.
size())
497 cipherString.
append(cipher.name().toLatin1());
507 const QByteArray preTls13Ciphers = filterCiphers(ciphers,
false);
509 if (preTls13Ciphers.
size()) {
517 const QByteArray tls13Ciphers = filterCiphers(ciphers,
true);
519 if (tls13Ciphers.
size()) {
520 if (!q_SSL_CTX_set_ciphersuites(sslContext->ctx, tls13Ciphers.
data())) {
527 if (!preTls13Ciphers.
size() && !tls13Ciphers.
size()) {
528 sslContext->errorStr = QSslSocket::tr(
"Invalid or empty cipher list (%1)").
arg(
QStringLiteral(
""));
536 const auto caCertificates = sslContext->sslConfiguration.
caCertificates();
549 if (caCertificate.expiryDate() >=
now) {
558#if OPENSSL_VERSION_MAJOR < 3
565 if ((success = q_SSL_CTX_load_verify_dir(sslContext->ctx, unixDir.constData())) != 1)
571 qCWarning(lcTlsBackend) <<
"An error encountered while to set root certificates location:"
579 sslContext->errorStr = QSslSocket::tr(
"Cannot provide a certificate with no key");
592 sslContext->pkey =
reinterpret_cast<EVP_PKEY *
>(configuration.d->
privateKey.
handle());
594#ifdef OPENSSL_NO_DEPRECATED_3_0
595 auto qtKey = QTlsBackend::backend<QTlsPrivate::TlsKeyOpenSSL>(configuration.d->
privateKey);
597 sslContext->pkey =
qtKey->genericKey;
616 auto pkey = sslContext->pkey;
618 sslContext->pkey =
nullptr;
650 auto verificationCallback =
659 auto verificationMode = SSL_VERIFY_PEER;
661 verificationMode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
669 q_SSL_CTX_sess_set_new_cb(sslContext->ctx, q_ssl_sess_set_new_cb);
670 q_SSL_CTX_set_session_cache_mode(sslContext->ctx, SSL_SESS_CACHE_CLIENT);
695 sslContext->errorStr = QSslSocket::tr(
"Diffie-Hellman parameters are not valid");
701#ifndef OPENSSL_NO_DEPRECATED_3_0
707 qFatal(
"q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
711 qCWarning(lcTlsBackend,
"Diffie-Hellman parameters are not supported, because OpenSSL v3 was built with deprecated API removed");
715#ifndef OPENSSL_NO_PSK
720 const auto qcurves = sslContext->sslConfiguration.
ellipticCurves();
721 if (!qcurves.isEmpty()) {
728 std::vector<int> curves;
729 curves.reserve(qcurves.size());
730 for (
const auto &sslCurve : qcurves)
731 curves.push_back(sslCurve.
id);
732 if (!
q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES,
long(curves.size()), &curves[0])) {
740 applyBackendConfig(sslContext);
743void QSslContext::applyBackendConfig(
QSslContext *sslContext)
750 auto ocspResponsePos = conf.
find(
"Qt-OCSP-response");
751 if (ocspResponsePos != conf.
end()) {
755 q_SSL_CTX_set_tlsext_status_cb(sslContext->ctx, QTlsPrivate::qt_OCSP_status_server_callback);
756 if (conf.
size() == 1)
767 if (
i.key() ==
"Qt-OCSP-response")
770 if (!
i.value().canConvert(
QMetaType(QMetaType::QByteArray))) {
773 QSslSocket::tr(
"Expecting QByteArray for %1").
arg(
787 QSslSocket::tr(
"An error occurred attempting to set %1 to %2").
arg(
792 QSslSocket::tr(
"Wrong value for %1 (%2)").
arg(
797 QSslSocket::tr(
"Unrecognized command %1 = %2").
arg(
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
void clear()
Clears the contents of the byte array and makes it null.
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
\inmodule QtCore\reentrant
static QDateTime currentDateTimeUtc()
qsizetype size() const noexcept
bool isEmpty() const noexcept
const_reference at(qsizetype i) const noexcept
iterator find(const Key &key)
const_iterator constBegin() const
const_iterator constEnd() const
const T * constData() const noexcept
Returns a const pointer to the shared data object.
The QSslCertificate class provides a convenient API for an X509 certificate.
Qt::HANDLE handle() const
Returns a pointer to the native certificate handle, if there is one, else \nullptr.
bool isNull() const
Returns true if this is a null certificate (i.e., a certificate with no contents); otherwise returns ...
The QSslCipher class represents an SSL cryptographic cipher.
QSsl::SslOptions sslOptions
QList< QByteArray > nextAllowedProtocols
The QSslConfiguration class holds the configuration and state of an SSL connection.
QSslCertificate localCertificate() const
Returns the certificate to be presented to the peer during the SSL handshake process.
bool testSslOption(QSsl::SslOption option) const
QList< QSslCertificate > caCertificates() const
Returns this connection's CA certificate database.
QSslSocket::PeerVerifyMode peerVerifyMode() const
Returns the verify mode.
QSsl::SslProtocol protocol() const
Returns the protocol setting for this SSL configuration.
QSslDiffieHellmanParameters diffieHellmanParameters() const
QByteArray preSharedKeyIdentityHint() const
int peerVerifyDepth() const
Returns the maximum number of certificates in the peer's certificate chain to be checked during the S...
QSslKey privateKey() const
Returns the \l {QSslKey} {SSL key} assigned to this connection or a null key if none has been assigne...
QList< QSslEllipticCurve > ellipticCurves() const
QList< QSslCipher > ciphers() const
Returns this connection's current cryptographic cipher suite.
QByteArray sessionTicket() const
bool handshakeMustInterruptOnError() const
bool missingCertificateIsFatal() const
QMap< QByteArray, QVariant > backendConfiguration() const
@ NextProtocolNegotiationNone
@ NextProtocolNegotiationUnsupported
@ NextProtocolNegotiationNegotiated
QByteArray sessionASN1() const
static std::shared_ptr< QSslContext > sharedFromPrivateConfiguration(QSslSocket::SslMode mode, QSslConfigurationPrivate *privConfiguration, bool allowRootCertOnDemandLoading)
int sessionTicketLifeTimeHint() const
NPNContext npnContext() const
QString errorString() const
static void forceAutoTestSecurityLevel()
void setSessionASN1(const QByteArray &sessionASN1)
static qssloptions setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
QSslError::SslError error() const
static std::shared_ptr< QSslContext > sharedFromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
The QSslDiffieHellmanParameters class provides an interface for Diffie-Hellman parameters for servers...
bool isEmpty() const noexcept
Returns true if this is a an empty QSslDiffieHellmanParameters instance.
bool isValid() const noexcept
Returns true if this is a valid QSslDiffieHellmanParameters; otherwise false.
SslError
Describes all recognized errors that can occur during an SSL handshake.
QSsl::KeyAlgorithm algorithm() const
Returns the key algorithm.
Qt::HANDLE handle() const
Returns a pointer to the native key handle, if there is one, else \nullptr.
bool isNull() const
Returns true if this is a null key; otherwise false.
static QList< QByteArray > unixRootCertDirectories()
static bool rootCertOnDemandLoadingSupported()
SslMode
Describes the connection modes available for QSslSocket.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
static QString getErrorsFromOpenSsl()
QTlsBackend is a factory class, providing implementations for the QSsl classes.
@ SslOptionDisableSessionPersistence
@ SslOptionDisableCompression
@ SslOptionDisableSessionTickets
@ SslOptionDisableLegacyRenegotiation
@ SslOptionDisableServerCipherPreference
@ SslOptionDisableEmptyFragments
SslProtocol
Describes the protocol of the cipher.
Combined button and popup list for selecting options.
Namespace containing onternal types that TLS backends implement.
QList< QSslCipher > defaultCiphers()
int q_X509Callback(int ok, X509_STORE_CTX *ctx)
int q_X509CallbackDirect(int ok, X509_STORE_CTX *ctx)
int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx)
int q_generate_cookie_callback(SSL *ssl, unsigned char *dst, unsigned *cookieLength)
int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie, unsigned cookieLength)
#define QT_WARNING_DISABLE_DEPRECATED
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qCWarning(category,...)
static ControlElement< T > * ptr(QWidget *widget)
GLboolean GLboolean GLboolean GLboolean a
[7]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
static QString qtKey(CFStringRef cfkey)
static int next_proto_cb(SSL *, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
static QString msgErrorSettingEllipticCurves(const QString &why)
static QString msgErrorSettingBackendConfig(const QString &why)
void q_SSL_CTX_free(SSL_CTX *a)
const SSL_METHOD * q_TLS_server_method()
int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b)
DH * q_d2i_DHparams(DH **a, const unsigned char **pp, long length)
void q_SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *a, SSL_CTX *b)
unsigned long qssloptions
int q_SSL_CTX_get_security_level(const SSL_CTX *ctx)
void q_SSL_SESSION_free(SSL_SESSION *ses)
int q_SSL_set_session(SSL *to, SSL_SESSION *session)
long q_SSL_CTX_ctrl(SSL_CTX *a, int b, long c, void *d)
int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath)
int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b)
unsigned int q_SSL_CONF_CTX_set_flags(SSL_CONF_CTX *a, unsigned int b)
int q_SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, const unsigned char *client, unsigned int client_len)
int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b)
X509 * q_X509_dup(X509 *a)
void q_SSL_CONF_CTX_free(SSL_CONF_CTX *a)
int q_SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, unsigned protos_len)
void q_SSL_CTX_set_verify_depth(SSL_CTX *a, int b)
SSL_CTX * q_SSL_CTX_new(const SSL_METHOD *a)
int q_SSL_CTX_use_certificate(SSL_CTX *a, X509 *b)
SSL_SESSION * q_d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length)
EVP_PKEY * q_EVP_PKEY_new()
void q_EVP_PKEY_free(EVP_PKEY *a)
int q_SSL_CONF_cmd(SSL_CONF_CTX *a, const char *b, const char *c)
#define q_SSL_CTX_set_min_proto_version(ctx, version)
X509_STORE * q_SSL_CTX_get_cert_store(const SSL_CTX *a)
int q_SSL_CTX_check_private_key(const SSL_CTX *a)
unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session)
int q_SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *hint)
int q_i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
int q_EVP_PKEY_up_ref(EVP_PKEY *a)
SSL_SESSION * q_SSL_get_session(const SSL *ssl)
void q_SSL_CTX_set_next_proto_select_cb(SSL_CTX *s, int(*cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg), void *arg)
void q_SSL_CTX_set_security_level(SSL_CTX *ctx, int level)
const SSL_METHOD * q_TLS_client_method()
SSL * q_SSL_new(SSL_CTX *a)
int q_SSL_CTX_set_cipher_list(SSL_CTX *a, const char *b)
int q_X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
#define q_SSL_CTX_set_tmp_dh(ctx, dh)
SSL_SESSION * q_SSL_get1_session(SSL *ssl)
void q_SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, int(*cb)(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg), void *arg)
int q_SSL_CTX_use_PrivateKey(SSL_CTX *a, EVP_PKEY *b)
void q_SSL_CTX_set_verify(SSL_CTX *a, int b, int(*c)(int, X509_STORE_CTX *))
#define q_SSL_CTX_set_mode(ctx, op)
SSL_CONF_CTX * q_SSL_CONF_CTX_new()
int q_SSL_CONF_CTX_finish(SSL_CONF_CTX *a)
qssloptions q_SSL_CTX_set_options(SSL_CTX *ctx, qssloptions op)
int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
#define q_SSL_CTX_set_max_proto_version(ctx, version)
#define QStringLiteral(str)
QTextStream out(stdout)
[7]
QList< QSslCertificate > cert
[0]
QSslConfiguration::NextProtocolNegotiationStatus status