43 #include <QtNetwork/qsslsocket.h>
44 #include <QtNetwork/qssldiffiehellmanparameters.h>
52 #include <QtNetwork/private/qssl_p.h>
53 #include <QtNetwork/private/qsslsocket_p.h>
54 #include <QtNetwork/private/qtlsbackend_p.h>
56 #include <QtNetwork/private/qssldiffiehellmanparameters_p.h>
71 extern "C" int qt_OCSP_status_server_callback(SSL *ssl,
void *);
82 unsigned *cookieLength);
84 unsigned cookieLength);
89 extern "C" int q_ssl_sess_set_new_cb(SSL *
context, SSL_SESSION *session);
92 static inline QString msgErrorSettingBackendConfig(
const QString &why)
94 return QSslSocket::tr(
"Error when setting the OpenSSL configuration (%1)").arg(why);
97 static inline QString msgErrorSettingEllipticCurves(
const QString &why)
99 return QSslSocket::tr(
"Error when setting the elliptic curves (%1)").arg(why);
108 case QSsl::TlsV1_0OrLater:
109 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
111 case QSsl::TlsV1_1OrLater:
112 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
117 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
120 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;
123 options = SSL_OP_ALL;
128 options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
130 options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
132 #ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
135 options &= ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
137 options |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
140 #ifdef SSL_OP_NO_TICKET
142 options |= SSL_OP_NO_TICKET;
144 #ifdef SSL_OP_NO_COMPRESSION
146 options |= SSL_OP_NO_COMPRESSION;
150 options |= SSL_OP_CIPHER_SERVER_PREFERENCE;
159 m_sessionTicketLifeTimeHint(-1)
179 std::shared_ptr<QSslContext> sslContext = std::make_shared<AccessToPrivateCtor>();
180 initSslContext(sslContext.get(),
mode, configuration, allowRootCertOnDemandLoading);
185 bool allowRootCertOnDemandLoading)
190 #ifndef OPENSSL_NO_NEXTPROTONEG
192 static int next_proto_cb(SSL *,
unsigned char **
out,
unsigned char *outlen,
193 const unsigned char *
in,
unsigned int inlen,
void *
arg)
207 case OPENSSL_NPN_UNSUPPORTED:
210 case OPENSSL_NPN_NEGOTIATED:
213 case OPENSSL_NPN_NO_OVERLAP:
217 qCWarning(lcTlsBackend,
"OpenSSL sent unknown NPN status");
220 return SSL_TLSEXT_ERR_OK;
239 const unsigned char *
data =
reinterpret_cast<const unsigned char *
>(m_sessionASN1.
constData());
247 qCWarning(lcTlsBackend,
"could not set SSL session");
253 #ifndef OPENSSL_NO_NEXTPROTONEG
256 m_supportedNPNVersions.
clear();
257 for (
int a = 0;
a < protocols.
count(); ++
a) {
258 if (protocols.
at(
a).
size() > 255) {
259 qCWarning(lcTlsBackend) <<
"TLS NPN extension" << protocols.
at(
a)
260 <<
"is too long and will be ignored.";
267 if (m_supportedNPNVersions.
size()) {
268 m_npnContext.
data =
reinterpret_cast<unsigned char *
>(m_supportedNPNVersions.
data());
269 m_npnContext.
len = m_supportedNPNVersions.
count();
275 typedef int (*alpn_callback_t) (SSL *,
const unsigned char **,
unsigned char *,
276 const unsigned char *,
unsigned int,
void *);
308 if (sessionSize > 0) {
309 m_sessionASN1.
resize(sessionSize);
310 unsigned char *
data =
reinterpret_cast<unsigned char *
>(m_sessionASN1.
data());
312 qCWarning(lcTlsBackend,
"could not store persistent version of SSL session");
317 return (session !=
nullptr);
322 return m_sessionASN1;
327 m_sessionASN1 = session;
332 return m_sessionTicketLifeTimeHint;
337 *forceSecurityLevel() =
true;
352 bool allowRootCertOnDemandLoading)
354 sslContext->sslConfiguration = configuration;
359 bool reinitialized =
false;
360 bool unsupportedProtocol =
false;
363 switch (sslContext->sslConfiguration.
protocol()) {
367 case QSsl::DtlsV1_0OrLater:
373 sslContext->ctx =
q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
375 sslContext->ctx =
nullptr;
376 unsupportedProtocol =
true;
377 qCWarning(lcTlsBackend,
"DTLS protocol requested, but feature 'dtls' is disabled");
382 #if !defined(TLS1_3_VERSION)
383 qCWarning(lcTlsBackend,
"TLS 1.3 is not supported");
384 sslContext->ctx =
nullptr;
385 unsupportedProtocol =
true;
393 if (!sslContext->ctx) {
396 if (!reinitialized) {
397 reinitialized =
true;
402 sslContext->errorStr =
QSslSocket::tr(
"Error creating SSL context (%1)").arg(
413 const long anyVersion =
415 isDtls ? DTLS_ANY_VERSION : TLS_ANY_VERSION;
419 long minVersion = anyVersion;
420 long maxVersion = anyVersion;
422 switch (sslContext->sslConfiguration.
protocol()) {
426 minVersion = TLS1_VERSION;
427 maxVersion = TLS1_VERSION;
430 minVersion = TLS1_1_VERSION;
431 maxVersion = TLS1_1_VERSION;
435 minVersion = TLS1_2_VERSION;
436 maxVersion = TLS1_2_VERSION;
439 #ifdef TLS1_3_VERSION
440 minVersion = TLS1_3_VERSION;
441 maxVersion = TLS1_3_VERSION;
452 case QSsl::TlsV1_0OrLater:
453 minVersion = TLS1_VERSION;
456 case QSsl::TlsV1_1OrLater:
457 minVersion = TLS1_1_VERSION;
463 minVersion = TLS1_2_VERSION;
469 minVersion = DTLS1_VERSION;
470 maxVersion = DTLS1_VERSION;
472 case QSsl::DtlsV1_0OrLater:
473 minVersion = DTLS1_VERSION;
478 minVersion = DTLS1_2_VERSION;
479 maxVersion = DTLS1_2_VERSION;
482 minVersion = DTLS1_2_VERSION;
486 #ifdef TLS1_3_VERSION
487 minVersion = TLS1_3_VERSION;
500 if (minVersion != anyVersion
502 sslContext->errorStr =
QSslSocket::tr(
"Error while setting the minimal protocol version");
507 if (maxVersion != anyVersion
509 sslContext->errorStr =
QSslSocket::tr(
"Error while setting the maximum protocol version");
528 if (selectTls13 != isTls13Cipher)
531 if (cipherString.
size())
533 cipherString.
append(cipher.name().toLatin1());
543 const QByteArray preTls13Ciphers = filterCiphers(ciphers,
false);
545 if (preTls13Ciphers.
size()) {
553 const QByteArray tls13Ciphers = filterCiphers(ciphers,
true);
554 #ifdef TLS1_3_VERSION
555 if (tls13Ciphers.
size()) {
556 if (!q_SSL_CTX_set_ciphersuites(sslContext->ctx, tls13Ciphers.
data())) {
563 if (!preTls13Ciphers.
size() && !tls13Ciphers.
size()) {
572 const auto caCertificates = sslContext->sslConfiguration.
caCertificates();
585 if (caCertificate.expiryDate() >=
now) {
594 #if OPENSSL_VERSION_MAJOR < 3
601 if ((success = q_SSL_CTX_load_verify_dir(sslContext->ctx, unixDir.constData())) != 1)
607 qCWarning(lcTlsBackend) <<
"An error encountered while to set root certificates location:"
615 sslContext->errorStr =
QSslSocket::tr(
"Cannot provide a certificate with no key");
628 sslContext->pkey =
reinterpret_cast<EVP_PKEY *
>(configuration.d->
privateKey.
handle());
630 #ifdef OPENSSL_NO_DEPRECATED_3_0
631 auto qtKey = QTlsBackend::backend<QTlsPrivate::TlsKeyOpenSSL>(configuration.d->
privateKey);
633 sslContext->pkey = qtKey->genericKey;
646 #ifndef OPENSSL_NO_EC
652 auto pkey = sslContext->pkey;
654 sslContext->pkey =
nullptr;
686 auto verificationCallback =
695 auto verificationMode = SSL_VERIFY_PEER;
697 verificationMode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
702 #ifdef TLS1_3_VERSION
705 q_SSL_CTX_sess_set_new_cb(sslContext->ctx, q_ssl_sess_set_new_cb);
706 q_SSL_CTX_set_session_cache_mode(sslContext->ctx, SSL_SESS_CACHE_CLIENT);
731 sslContext->errorStr =
QSslSocket::tr(
"Diffie-Hellman parameters are not valid");
737 #ifndef OPENSSL_NO_DEPRECATED_3_0
740 DH *dh =
q_d2i_DHparams(
nullptr,
reinterpret_cast<const unsigned char **
>(&ptr),
743 qFatal(
"q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
747 qCWarning(lcTlsBackend,
"Diffie-Hellman parameters are not supported, because OpenSSL v3 was built with deprecated API removed");
751 #ifndef OPENSSL_NO_PSK
756 const auto qcurves = sslContext->sslConfiguration.
ellipticCurves();
757 if (!qcurves.isEmpty()) {
759 sslContext->errorStr = msgErrorSettingEllipticCurves(
QSslSocket::tr(
"OpenSSL version with disabled elliptic curves"));
764 std::vector<int> curves;
765 curves.reserve(qcurves.size());
766 for (
const auto &sslCurve : qcurves)
767 curves.push_back(sslCurve.id);
768 if (!
q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES,
long(curves.size()), &curves[0])) {
776 applyBackendConfig(sslContext);
779 void QSslContext::applyBackendConfig(
QSslContext *sslContext)
786 auto ocspResponsePos = conf.
find(
"Qt-OCSP-response");
787 if (ocspResponsePos != conf.
end()) {
791 q_SSL_CTX_set_tlsext_status_cb(sslContext->ctx, QTlsPrivate::qt_OCSP_status_server_callback);
792 if (conf.
size() == 1)
803 if (
i.key() ==
"Qt-OCSP-response")
808 sslContext->errorStr = msgErrorSettingBackendConfig(
822 sslContext->errorStr = msgErrorSettingBackendConfig(
827 sslContext->errorStr = msgErrorSettingBackendConfig(
832 sslContext->errorStr = msgErrorSettingBackendConfig(
840 sslContext->errorStr = msgErrorSettingBackendConfig(
QSslSocket::tr(
"SSL_CONF_finish() failed"));
844 sslContext->errorStr = msgErrorSettingBackendConfig(
QSslSocket::tr(
"SSL_CONF_CTX_new() failed"));
small capitals from c petite p scientific i
[1]
The QByteArray class provides an array of bytes.
qsizetype size() const noexcept
const char * constData() const noexcept
bool isEmpty() const noexcept
void resize(qsizetype size)
QByteArray & append(char c)
qsizetype count(char c) const
The QDateTime class provides date and time functions.
static QDateTime currentDateTimeUtc()
bool isEmpty() const noexcept
const_reference at(qsizetype i) const noexcept
qsizetype count() const noexcept
iterator find(const Key &key)
const_iterator constBegin() const
const_iterator constEnd() const
const T * constData() const noexcept
The QSharedPointer class holds a strong reference to a shared pointer.
The QSslCertificate class provides a convenient API for an X509 certificate.
Qt::HANDLE handle() const
The QSslCipher class represents an SSL cryptographic cipher.
The QSslConfiguration class holds the configuration and state of an SSL connection.
QSslCertificate localCertificate() const
bool testSslOption(QSsl::SslOption option) const
QList< QSslCertificate > caCertificates() const
QSslSocket::PeerVerifyMode peerVerifyMode() const
QSsl::SslProtocol protocol() const
QSslDiffieHellmanParameters diffieHellmanParameters() const
QByteArray preSharedKeyIdentityHint() const
int peerVerifyDepth() const
QSslKey privateKey() const
QList< QSslEllipticCurve > ellipticCurves() const
QList< QSslCipher > ciphers() const
QByteArray sessionTicket() const
bool handshakeMustInterruptOnError() const
bool missingCertificateIsFatal() const
QMap< QByteArray, QVariant > backendConfiguration() const
@ NextProtocolNegotiationNone
@ NextProtocolNegotiationUnsupported
@ NextProtocolNegotiationNegotiated
QSsl::SslOptions sslOptions
QList< QByteArray > nextAllowedProtocols
QList< QSslCertificate > localCertificateChain
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()
static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
void setSessionASN1(const QByteArray &sessionASN1)
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
bool isValid() const noexcept
QSsl::KeyAlgorithm algorithm() const
Qt::HANDLE handle() const
static QList< QByteArray > unixRootCertDirectories()
static bool rootCertOnDemandLoadingSupported()
The QString class provides a Unicode character string.
static QString fromUtf8(QByteArrayView utf8)
static QString getErrorsFromOpenSsl()
@ SslOptionDisableSessionPersistence
@ SslOptionDisableCompression
@ SslOptionDisableSessionTickets
@ SslOptionDisableLegacyRenegotiation
@ SslOptionDisableServerCipherPreference
@ SslOptionDisableEmptyFragments
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
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qCWarning(category,...)
GLboolean GLboolean GLboolean GLboolean a
[7]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
SSL_SESSION * q_d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length)
void q_SSL_CTX_free(SSL_CTX *a)
int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b)
void q_SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *a, SSL_CTX *b)
int q_SSL_CTX_get_security_level(const SSL_CTX *ctx)
const SSL_METHOD * q_TLS_client_method()
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)
const SSL_METHOD * q_TLS_server_method()
int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b)
X509 * q_X509_dup(X509 *a)
unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op)
X509_STORE * q_SSL_CTX_get_cert_store(const SSL_CTX *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)
SSL * q_SSL_new(SSL_CTX *a)
void q_SSL_CTX_set_verify_depth(SSL_CTX *a, int b)
int q_SSL_CTX_use_certificate(SSL_CTX *a, X509 *b)
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)
SSL_CTX * q_SSL_CTX_new(const SSL_METHOD *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)
SSL_SESSION * q_SSL_get1_session(SSL *ssl)
int q_EVP_PKEY_up_ref(EVP_PKEY *a)
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)
DH * q_d2i_DHparams(DH **a, const unsigned char **pp, long length)
SSL_SESSION * q_SSL_get_session(const SSL *ssl)
EVP_PKEY * q_EVP_PKEY_new()
int q_SSL_CTX_set_cipher_list(SSL_CTX *a, const char *b)
int q_X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
SSL_CONF_CTX * q_SSL_CONF_CTX_new()
#define q_SSL_CTX_set_tmp_dh(ctx, dh)
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)
int q_SSL_CONF_CTX_finish(SSL_CONF_CTX *a)
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