diff options
Diffstat (limited to 'src/network/ssl')
-rw-r--r-- | src/network/ssl/qdtls.h | 2 | ||||
-rw-r--r-- | src/network/ssl/qocspresponse.cpp | 2 | ||||
-rw-r--r-- | src/network/ssl/qocspresponse.h | 2 | ||||
-rw-r--r-- | src/network/ssl/qpassworddigestor.cpp | 100 | ||||
-rw-r--r-- | src/network/ssl/qssl.cpp | 2 | ||||
-rw-r--r-- | src/network/ssl/qssl.h | 13 | ||||
-rw-r--r-- | src/network/ssl/qsslcertificate.cpp | 74 | ||||
-rw-r--r-- | src/network/ssl/qsslcertificate.h | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslcertificate_p.h | 4 | ||||
-rw-r--r-- | src/network/ssl/qsslconfiguration.cpp | 41 | ||||
-rw-r--r-- | src/network/ssl/qsslconfiguration.h | 2 | ||||
-rw-r--r-- | src/network/ssl/qssldiffiehellmanparameters.cpp | 16 | ||||
-rw-r--r-- | src/network/ssl/qsslellipticcurve.cpp | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslkey.h | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslpresharedkeyauthenticator.h | 1 | ||||
-rw-r--r-- | src/network/ssl/qsslserver.cpp | 151 | ||||
-rw-r--r-- | src/network/ssl/qsslserver.h | 3 | ||||
-rw-r--r-- | src/network/ssl/qsslserver_p.h | 34 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket.cpp | 42 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket.h | 2 | ||||
-rw-r--r-- | src/network/ssl/qtlsbackend.cpp | 36 | ||||
-rw-r--r-- | src/network/ssl/qtlsbackend_p.h | 18 |
22 files changed, 433 insertions, 118 deletions
diff --git a/src/network/ssl/qdtls.h b/src/network/ssl/qdtls.h index 903ba5b4e1..dd24aa219a 100644 --- a/src/network/ssl/qdtls.h +++ b/src/network/ssl/qdtls.h @@ -15,7 +15,7 @@ Q_MOC_INCLUDE(<QtNetwork/QSslPreSharedKeyAuthenticator>) -#ifndef Q_CLANG_QDOC +#ifndef Q_QDOC QT_REQUIRE_CONFIG(dtls); #endif diff --git a/src/network/ssl/qocspresponse.cpp b/src/network/ssl/qocspresponse.cpp index 9911988aff..74e2c814fd 100644 --- a/src/network/ssl/qocspresponse.cpp +++ b/src/network/ssl/qocspresponse.cpp @@ -201,8 +201,6 @@ bool QOcspResponse::isEqual(const QOcspResponse &other) const } /*! - \fn size_t qHash(const QOcspResponse &response, size_t seed) - Returns the hash value for the \a response, using \a seed to seed the calculation. \since 5.13 diff --git a/src/network/ssl/qocspresponse.h b/src/network/ssl/qocspresponse.h index d208edab7a..68251a1547 100644 --- a/src/network/ssl/qocspresponse.h +++ b/src/network/ssl/qocspresponse.h @@ -11,7 +11,7 @@ #include <QtCore/qmetatype.h> #include <QtCore/qobject.h> -#ifndef Q_CLANG_QDOC +#ifndef Q_QDOC QT_REQUIRE_CONFIG(ssl); #endif diff --git a/src/network/ssl/qpassworddigestor.cpp b/src/network/ssl/qpassworddigestor.cpp index a6c6e7666c..94de14abd4 100644 --- a/src/network/ssl/qpassworddigestor.cpp +++ b/src/network/ssl/qpassworddigestor.cpp @@ -6,9 +6,20 @@ #include <QtCore/QDebug> #include <QtCore/QMessageAuthenticationCode> #include <QtCore/QtEndian> +#include <QtCore/QList> + +#include "qtcore-config_p.h" #include <limits> +#if QT_CONFIG(opensslv30) && QT_CONFIG(openssl_linked) +#define USING_OPENSSL30 +#include <openssl/core_names.h> +#include <openssl/kdf.h> +#include <openssl/params.h> +#include <openssl/provider.h> +#endif + QT_BEGIN_NAMESPACE namespace QPasswordDigestor { @@ -86,6 +97,85 @@ Q_NETWORK_EXPORT QByteArray deriveKeyPbkdf1(QCryptographicHash::Algorithm algori return key.left(dkLen); } +#ifdef USING_OPENSSL30 +// Copied from QCryptographicHashPrivate +static constexpr const char * methodToName(QCryptographicHash::Algorithm method) noexcept +{ + switch (method) { +#define CASE(Enum, Name) \ + case QCryptographicHash:: Enum : \ + return Name \ + /*end*/ + CASE(Sha1, "SHA1"); + CASE(Md4, "MD4"); + CASE(Md5, "MD5"); + CASE(Sha224, "SHA224"); + CASE(Sha256, "SHA256"); + CASE(Sha384, "SHA384"); + CASE(Sha512, "SHA512"); + CASE(RealSha3_224, "SHA3-224"); + CASE(RealSha3_256, "SHA3-256"); + CASE(RealSha3_384, "SHA3-384"); + CASE(RealSha3_512, "SHA3-512"); + CASE(Keccak_224, "SHA3-224"); + CASE(Keccak_256, "SHA3-256"); + CASE(Keccak_384, "SHA3-384"); + CASE(Keccak_512, "SHA3-512"); + CASE(Blake2b_512, "BLAKE2B512"); + CASE(Blake2s_256, "BLAKE2S256"); +#undef CASE + default: return nullptr; + } +} + +static QByteArray opensslDeriveKeyPbkdf2(QCryptographicHash::Algorithm algorithm, + const QByteArray &data, const QByteArray &salt, + uint64_t iterations, quint64 dkLen) +{ + EVP_KDF *kdf = EVP_KDF_fetch(nullptr, "PBKDF2", nullptr); + + if (!kdf) + return QByteArray(); + + auto cleanUpKdf = qScopeGuard([kdf] { + EVP_KDF_free(kdf); + }); + + EVP_KDF_CTX *ctx = EVP_KDF_CTX_new(kdf); + + if (!ctx) + return QByteArray(); + + auto cleanUpCtx = qScopeGuard([ctx] { + EVP_KDF_CTX_free(ctx); + }); + + // Do not enable SP800-132 compliance check, otherwise we will require: + // - the iteration count is at least 1000 + // - the salt length is at least 128 bits + // - the derived key length is at least 112 bits + // This would be a different behavior from the original implementation. + int checkDisabled = 1; + QList<OSSL_PARAM> params; + params.append(OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, const_cast<char*>(methodToName(algorithm)), 0)); + params.append(OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, const_cast<char*>(salt.data()), salt.size())); + params.append(OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD, const_cast<char*>(data.data()), data.size())); + params.append(OSSL_PARAM_construct_uint64(OSSL_KDF_PARAM_ITER, &iterations)); + params.append(OSSL_PARAM_construct_int(OSSL_KDF_PARAM_PKCS5, &checkDisabled)); + params.append(OSSL_PARAM_construct_end()); + + if (EVP_KDF_CTX_set_params(ctx, params.data()) <= 0) + return QByteArray(); + + QByteArray derived(dkLen, '\0'); + + if (!EVP_KDF_derive(ctx, reinterpret_cast<unsigned char*>(derived.data()), derived.size(), nullptr)) + return QByteArray(); + + return derived; +} +#endif + /*! \since 5.12 @@ -107,8 +197,6 @@ Q_NETWORK_EXPORT QByteArray deriveKeyPbkdf2(QCryptographicHash::Algorithm algori const QByteArray &data, const QByteArray &salt, int iterations, quint64 dkLen) { - // https://tools.ietf.org/html/rfc8018#section-5.2 - // The RFC recommends checking that 'dkLen' is not greater than '(2^32 - 1) * hLen' int hashLen = QCryptographicHash::hashLength(algorithm); const quint64 maxLen = quint64(std::numeric_limits<quint32>::max() - 1) * hashLen; @@ -122,11 +210,17 @@ Q_NETWORK_EXPORT QByteArray deriveKeyPbkdf2(QCryptographicHash::Algorithm algori if (iterations < 1 || dkLen < 1) return QByteArray(); +#ifdef USING_OPENSSL30 + if (methodToName(algorithm)) + return opensslDeriveKeyPbkdf2(algorithm, data, salt, iterations, dkLen); +#endif + + // https://tools.ietf.org/html/rfc8018#section-5.2 QByteArray key; quint32 currentIteration = 1; QMessageAuthenticationCode hmac(algorithm, data); QByteArray index(4, Qt::Uninitialized); - while (quint64(key.length()) < dkLen) { + while (quint64(key.size()) < dkLen) { hmac.addData(salt); qToBigEndian(currentIteration, index.data()); diff --git a/src/network/ssl/qssl.cpp b/src/network/ssl/qssl.cpp index 7525df8c87..dfd3745d3e 100644 --- a/src/network/ssl/qssl.cpp +++ b/src/network/ssl/qssl.cpp @@ -256,3 +256,5 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl"); */ QT_END_NAMESPACE + +#include "moc_qssl.cpp" diff --git a/src/network/ssl/qssl.h b/src/network/ssl/qssl.h index 3d01168172..e52b8c6361 100644 --- a/src/network/ssl/qssl.h +++ b/src/network/ssl/qssl.h @@ -10,21 +10,26 @@ #endif #include <QtNetwork/qtnetworkglobal.h> +#include <QtCore/qobjectdefs.h> #include <QtCore/QFlags> QT_BEGIN_NAMESPACE namespace QSsl { + Q_NAMESPACE_EXPORT(Q_NETWORK_EXPORT) + enum KeyType { PrivateKey, PublicKey }; + Q_ENUM_NS(KeyType) enum EncodingFormat { Pem, Der }; + Q_ENUM_NS(EncodingFormat) enum KeyAlgorithm { Opaque, @@ -33,12 +38,14 @@ namespace QSsl { Ec, Dh, }; + Q_ENUM_NS(KeyAlgorithm) enum AlternativeNameEntryType { EmailEntry, DnsEntry, IpAddressEntry }; + Q_ENUM_NS(AlternativeNameEntryType) enum SslProtocol { TlsV1_0 QT_DEPRECATED_VERSION_X_6_3("Use TlsV1_2OrLater instead."), @@ -61,6 +68,7 @@ namespace QSsl { UnknownProtocol = -1 }; + Q_ENUM_NS(SslProtocol) enum SslOption { SslOptionDisableEmptyFragments = 0x01, @@ -72,6 +80,7 @@ namespace QSsl { SslOptionDisableSessionPersistence = 0x40, SslOptionDisableServerCipherPreference = 0x80 }; + Q_ENUM_NS(SslOption) Q_DECLARE_FLAGS(SslOptions, SslOption) enum class AlertLevel { @@ -79,6 +88,7 @@ namespace QSsl { Fatal, Unknown }; + Q_ENUM_NS(AlertLevel) enum class AlertType { CloseNotify, @@ -116,6 +126,7 @@ namespace QSsl { NoApplicationProtocol = 120, UnknownAlertMessage = 255 }; + Q_ENUM_NS(AlertType) enum class ImplementedClass { @@ -127,6 +138,7 @@ namespace QSsl { Dtls, DtlsCookie }; + Q_ENUM_NS(ImplementedClass) enum class SupportedFeature { @@ -138,6 +150,7 @@ namespace QSsl { SessionTicket, Alerts }; + Q_ENUM_NS(SupportedFeature) } Q_DECLARE_OPERATORS_FOR_FLAGS(QSsl::SslOptions) diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index 39745427eb..9878c603b6 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -110,7 +110,7 @@ #endif #include <QtCore/qdir.h> -#include <QtCore/qdiriterator.h> +#include <QtCore/qdirlisting.h> #include <QtCore/qfile.h> QT_BEGIN_NAMESPACE @@ -186,7 +186,7 @@ QSslCertificate::QSslCertificate(const QByteArray &data, QSsl::EncodingFormat fo return; } - QList<QSslCertificate> certs = X509Reader(data, 1); + const QList<QSslCertificate> certs = X509Reader(data, 1); if (!certs.isEmpty()) d = certs.first().d; } @@ -624,7 +624,7 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path, QString sourcePath = QDir::fromNativeSeparators(path); // Find the path without the filename - QString pathPrefix = sourcePath.left(sourcePath.lastIndexOf(u'/')); + QStringView pathPrefix = QStringView(sourcePath).left(sourcePath.lastIndexOf(u'/')); // Check if the path contains any special chars int pos = -1; @@ -647,7 +647,7 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path, if (lastIndexOfSlash != -1) pathPrefix = pathPrefix.left(lastIndexOfSlash); else - pathPrefix.clear(); + pathPrefix = {}; } else { // Check if the path is a file. if (QFileInfo(sourcePath).isFile()) { @@ -664,10 +664,12 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path, // Special case - if the prefix ends up being nothing, use "." instead. int startIndex = 0; if (pathPrefix.isEmpty()) { - pathPrefix = "."_L1; + pathPrefix = u"."; startIndex = 2; } + const QString pathPrefixString = pathPrefix.toString(); + // The path can be a file or directory. QList<QSslCertificate> certs; @@ -678,9 +680,12 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path, QRegularExpression pattern(QRegularExpression::anchoredPattern(sourcePath)); #endif - QDirIterator it(pathPrefix, QDir::Files, QDirIterator::FollowSymlinks | QDirIterator::Subdirectories); - while (it.hasNext()) { - QString filePath = startIndex == 0 ? it.next() : it.next().mid(startIndex); + using F = QDirListing::IteratorFlag; + constexpr auto iterFlags = F::FollowSymlinks | F::Recursive; + for (const auto &dirEntry : QDirListing(pathPrefixString, QDir::Files, iterFlags)) { + QString filePath = dirEntry.filePath(); + if (startIndex > 0) + filePath.remove(0, startIndex); #if QT_CONFIG(regularexpression) if (!pattern.match(filePath).hasMatch()) @@ -878,7 +883,7 @@ static const char *const certificate_blacklist[] = { bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate) { for (int a = 0; certificate_blacklist[a] != nullptr; a++) { - QString blacklistedCommonName = QString::fromUtf8(certificate_blacklist[(a+1)]); + auto blacklistedCommonName = QAnyStringView(QUtf8StringView(certificate_blacklist[(a+1)])); if (certificate.serialNumber() == certificate_blacklist[a++] && (certificate.subjectInfo(QSslCertificate::CommonName).contains(blacklistedCommonName) || certificate.issuerInfo(QSslCertificate::CommonName).contains(blacklistedCommonName))) @@ -889,19 +894,18 @@ bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate) QByteArray QSslCertificatePrivate::subjectInfoToString(QSslCertificate::SubjectInfo info) { - QByteArray str; switch (info) { - case QSslCertificate::Organization: str = QByteArray("O"); break; - case QSslCertificate::CommonName: str = QByteArray("CN"); break; - case QSslCertificate::LocalityName: str = QByteArray("L"); break; - case QSslCertificate::OrganizationalUnitName: str = QByteArray("OU"); break; - case QSslCertificate::CountryName: str = QByteArray("C"); break; - case QSslCertificate::StateOrProvinceName: str = QByteArray("ST"); break; - case QSslCertificate::DistinguishedNameQualifier: str = QByteArray("dnQualifier"); break; - case QSslCertificate::SerialNumber: str = QByteArray("serialNumber"); break; - case QSslCertificate::EmailAddress: str = QByteArray("emailAddress"); break; + case QSslCertificate::Organization: return "O"_ba; + case QSslCertificate::CommonName: return "CN"_ba; + case QSslCertificate::LocalityName: return"L"_ba; + case QSslCertificate::OrganizationalUnitName: return "OU"_ba; + case QSslCertificate::CountryName: return "C"_ba; + case QSslCertificate::StateOrProvinceName: return "ST"_ba; + case QSslCertificate::DistinguishedNameQualifier: return "dnQualifier"_ba; + case QSslCertificate::SerialNumber: return "serialNumber"_ba; + case QSslCertificate::EmailAddress: return "emailAddress"_ba; } - return str; + return QByteArray(); } /*! @@ -918,13 +922,13 @@ QString QSslCertificate::issuerDisplayName() const QStringList names; names = issuerInfo(QSslCertificate::CommonName); if (!names.isEmpty()) - return names.first(); + return names.constFirst(); names = issuerInfo(QSslCertificate::Organization); if (!names.isEmpty()) - return names.first(); + return names.constFirst(); names = issuerInfo(QSslCertificate::OrganizationalUnitName); if (!names.isEmpty()) - return names.first(); + return names.constFirst(); return QString(); } @@ -943,20 +947,18 @@ QString QSslCertificate::subjectDisplayName() const QStringList names; names = subjectInfo(QSslCertificate::CommonName); if (!names.isEmpty()) - return names.first(); + return names.constFirst(); names = subjectInfo(QSslCertificate::Organization); if (!names.isEmpty()) - return names.first(); + return names.constFirst(); names = subjectInfo(QSslCertificate::OrganizationalUnitName); if (!names.isEmpty()) - return names.first(); + return names.constFirst(); return QString(); } /*! - \fn size_t qHash(const QSslCertificate &key, size_t seed) - Returns the hash value for the \a key, using \a seed to seed the calculation. \since 5.4 \relates QHash @@ -976,15 +978,15 @@ QDebug operator<<(QDebug debug, const QSslCertificate &certificate) QDebugStateSaver saver(debug); debug.resetFormat().nospace(); debug << "QSslCertificate(" - << certificate.version() - << ", " << certificate.serialNumber() - << ", " << certificate.digest().toBase64() - << ", " << certificate.issuerDisplayName() - << ", " << certificate.subjectDisplayName() - << ", " << certificate.subjectAlternativeNames() + << "Version=" << certificate.version() + << ", SerialNumber=" << certificate.serialNumber() + << ", Digest=" << certificate.digest().toBase64() + << ", Issuer=" << certificate.issuerDisplayName() + << ", Subject=" << certificate.subjectDisplayName() + << ", AlternativeSubjectNames=" << certificate.subjectAlternativeNames() #if QT_CONFIG(datestring) - << ", " << certificate.effectiveDate() - << ", " << certificate.expiryDate() + << ", EffectiveDate=" << certificate.effectiveDate() + << ", ExpiryDate=" << certificate.expiryDate() #endif << ')'; return debug; diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index 5807c8d2c7..cdf11b28b0 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -14,8 +14,8 @@ #include <QtCore/qbytearray.h> #include <QtCore/qcryptographichash.h> #include <QtCore/qdatetime.h> -#include <QtCore/qsharedpointer.h> #include <QtCore/qmap.h> +#include <QtCore/qshareddata.h> #include <QtNetwork/qssl.h> QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h index 02cf002460..ca59abae82 100644 --- a/src/network/ssl/qsslcertificate_p.h +++ b/src/network/ssl/qsslcertificate_p.h @@ -35,8 +35,8 @@ public: ~QSslCertificatePrivate(); QList<QSslCertificateExtension> extensions() const; - Q_NETWORK_PRIVATE_EXPORT static bool isBlacklisted(const QSslCertificate &certificate); - Q_NETWORK_PRIVATE_EXPORT static QByteArray subjectInfoToString(QSslCertificate::SubjectInfo info); + Q_NETWORK_EXPORT static bool isBlacklisted(const QSslCertificate &certificate); + Q_NETWORK_EXPORT static QByteArray subjectInfoToString(QSslCertificate::SubjectInfo info); QAtomicInt ref; std::unique_ptr<QTlsPrivate::X509Certificate> backend; diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp index 80377f3426..fd308d7037 100644 --- a/src/network/ssl/qsslconfiguration.cpp +++ b/src/network/ssl/qsslconfiguration.cpp @@ -105,6 +105,12 @@ const char QSslConfiguration::NextProtocolHttp1_1[] = "http/1.1"; */ /*! + \variable QSslConfiguration::ALPNProtocolHTTP2 + \brief The value used for negotiating HTTP 2 during the Application-Layer + Protocol Negotiation. +*/ + +/*! Constructs an empty SSL configuration. This configuration contains no valid settings and the state will be empty. isNull() will return true after this constructor is called. @@ -218,15 +224,15 @@ bool QSslConfiguration::isNull() const d->peerVerifyMode == QSslSocket::AutoVerifyPeer && d->peerVerifyDepth == 0 && d->allowRootCertOnDemandLoading == true && - d->caCertificates.count() == 0 && - d->ciphers.count() == 0 && + d->caCertificates.size() == 0 && + d->ciphers.size() == 0 && d->ellipticCurves.isEmpty() && d->ephemeralServerKey.isNull() && d->dhParams == QSslDiffieHellmanParameters::defaultParameters() && d->localCertificateChain.isEmpty() && d->privateKey.isNull() && d->peerCertificate.isNull() && - d->peerCertificateChain.count() == 0 && + d->peerCertificateChain.size() == 0 && d->backendConfig.isEmpty() && d->sslOptions == QSslConfigurationPrivate::defaultSslOptions && d->sslSession.isNull() && @@ -550,8 +556,6 @@ void QSslConfiguration::setPrivateKey(const QSslKey &key) ciphers. You can revert to using the entire set by calling setCiphers() with the list returned by supportedCiphers(). - \note This is not currently supported in the Schannel backend. - \sa setCiphers(), supportedCiphers() */ QList<QSslCipher> QSslConfiguration::ciphers() const @@ -567,8 +571,6 @@ QList<QSslCipher> QSslConfiguration::ciphers() const Restricting the cipher suite must be done before the handshake phase, where the session cipher is chosen. - \note This is not currently supported in the Schannel backend. - \sa ciphers(), supportedCiphers() */ void QSslConfiguration::setCiphers(const QList<QSslCipher> &ciphers) @@ -581,16 +583,14 @@ void QSslConfiguration::setCiphers(const QList<QSslCipher> &ciphers) Sets the cryptographic cipher suite for this configuration to \a ciphers, which is a colon-separated list of cipher suite names. The ciphers are listed - in order of preference, starting with the most preferred cipher. For example: - - \snippet code/src_network_ssl_qsslconfiguration.cpp 1 - + in order of preference, starting with the most preferred cipher. Each cipher name in \a ciphers must be the name of a cipher in the list returned by supportedCiphers(). Restricting the cipher suite must be done before the handshake phase, where the session cipher is chosen. - \note This is not currently supported in the Schannel backend. + \note With the Schannel backend the order of the ciphers is ignored and Schannel + picks the most secure one during the handshake. \sa ciphers() */ @@ -922,7 +922,11 @@ void QSslConfiguration::setPreSharedKeyIdentityHint(const QByteArray &hint) Retrieves the current set of Diffie-Hellman parameters. If no Diffie-Hellman parameters have been set, the QSslConfiguration object - defaults to using the 1024-bit MODP group from RFC 2409. + defaults to using the 2048-bit MODP group from RFC 3526. + + \note The default parameters may change in future Qt versions. + Please check the documentation of the \e{exact Qt version} that you + are using in order to know what defaults that version uses. */ QSslDiffieHellmanParameters QSslConfiguration::diffieHellmanParameters() const { @@ -936,7 +940,14 @@ QSslDiffieHellmanParameters QSslConfiguration::diffieHellmanParameters() const a server to \a dhparams. If no Diffie-Hellman parameters have been set, the QSslConfiguration object - defaults to using the 1024-bit MODP group from RFC 2409. + defaults to using the 2048-bit MODP group from RFC 3526. + + Since 6.7 you can provide an empty Diffie-Hellman parameter to use auto selection + (see SSL_CTX_set_dh_auto of openssl) if the tls backend supports it. + + \note The default parameters may change in future Qt versions. + Please check the documentation of the \e{exact Qt version} that you + are using in order to know what defaults that version uses. */ void QSslConfiguration::setDiffieHellmanParameters(const QSslDiffieHellmanParameters &dhparams) { @@ -1098,7 +1109,7 @@ void QSslConfiguration::setDefaultConfiguration(const QSslConfiguration &configu QSslConfigurationPrivate::setDefaultConfiguration(configuration); } -#if QT_CONFIG(dtls) || defined(Q_CLANG_QDOC) +#if QT_CONFIG(dtls) || defined(Q_QDOC) /*! This function returns true if DTLS cookie verification was enabled on a diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h index 85c287bb2f..dd2dd2a97c 100644 --- a/src/network/ssl/qsslconfiguration.h +++ b/src/network/ssl/qsslconfiguration.h @@ -125,7 +125,7 @@ public: static QSslConfiguration defaultConfiguration(); static void setDefaultConfiguration(const QSslConfiguration &configuration); -#if QT_CONFIG(dtls) || defined(Q_CLANG_QDOC) +#if QT_CONFIG(dtls) || defined(Q_QDOC) bool dtlsCookieVerificationEnabled() const; void setDtlsCookieVerificationEnabled(bool enable); diff --git a/src/network/ssl/qssldiffiehellmanparameters.cpp b/src/network/ssl/qssldiffiehellmanparameters.cpp index 04add93116..7da14f3536 100644 --- a/src/network/ssl/qssldiffiehellmanparameters.cpp +++ b/src/network/ssl/qssldiffiehellmanparameters.cpp @@ -33,17 +33,18 @@ QT_BEGIN_NAMESPACE -// The 1024-bit MODP group from RFC 2459 (Second Oakley Group) +// The 2048-bit MODP group from RFC 3526 Q_AUTOTEST_EXPORT const char *qssl_dhparams_default_base64 = - "MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR" - "Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL" - "/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC"; + "MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFKCHmO" + "NATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjftawv/XLb0Brft7jhr" + "+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXTmmkWP6j9JM9fg2VdI9yjrZYc" + "YvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhghfDKQXkYuNs474553LBgOhgObJ4Oi7Aei" + "j7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg=="; /*! Returns the default QSslDiffieHellmanParameters used by QSslSocket. - This is currently the 1024-bit MODP group from RFC 2459, also - known as the Second Oakley Group. + This is currently the 2048-bit MODP group from RFC 3526. */ QSslDiffieHellmanParameters QSslDiffieHellmanParameters::defaultParameters() { @@ -241,8 +242,7 @@ QString QSslDiffieHellmanParameters::errorString() const noexcept return QCoreApplication::translate("QSslDiffieHellmanParameter", "The given Diffie-Hellman parameters are deemed unsafe"); } - Q_UNREACHABLE(); - return QString(); + Q_UNREACHABLE_RETURN(QString()); } /*! diff --git a/src/network/ssl/qsslellipticcurve.cpp b/src/network/ssl/qsslellipticcurve.cpp index 959bf1de33..77aa66f3cc 100644 --- a/src/network/ssl/qsslellipticcurve.cpp +++ b/src/network/ssl/qsslellipticcurve.cpp @@ -160,7 +160,7 @@ bool QSslEllipticCurve::isTlsNamedCurve() const noexcept */ /*! - \fn size_t qHash(QSslEllipticCurve curve, size_t seed) + \fn size_t qHash(QSslEllipticCurve curve, size_t seed = 0) \since 5.5 \relates QHash diff --git a/src/network/ssl/qsslkey.h b/src/network/ssl/qsslkey.h index db14c89c98..decfc4b5a1 100644 --- a/src/network/ssl/qsslkey.h +++ b/src/network/ssl/qsslkey.h @@ -8,7 +8,7 @@ #include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qnamespace.h> #include <QtCore/qbytearray.h> -#include <QtCore/qsharedpointer.h> +#include <QtCore/qshareddata.h> #include <QtNetwork/qssl.h> QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.h b/src/network/ssl/qsslpresharedkeyauthenticator.h index 98cfad19ed..a3912406d3 100644 --- a/src/network/ssl/qsslpresharedkeyauthenticator.h +++ b/src/network/ssl/qsslpresharedkeyauthenticator.h @@ -16,6 +16,7 @@ QT_BEGIN_NAMESPACE class QSslPreSharedKeyAuthenticatorPrivate; class QSslPreSharedKeyAuthenticator { + Q_GADGET_EXPORT(Q_NETWORK_EXPORT) public: Q_NETWORK_EXPORT QSslPreSharedKeyAuthenticator(); Q_NETWORK_EXPORT ~QSslPreSharedKeyAuthenticator(); diff --git a/src/network/ssl/qsslserver.cpp b/src/network/ssl/qsslserver.cpp index 727d647784..40a6a6f526 100644 --- a/src/network/ssl/qsslserver.cpp +++ b/src/network/ssl/qsslserver.cpp @@ -16,7 +16,7 @@ Transport Layer Security (TLS). To configure the secure handshake settings, use the applicable setter - functions on a QSslConfiguration object, and then use it as a argument + functions on a QSslConfiguration object, and then use it as an argument to the setSslConfiguration() function. All following incoming connections handled will use these settings. @@ -32,7 +32,7 @@ nextPendingConnection() function to fetch the next incoming connection and take it out of the pending connection queue. The QSslSocket is a child of the QSslServer and will be deleted when the QSslServer is deleted. It is - still a good a good idea to destroy the object explicitly when you are done + still a good idea to destroy the object explicitly when you are done with it, to avoid wasting memory. \sa QTcpServer, QSslConfiguration, QSslSocket @@ -171,6 +171,13 @@ QSslConfiguration::setHandshakeMustInterruptOnError() */ +/*! + \fn void QSslServer::startedEncryptionHandshake(QSslSocket *socket) + + This signal is emitted when the client, connected to \a socket, + initiates the TLS handshake. +*/ + #include "qsslserver.h" #include "qsslserver_p.h" @@ -228,6 +235,42 @@ QSslConfiguration QSslServer::sslConfiguration() const } /*! + Sets the \a timeout to use for all incoming handshakes, in milliseconds. + + This is relevant in the scenario where a client, whether malicious or + accidental, connects to the server but makes no attempt at communicating or + initiating a handshake. QSslServer will then automatically end the + connection after \a timeout milliseconds have elapsed. + + By default the timeout is 5000 milliseconds (5 seconds). + + \note The underlying TLS framework may have their own timeout logic now or + in the future, this function does not affect that. + + \note The \a timeout passed to this function will only apply to \e{new} + connections. If a client is already connected it will use the timeout which + was set when it connected. + + \sa handshakeTimeout() +*/ +void QSslServer::setHandshakeTimeout(int timeout) +{ + Q_D(QSslServer); + d->handshakeTimeout = timeout; +} + +/*! + Returns the currently configured handshake timeout. + + \sa setHandshakeTimeout() +*/ +int QSslServer::handshakeTimeout() const +{ + const Q_D(QSslServer); + return d->handshakeTimeout; +} + +/*! Called when a new connection is established. Converts \a socket to a QSslSocket. @@ -241,47 +284,129 @@ void QSslServer::incomingConnection(qintptr socket) pSslSocket->setSslConfiguration(sslConfiguration()); if (Q_LIKELY(pSslSocket->setSocketDescriptor(socket))) { - connect(pSslSocket, &QSslSocket::peerVerifyError, + connect(pSslSocket, &QSslSocket::peerVerifyError, this, [this, pSslSocket](const QSslError &error) { Q_EMIT peerVerifyError(pSslSocket, error); }); - connect(pSslSocket, &QSslSocket::sslErrors, + connect(pSslSocket, &QSslSocket::sslErrors, this, [this, pSslSocket](const QList<QSslError> &errors) { Q_EMIT sslErrors(pSslSocket, errors); }); - connect(pSslSocket, &QAbstractSocket::errorOccurred, + connect(pSslSocket, &QAbstractSocket::errorOccurred, this, [this, pSslSocket](QAbstractSocket::SocketError error) { Q_EMIT errorOccurred(pSslSocket, error); if (!pSslSocket->isEncrypted()) pSslSocket->deleteLater(); }); - connect(pSslSocket, &QSslSocket::encrypted, [this, pSslSocket]() { - pSslSocket->disconnect(); + connect(pSslSocket, &QSslSocket::encrypted, this, [this, pSslSocket]() { + Q_D(QSslServer); + d->removeSocketData(quintptr(pSslSocket)); + pSslSocket->disconnect(this); addPendingConnection(pSslSocket); }); - connect(pSslSocket, &QSslSocket::preSharedKeyAuthenticationRequired, + connect(pSslSocket, &QSslSocket::preSharedKeyAuthenticationRequired, this, [this, pSslSocket](QSslPreSharedKeyAuthenticator *authenticator) { Q_EMIT preSharedKeyAuthenticationRequired(pSslSocket, authenticator); }); - connect(pSslSocket, &QSslSocket::alertSent, + connect(pSslSocket, &QSslSocket::alertSent, this, [this, pSslSocket](QSsl::AlertLevel level, QSsl::AlertType type, const QString &description) { Q_EMIT alertSent(pSslSocket, level, type, description); }); - connect(pSslSocket, &QSslSocket::alertReceived, + connect(pSslSocket, &QSslSocket::alertReceived, this, [this, pSslSocket](QSsl::AlertLevel level, QSsl::AlertType type, const QString &description) { Q_EMIT alertReceived(pSslSocket, level, type, description); }); - connect(pSslSocket, &QSslSocket::handshakeInterruptedOnError, + connect(pSslSocket, &QSslSocket::handshakeInterruptedOnError, this, [this, pSslSocket](const QSslError &error) { Q_EMIT handshakeInterruptedOnError(pSslSocket, error); }); - Q_EMIT startedEncryptionHandshake(pSslSocket); + d_func()->initializeHandshakeProcess(pSslSocket); + } +} + +void QSslServerPrivate::initializeHandshakeProcess(QSslSocket *socket) +{ + Q_Q(QSslServer); + QMetaObject::Connection readyRead = QObject::connect( + socket, &QSslSocket::readyRead, q, [this]() { checkClientHelloAndContinue(); }); + + QMetaObject::Connection destroyed = + QObject::connect(socket, &QSslSocket::destroyed, q, [this](QObject *obj) { + // This cast is not safe to use since the socket is inside the + // QObject dtor, but we only use the pointer value! + removeSocketData(quintptr(obj)); + }); + auto it = socketData.emplace(quintptr(socket), readyRead, destroyed, std::make_shared<QTimer>()); + it->timeoutTimer->setSingleShot(true); + it->timeoutTimer->callOnTimeout(q, [this, socket]() { handleHandshakeTimedOut(socket); }); + it->timeoutTimer->setInterval(handshakeTimeout); + it->timeoutTimer->start(); +} + +// This function may be called while in the socket's QObject dtor, __never__ use +// the socket for anything other than a lookup! +void QSslServerPrivate::removeSocketData(quintptr socket) +{ + auto it = socketData.find(socket); + if (it != socketData.end()) { + it->disconnectSignals(); + socketData.erase(it); + } +} + +int QSslServerPrivate::totalPendingConnections() const +{ + // max pending connections is int, so this cannot exceed that + return QTcpServerPrivate::totalPendingConnections() + int(socketData.size()); +} + +void QSslServerPrivate::checkClientHelloAndContinue() +{ + Q_Q(QSslServer); + QSslSocket *socket = qobject_cast<QSslSocket *>(q->sender()); + if (Q_UNLIKELY(!socket) || socket->bytesAvailable() <= 0) + return; + + char byte = '\0'; + if (socket->peek(&byte, 1) != 1) { + socket->deleteLater(); + return; + } + + auto it = socketData.find(quintptr(socket)); + const bool foundData = it != socketData.end(); + if (foundData && it->readyReadConnection) + QObject::disconnect(std::exchange(it->readyReadConnection, {})); - pSslSocket->startServerEncryption(); + constexpr char CLIENT_HELLO = 0x16; + if (byte != CLIENT_HELLO) { + socket->disconnectFromHost(); + socket->deleteLater(); + return; } + + // Be nice and restart the timeout timer since some progress was made + if (foundData) + it->timeoutTimer->start(); + + socket->startServerEncryption(); + Q_EMIT q->startedEncryptionHandshake(socket); +} + +void QSslServerPrivate::handleHandshakeTimedOut(QSslSocket *socket) +{ + Q_Q(QSslServer); + removeSocketData(quintptr(socket)); + socket->disconnectFromHost(); + Q_EMIT q->errorOccurred(socket, QAbstractSocket::SocketTimeoutError); + socket->deleteLater(); + if (!socketEngine->isReadNotificationEnabled() && totalPendingConnections() < maxConnections) + q->resumeAccepting(); } QT_END_NAMESPACE + +#include "moc_qsslserver.cpp" diff --git a/src/network/ssl/qsslserver.h b/src/network/ssl/qsslserver.h index d2f3abc456..aaa0f43c35 100644 --- a/src/network/ssl/qsslserver.h +++ b/src/network/ssl/qsslserver.h @@ -33,6 +33,9 @@ public: void setSslConfiguration(const QSslConfiguration &sslConfiguration); QSslConfiguration sslConfiguration() const; + void setHandshakeTimeout(int timeout); + int handshakeTimeout() const; + Q_SIGNALS: void sslErrors(QSslSocket *socket, const QList<QSslError> &errors); void peerVerifyError(QSslSocket *socket, const QSslError &error); diff --git a/src/network/ssl/qsslserver_p.h b/src/network/ssl/qsslserver_p.h index b4b6490ed4..1b90d35d48 100644 --- a/src/network/ssl/qsslserver_p.h +++ b/src/network/ssl/qsslserver_p.h @@ -16,19 +16,53 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> + +#include <QtCore/qhash.h> +#include <QtCore/qtimer.h> + #include <QtNetwork/QSslConfiguration> #include <QtNetwork/private/qtcpserver_p.h> +#include <utility> QT_BEGIN_NAMESPACE class Q_NETWORK_EXPORT QSslServerPrivate : public QTcpServerPrivate { + static constexpr int DefaultHandshakeTimeout = 5'000; // 5 seconds public: Q_DECLARE_PUBLIC(QSslServer) QSslServerPrivate(); + void checkClientHelloAndContinue(); + void initializeHandshakeProcess(QSslSocket *socket); + void removeSocketData(quintptr socket); + void handleHandshakeTimedOut(QSslSocket *socket); + int totalPendingConnections() const override; + + struct SocketData { + QMetaObject::Connection readyReadConnection; + QMetaObject::Connection destroyedConnection; + std::shared_ptr<QTimer> timeoutTimer; // shared_ptr because QHash demands copying + + SocketData(QMetaObject::Connection readyRead, QMetaObject::Connection destroyed, + std::shared_ptr<QTimer> &&timer) + : readyReadConnection(readyRead), + destroyedConnection(destroyed), + timeoutTimer(std::move(timer)) + { + } + + void disconnectSignals() + { + QObject::disconnect(std::exchange(readyReadConnection, {})); + QObject::disconnect(std::exchange(destroyedConnection, {})); + } + }; + QHash<quintptr, SocketData> socketData; QSslConfiguration sslConfiguration; + int handshakeTimeout = DefaultHandshakeTimeout; }; diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index cd76517c25..395394d432 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -97,8 +97,7 @@ \list \li The socket's cryptographic cipher suite can be customized before - the handshake phase with QSslConfiguration::setCiphers() - and QSslConfiguration::setDefaultCiphers(). + the handshake phase with QSslConfiguration::setCiphers(). \li The socket's local certificate and private key can be customized before the handshake phase with setLocalCertificate() and setPrivateKey(). @@ -365,6 +364,12 @@ QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; +#ifdef Q_OS_VXWORKS +constexpr auto isVxworks = true; +#else +constexpr auto isVxworks = false; +#endif + class QSslSocketGlobalData { public: @@ -1539,7 +1544,12 @@ QList<QString> QSslSocket::availableBackends() from the list of available backends. \note When selecting a default backend implicitly, QSslSocket prefers - the OpenSSL backend if available. + the OpenSSL backend if available. If it's not available, the Schannel backend + is implicitly selected on Windows, and Secure Transport on Darwin platforms. + Failing these, if a custom TLS backend is found, it is used. + If no other backend is found, the "certificate only" backend is selected. + For more information about TLS plugins, please see + \l {Enabling and Disabling SSL Support when Building Qt from Source}. \sa setActiveBackend(), availableBackends() */ @@ -1973,6 +1983,10 @@ QSslSocketPrivate::QSslSocketPrivate() , flushTriggered(false) { QSslConfigurationPrivate::deepCopyDefaultConfiguration(&configuration); + // If the global configuration doesn't allow root certificates to be loaded + // on demand then we have to disable it for this socket as well. + if (!configuration.allowRootCertOnDemandLoading) + allowRootCertOnDemandLoading = false; const auto *tlsBackend = tlsBackendInUse(); if (!tlsBackend) { @@ -2281,6 +2295,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri ptr->sessionProtocol = global->sessionProtocol; ptr->ciphers = global->ciphers; ptr->caCertificates = global->caCertificates; + ptr->allowRootCertOnDemandLoading = global->allowRootCertOnDemandLoading; ptr->protocol = global->protocol; ptr->peerVerifyMode = global->peerVerifyMode; ptr->peerVerifyDepth = global->peerVerifyDepth; @@ -2661,7 +2676,7 @@ bool QSslSocketPrivate::verifyErrorsHaveBeenIgnored() // was called) const auto &sslErrors = backend->tlsErrors(); doEmitSslError = false; - for (int a = 0; a < sslErrors.count(); a++) { + for (int a = 0; a < sslErrors.size(); a++) { if (!ignoreErrorsList.contains(sslErrors.at(a))) { doEmitSslError = true; break; @@ -2799,11 +2814,11 @@ QByteArray QSslSocketPrivate::peek(qint64 maxSize) QByteArray ret; ret.reserve(maxSize); ret.resize(buffer.peek(ret.data(), maxSize, transactionPos)); - if (ret.length() == maxSize) + if (ret.size() == maxSize) return ret; //peek at data in the plain socket if (plainSocket) - return ret + plainSocket->peek(maxSize - ret.length()); + return ret + plainSocket->peek(maxSize - ret.size()); return QByteArray(); } else { @@ -2955,7 +2970,13 @@ QList<QByteArray> QSslSocketPrivate::unixRootCertDirectories() ba("/opt/openssl/certs/"), // HP-UX ba("/etc/ssl/"), // OpenBSD }; - return QList<QByteArray>::fromReadOnlyData(dirs); + QList<QByteArray> result = QList<QByteArray>::fromReadOnlyData(dirs); + if constexpr (isVxworks) { + static QByteArray vxworksCertsDir = qgetenv("VXWORKS_CERTS_DIR"); + if (!vxworksCertsDir.isEmpty()) + result.push_back(vxworksCertsDir); + } + return result; } /*! @@ -3031,7 +3052,7 @@ bool QSslSocketPrivate::isMatchingHostname(const QString &cn, const QString &hos qsizetype secondCnDot = cn.indexOf(u'.', firstCnDot+1); // Check at least 3 components - if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.length())) + if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.size())) return false; // Check * is last character of 1st component (ie. there's a following .) @@ -3086,10 +3107,11 @@ QTlsBackend *QSslSocketPrivate::tlsBackendInUse() tlsBackend = QTlsBackend::findBackend(activeBackendName); if (tlsBackend) { - QObject::connect(tlsBackend, &QObject::destroyed, [] { + QObject::connect(tlsBackend, &QObject::destroyed, tlsBackend, [] { const QMutexLocker locker(&backendMutex); tlsBackend = nullptr; - }); + }, + Qt::DirectConnection); } return tlsBackend; } diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h index 3174a68953..3ed1bc45cc 100644 --- a/src/network/ssl/qsslsocket.h +++ b/src/network/ssl/qsslsocket.h @@ -35,6 +35,7 @@ public: SslClientMode, SslServerMode }; + Q_ENUM(SslMode) enum PeerVerifyMode { VerifyNone, @@ -42,6 +43,7 @@ public: VerifyPeer, AutoVerifyPeer }; + Q_ENUM(PeerVerifyMode) explicit QSslSocket(QObject *parent = nullptr); ~QSslSocket(); diff --git a/src/network/ssl/qtlsbackend.cpp b/src/network/ssl/qtlsbackend.cpp index bc5b492d0f..761ab33fbe 100644 --- a/src/network/ssl/qtlsbackend.cpp +++ b/src/network/ssl/qtlsbackend.cpp @@ -27,7 +27,7 @@ QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; -Q_APPLICATION_STATIC(QFactoryLoader, loader, QTlsBackend_iid, +Q_APPLICATION_STATIC(QFactoryLoader, qtlsbLoader, QTlsBackend_iid, QStringLiteral("/tls")) namespace { @@ -54,7 +54,7 @@ public: bool tryPopulateCollection() { - if (!loader()) + if (!qtlsbLoader()) return false; Q_CONSTINIT static QBasicMutex mutex; @@ -63,10 +63,10 @@ public: return true; #if QT_CONFIG(library) - loader->update(); + qtlsbLoader->update(); #endif int index = 0; - while (loader->instance(index)) + while (qtlsbLoader->instance(index)) ++index; return true; @@ -889,20 +889,28 @@ QSslCipher QTlsBackend::createCiphersuite(const QString &suiteName, QSsl::SslPro /*! \internal - Auxiliary function. Creates a new QSslCipher from \a name (which is an implementation-specific - string), \a protocol and \a protocolString, e.g.: + Auxiliary function. Creates a new QSslCipher from \a name, \a keyExchangeMethod, \a encryptionMethod, + \a authenticationMethod, \a bits, \a protocol version and \a protocolString. + For example: \code - createCipher(QStringLiteral("schannel"), QSsl::TlsV1_2, "TLSv1.2"_L1); + createCiphersuite("ECDHE-RSA-AES256-GCM-SHA256"_L1, "ECDH"_L1, "AES"_L1, "RSA"_L1, 256, + QSsl::TlsV1_2, "TLSv1.2"_L1); \endcode */ -QSslCipher QTlsBackend::createCipher(const QString &name, QSsl::SslProtocol protocol, - const QString &protocolString) +QSslCipher QTlsBackend::createCiphersuite(const QString &name, const QString &keyExchangeMethod, + const QString &encryptionMethod, + const QString &authenticationMethod, + int bits, QSsl::SslProtocol protocol, + const QString &protocolString) { - // Note the name 'createCipher' (not 'ciphersuite'): we don't provide - // information about Kx, Au, bits/supported etc. QSslCipher cipher; cipher.d->isNull = false; cipher.d->name = name; + cipher.d->bits = bits; + cipher.d->supportedBits = bits; + cipher.d->keyExchangeMethod = keyExchangeMethod; + cipher.d->encryptionMethod = encryptionMethod; + cipher.d->authenticationMethod = authenticationMethod; cipher.d->protocol = protocol; cipher.d->protocolString = protocolString; return cipher; @@ -1382,8 +1390,7 @@ QByteArray TlsKey::pemHeader() const else if (algorithm() == QSsl::Dh) return QByteArrayLiteral("-----BEGIN PRIVATE KEY-----"); - Q_UNREACHABLE(); - return {}; + Q_UNREACHABLE_RETURN({}); } /*! @@ -1404,8 +1411,7 @@ QByteArray TlsKey::pemFooter() const else if (algorithm() == QSsl::Dh) return QByteArrayLiteral("-----END PRIVATE KEY-----"); - Q_UNREACHABLE(); - return {}; + Q_UNREACHABLE_RETURN({}); } /*! diff --git a/src/network/ssl/qtlsbackend_p.h b/src/network/ssl/qtlsbackend_p.h index c69e641854..090531014b 100644 --- a/src/network/ssl/qtlsbackend_p.h +++ b/src/network/ssl/qtlsbackend_p.h @@ -31,7 +31,6 @@ #include <QtNetwork/qssl.h> #include <QtCore/qloggingcategory.h> -#include <QtCore/qsharedpointer.h> #include <QtCore/qnamespace.h> #include <QtCore/qobject.h> #include <QtCore/qglobal.h> @@ -58,7 +57,7 @@ class QSslKey; namespace QTlsPrivate { -class Q_NETWORK_PRIVATE_EXPORT TlsKey { +class Q_NETWORK_EXPORT TlsKey { public: virtual ~TlsKey(); @@ -95,7 +94,7 @@ public: QByteArray pemFooter() const; }; -class Q_NETWORK_PRIVATE_EXPORT X509Certificate +class Q_NETWORK_EXPORT X509Certificate { public: virtual ~X509Certificate(); @@ -152,7 +151,7 @@ using X509Pkcs12ReaderPtr = bool (*)(QIODevice *device, QSslKey *key, QSslCertif #if QT_CONFIG(ssl) // TLS over TCP. Handshake, encryption/decryption. -class Q_NETWORK_PRIVATE_EXPORT TlsCryptograph : public QObject +class Q_NETWORK_EXPORT TlsCryptograph : public QObject { public: virtual ~TlsCryptograph(); @@ -188,7 +187,7 @@ class TlsCryptograph; #if QT_CONFIG(dtls) -class Q_NETWORK_PRIVATE_EXPORT DtlsBase +class Q_NETWORK_EXPORT DtlsBase { public: virtual ~DtlsBase(); @@ -218,7 +217,7 @@ public: }; // TLS over UDP. Handshake, encryption/decryption. -class Q_NETWORK_PRIVATE_EXPORT DtlsCryptograph : virtual public DtlsBase +class Q_NETWORK_EXPORT DtlsCryptograph : virtual public DtlsBase { public: @@ -347,8 +346,11 @@ public: static QSslCipher createCiphersuite(const QString &description, int bits, int supportedBits); static QSslCipher createCiphersuite(const QString &suiteName, QSsl::SslProtocol protocol, const QString &protocolString); - static QSslCipher createCipher(const QString &name, QSsl::SslProtocol protocol, - const QString &protocolString); + static QSslCipher createCiphersuite(const QString &name, const QString &keyExchangeMethod, + const QString &encryptionMethod, + const QString &authenticationMethod, + int bits, QSsl::SslProtocol protocol, + const QString &protocolString); // Those statics are implemented using QSslSocketPrivate (which is not exported, // unlike QTlsBackend). |