summaryrefslogtreecommitdiffstats
path: root/src/network/ssl/qsslcertificate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/ssl/qsslcertificate.cpp')
-rw-r--r--src/network/ssl/qsslcertificate.cpp431
1 files changed, 319 insertions, 112 deletions
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index c63ef5d205..9878c603b6 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
@@ -121,8 +85,7 @@
\value Wildcard This provides a simple pattern matching syntax
similar to that used by shells (command interpreters) for "file
- globbing". See \l {QRegularExpression#Wildcard matching}
- {QRegularExpression Wildcard Matching}.
+ globbing". See \l {QRegularExpression::fromWildcard()}.
\value FixedString The pattern is a fixed string. This is
equivalent to using the RegularExpression pattern on a string in
@@ -131,31 +94,46 @@
*/
#include <QtNetwork/qtnetworkglobal.h>
-#ifndef QT_NO_OPENSSL
-#include "qsslsocket_openssl_symbols_p.h"
-#endif
-#ifdef QT_SECURETRANSPORT
-#include "qsslsocket_mac_p.h"
-#endif
-#if QT_CONFIG(schannel)
-#include "qsslsocket_schannel_p.h"
-#endif
+
#if QT_CONFIG(regularexpression)
#include "qregularexpression.h"
#endif
-#include "qssl_p.h"
-#include "qsslcertificate.h"
+
+#include "qsslcertificateextension_p.h"
#include "qsslcertificate_p.h"
+#include "qsslcertificate.h"
+#include "qssl_p.h"
+
#ifndef QT_NO_SSL
+#include "qsslsocket_p.h"
#include "qsslkey_p.h"
#endif
#include <QtCore/qdir.h>
-#include <QtCore/qdiriterator.h>
+#include <QtCore/qdirlisting.h>
#include <QtCore/qfile.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+QT_IMPL_METATYPE_EXTERN(QSslCertificate)
+
+QSslCertificatePrivate::QSslCertificatePrivate()
+{
+#ifndef QT_NO_SSL
+ QSslSocketPrivate::ensureInitialized();
+#endif
+
+ const QTlsBackend *tlsBackend = QTlsBackend::activeOrAnyBackend();
+ if (tlsBackend)
+ backend.reset(tlsBackend->createCertificate());
+ else
+ qCWarning(lcSsl, "No TLS backend is available");
+}
+
+QSslCertificatePrivate::~QSslCertificatePrivate() = default;
+
/*!
Constructs a QSslCertificate by reading \a format encoded data
from \a device and using the first certificate found. You can
@@ -165,13 +143,25 @@ QT_BEGIN_NAMESPACE
QSslCertificate::QSslCertificate(QIODevice *device, QSsl::EncodingFormat format)
: d(new QSslCertificatePrivate)
{
-#ifndef QT_NO_OPENSSL
- QSslSocketPrivate::ensureInitialized();
- if (device && QSslSocket::supportsSsl())
-#else
- if (device)
-#endif
- d->init(device->readAll(), format);
+ if (device) {
+ const auto data = device->readAll();
+ if (data.isEmpty())
+ return;
+
+ const auto *tlsBackend = QTlsBackend::activeOrAnyBackend();
+ if (!tlsBackend)
+ return;
+
+ auto *X509Reader = format == QSsl::Pem ? tlsBackend->X509PemReader() : tlsBackend->X509DerReader();
+ if (!X509Reader) {
+ qCWarning(lcSsl, "Current TLS plugin does not support reading from PEM/DER");
+ return;
+ }
+
+ QList<QSslCertificate> certs = X509Reader(data, 1);
+ if (!certs.isEmpty())
+ d = certs.first().d;
+ }
}
/*!
@@ -183,11 +173,22 @@ QSslCertificate::QSslCertificate(QIODevice *device, QSsl::EncodingFormat format)
QSslCertificate::QSslCertificate(const QByteArray &data, QSsl::EncodingFormat format)
: d(new QSslCertificatePrivate)
{
-#ifndef QT_NO_OPENSSL
- QSslSocketPrivate::ensureInitialized();
- if (QSslSocket::supportsSsl())
-#endif
- d->init(data, format);
+ if (data.isEmpty())
+ return;
+
+ const auto *tlsBackend = QTlsBackend::activeOrAnyBackend();
+ if (!tlsBackend)
+ return;
+
+ auto *X509Reader = format == QSsl::Pem ? tlsBackend->X509PemReader() : tlsBackend->X509DerReader();
+ if (!X509Reader) {
+ qCWarning(lcSsl, "Current TLS plugin does not support reading from PEM/DER");
+ return;
+ }
+
+ const QList<QSslCertificate> certs = X509Reader(data, 1);
+ if (!certs.isEmpty())
+ d = certs.first().d;
}
/*!
@@ -229,6 +230,20 @@ QSslCertificate &QSslCertificate::operator=(const QSslCertificate &other)
returns \c false.
*/
+bool QSslCertificate::operator==(const QSslCertificate &other) const
+{
+ if (d == other.d)
+ return true;
+
+ if (isNull() && other.isNull())
+ return true;
+
+ if (d->backend.get() && other.d->backend.get())
+ return d->backend->isEqual(*other.d->backend.get());
+
+ return false;
+}
+
/*!
\fn bool QSslCertificate::operator!=(const QSslCertificate &other) const
@@ -246,6 +261,13 @@ QSslCertificate &QSslCertificate::operator=(const QSslCertificate &other)
\sa clear()
*/
+bool QSslCertificate::isNull() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->isNull();
+
+ return true;
+}
/*!
Returns \c true if this certificate is blacklisted; otherwise
@@ -268,6 +290,13 @@ bool QSslCertificate::isBlacklisted() const
A certificate is considered self-signed its issuer and subject
are identical.
*/
+bool QSslCertificate::isSelfSigned() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->isSelfSigned();
+
+ return false;
+}
/*!
Clears the contents of this certificate, making it a null
@@ -286,12 +315,26 @@ void QSslCertificate::clear()
\fn QByteArray QSslCertificate::version() const
Returns the certificate's version string.
*/
+QByteArray QSslCertificate::version() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->version();
+
+ return {};
+}
/*!
\fn QByteArray QSslCertificate::serialNumber() const
Returns the certificate's serial number string in hexadecimal format.
*/
+QByteArray QSslCertificate::serialNumber() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->serialNumber();
+
+ return {};
+}
/*!
Returns a cryptographic digest of this certificate. By default,
@@ -313,6 +356,13 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
\sa subjectInfo()
*/
+QStringList QSslCertificate::issuerInfo(SubjectInfo info) const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->issuerInfo(info);
+
+ return {};
+}
/*!
\fn QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const
@@ -323,6 +373,13 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
\sa subjectInfo()
*/
+QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->issuerInfo(attribute);
+
+ return {};
+}
/*!
\fn QString QSslCertificate::subjectInfo(SubjectInfo subject) const
@@ -333,6 +390,13 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
\sa issuerInfo()
*/
+QStringList QSslCertificate::subjectInfo(SubjectInfo info) const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->subjectInfo(info);
+
+ return {};
+}
/*!
\fn QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const
@@ -343,6 +407,13 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
\sa issuerInfo()
*/
+QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->subjectInfo(attribute);
+
+ return {};
+}
/*!
\fn QList<QByteArray> QSslCertificate::subjectInfoAttributes() const
@@ -356,6 +427,13 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
\sa subjectInfo()
*/
+QList<QByteArray> QSslCertificate::subjectInfoAttributes() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->subjectInfoAttributes();
+
+ return {};
+}
/*!
\fn QList<QByteArray> QSslCertificate::issuerInfoAttributes() const
@@ -369,6 +447,13 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
\sa subjectInfo()
*/
+QList<QByteArray> QSslCertificate::issuerInfoAttributes() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->issuerInfoAttributes();
+
+ return {};
+}
/*!
\fn QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlternativeNames() const
@@ -385,6 +470,13 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
\sa subjectInfo()
*/
+QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlternativeNames() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->subjectAlternativeNames();
+
+ return {};
+}
/*!
\fn QDateTime QSslCertificate::effectiveDate() const
@@ -394,6 +486,13 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
\sa expiryDate()
*/
+QDateTime QSslCertificate::effectiveDate() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->effectiveDate();
+
+ return {};
+}
/*!
\fn QDateTime QSslCertificate::expiryDate() const
@@ -403,6 +502,13 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
\sa effectiveDate()
*/
+QDateTime QSslCertificate::expiryDate() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->expiryDate();
+
+ return {};
+}
/*!
\fn Qt::HANDLE QSslCertificate::handle() const
@@ -416,11 +522,29 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
non-portable, and its return value may vary from platform to
platform or change from minor release to minor release.
*/
+Qt::HANDLE QSslCertificate::handle() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->handle();
+
+ return {};
+}
+#ifndef QT_NO_SSL
/*!
\fn QSslKey QSslCertificate::publicKey() const
Returns the certificate subject's public key.
*/
+QSslKey QSslCertificate::publicKey() const
+{
+ QSslKey key;
+ if (const auto *backend = d->backend.get())
+ QTlsBackend::resetBackend(key, backend->publicKey());
+
+ return key;
+}
+#endif // QT_NO_SSL
+
/*!
\fn QList<QSslCertificateExtension> QSslCertificate::extensions() const
@@ -428,6 +552,10 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
Returns a list containing the X509 extensions of this certificate.
\since 5.0
*/
+QList<QSslCertificateExtension> QSslCertificate::extensions() const
+{
+ return d->extensions();
+}
/*!
\fn QByteArray QSslCertificate::toPem() const
@@ -435,6 +563,13 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
Returns this certificate converted to a PEM (Base64) encoded
representation.
*/
+QByteArray QSslCertificate::toPem() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->toPem();
+
+ return {};
+}
/*!
\fn QByteArray QSslCertificate::toDer() const
@@ -442,6 +577,13 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
Returns this certificate converted to a DER (binary) encoded
representation.
*/
+QByteArray QSslCertificate::toDer() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->toDer();
+
+ return {};
+}
/*!
\fn QString QSslCertificate::toText() const
@@ -451,6 +593,13 @@ QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) cons
\since 5.0
*/
+QString QSslCertificate::toText() const
+{
+ if (const auto *backend = d->backend.get())
+ return backend->toText();
+
+ return {};
+}
/*!
\since 5.15
@@ -475,16 +624,16 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
QString sourcePath = QDir::fromNativeSeparators(path);
// Find the path without the filename
- QString pathPrefix = sourcePath.left(sourcePath.lastIndexOf(QLatin1Char('/')));
+ QStringView pathPrefix = QStringView(sourcePath).left(sourcePath.lastIndexOf(u'/'));
// Check if the path contains any special chars
int pos = -1;
#if QT_CONFIG(regularexpression)
if (syntax == PatternSyntax::Wildcard)
- pos = pathPrefix.indexOf(QRegularExpression(QLatin1String("[*?[]")));
+ pos = pathPrefix.indexOf(QRegularExpression("[*?[]"_L1));
else if (syntax == PatternSyntax::RegularExpression)
- pos = sourcePath.indexOf(QRegularExpression(QLatin1String("[\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\}\\|]")));
+ pos = sourcePath.indexOf(QRegularExpression("[\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\}\\|]"_L1));
#else
if (syntax == PatternSyntax::Wildcard || syntax == PatternSyntax::RegExp)
qWarning("Regular expression support is disabled in this build. Only fixed string can be searched");
@@ -494,11 +643,11 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
if (pos != -1) {
// there was a special char in the path so cut of the part containing that char.
pathPrefix = pathPrefix.left(pos);
- const int lastIndexOfSlash = pathPrefix.lastIndexOf(QLatin1Char('/'));
+ const qsizetype lastIndexOfSlash = pathPrefix.lastIndexOf(u'/');
if (lastIndexOfSlash != -1)
pathPrefix = pathPrefix.left(lastIndexOfSlash);
else
- pathPrefix.clear();
+ pathPrefix = {};
} else {
// Check if the path is a file.
if (QFileInfo(sourcePath).isFile()) {
@@ -515,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 = QLatin1String(".");
+ pathPrefix = u".";
startIndex = 2;
}
+ const QString pathPrefixString = pathPrefix.toString();
+
// The path can be a file or directory.
QList<QSslCertificate> certs;
@@ -529,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())
@@ -576,13 +730,22 @@ QList<QSslCertificate> QSslCertificate::fromDevice(QIODevice *device, QSsl::Enco
*/
QList<QSslCertificate> QSslCertificate::fromData(const QByteArray &data, QSsl::EncodingFormat format)
{
- return (format == QSsl::Pem)
- ? QSslCertificatePrivate::certificatesFromPem(data)
- : QSslCertificatePrivate::certificatesFromDer(data);
+ const auto *tlsBackend = QTlsBackend::activeOrAnyBackend();
+ if (!tlsBackend) {
+ qCWarning(lcSsl, "No TLS backend is available");
+ return {};
+ }
+
+ auto reader = format == QSsl::Pem ? tlsBackend->X509PemReader() : tlsBackend->X509DerReader();
+ if (!reader) {
+ qCWarning(lcSsl, "The available TLS backend does not support reading PEM/DER");
+ return {};
+ }
+
+ return reader(data, -1);
}
#ifndef QT_NO_SSL
-
/*!
Verifies a certificate chain. The chain to be verified is passed in the
\a certificateChain parameter. The first certificate in the list should
@@ -597,13 +760,19 @@ QList<QSslCertificate> QSslCertificate::fromData(const QByteArray &data, QSsl::E
\since 5.0
*/
-#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
QList<QSslError> QSslCertificate::verify(const QList<QSslCertificate> &certificateChain, const QString &hostName)
-#else
-QList<QSslError> QSslCertificate::verify(QList<QSslCertificate> certificateChain, const QString &hostName)
-#endif
{
- return QSslSocketBackendPrivate::verify(certificateChain, hostName);
+ const auto *tlsBackend = QTlsBackend::activeOrAnyBackend();
+ if (!tlsBackend) {
+ qCWarning(lcSsl, "No TLS backend is available");
+ return {};
+ }
+ auto verifyPtr = tlsBackend->X509Verifier();
+ if (!verifyPtr) {
+ qCWarning(lcSsl, "Available TLS backend does not support manual certificate verification");
+ return {};
+ }
+ return verifyPtr(certificateChain, hostName);
}
/*!
@@ -623,10 +792,43 @@ bool QSslCertificate::importPkcs12(QIODevice *device,
QList<QSslCertificate> *caCertificates,
const QByteArray &passPhrase)
{
- return QSslSocketBackendPrivate::importPkcs12(device, key, certificate, caCertificates, passPhrase);
+ if (!device || !key || !certificate)
+ return false;
+
+ const auto *tlsBackend = QTlsBackend::activeOrAnyBackend();
+ if (!tlsBackend) {
+ qCWarning(lcSsl, "No TLS backend is available");
+ return false;
+ }
+
+ if (auto reader = tlsBackend->X509Pkcs12Reader())
+ return reader(device, key, certificate, caCertificates, passPhrase);
+
+ qCWarning(lcSsl, "Available TLS backend does not support PKCS12");
+
+ return false;
}
+#endif // QT_NO_SSL
-#endif
+QList<QSslCertificateExtension> QSslCertificatePrivate::extensions() const
+{
+ QList<QSslCertificateExtension> result;
+
+ if (backend.get()) {
+ auto nExt = backend->numberOfExtensions();
+ for (decltype (nExt) i = 0; i < nExt; ++i) {
+ QSslCertificateExtension ext;
+ ext.d->oid = backend->oidForExtension(i);
+ ext.d->name = backend->nameForExtension(i);
+ ext.d->value = backend->valueForExtension(i);
+ ext.d->critical = backend->isExtensionCritical(i);
+ ext.d->supported = backend->isExtensionSupported(i);
+ result << ext;
+ }
+ }
+
+ return result;
+}
// These certificates are known to be fraudulent and were created during the comodo
// compromise. See http://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html
@@ -681,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)))
@@ -692,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();
}
/*!
@@ -721,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();
}
@@ -746,24 +947,30 @@ 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
*/
+size_t qHash(const QSslCertificate &key, size_t seed) noexcept
+{
+ if (const auto *backend = key.d->backend.get())
+ return backend->hash(seed);
+
+ return seed;
+
+}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QSslCertificate &certificate)
@@ -771,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;