| /**************************************************************************** |
| ** |
| ** 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$ |
| ** |
| ****************************************************************************/ |
| |
| |
| /*! |
| \class QSslCertificate |
| \brief The QSslCertificate class provides a convenient API for an X509 certificate. |
| \since 4.3 |
| |
| \reentrant |
| \ingroup network |
| \ingroup ssl |
| \ingroup shared |
| \inmodule QtNetwork |
| |
| QSslCertificate stores an X509 certificate, and is commonly used |
| to verify the identity and store information about the local host, |
| a remotely connected peer, or a trusted third party Certificate |
| Authority. |
| |
| There are many ways to construct a QSslCertificate. The most |
| common way is to call QSslSocket::peerCertificate(), which returns |
| a QSslCertificate object, or QSslSocket::peerCertificateChain(), |
| which returns a list of them. You can also load certificates from |
| a DER (binary) or PEM (Base64) encoded bundle, typically stored as |
| one or more local files, or in a Qt Resource. |
| |
| You can call isNull() to check if your certificate is null. By default, |
| QSslCertificate constructs a null certificate. A null certificate is |
| invalid, but an invalid certificate is not necessarily null. If you want |
| to reset all contents in a certificate, call clear(). |
| |
| After loading a certificate, you can find information about the |
| certificate, its subject, and its issuer, by calling one of the |
| many accessor functions, including version(), serialNumber(), |
| issuerInfo() and subjectInfo(). You can call effectiveDate() and |
| expiryDate() to check when the certificate starts being |
| effective and when it expires. |
| The publicKey() function returns the certificate |
| subject's public key as a QSslKey. You can call issuerInfo() or |
| subjectInfo() to get detailed information about the certificate |
| issuer and its subject. |
| |
| Internally, QSslCertificate is stored as an X509 structure. You |
| can access this handle by calling handle(), but the results are |
| likely to not be portable. |
| |
| \sa QSslSocket, QSslKey, QSslCipher, QSslError |
| */ |
| |
| /*! |
| \enum QSslCertificate::SubjectInfo |
| |
| Describes keys that you can pass to QSslCertificate::issuerInfo() or |
| QSslCertificate::subjectInfo() to get information about the certificate |
| issuer or subject. |
| |
| \value Organization "O" The name of the organization. |
| |
| \value CommonName "CN" The common name; most often this is used to store |
| the host name. |
| |
| \value LocalityName "L" The locality. |
| |
| \value OrganizationalUnitName "OU" The organizational unit name. |
| |
| \value CountryName "C" The country. |
| |
| \value StateOrProvinceName "ST" The state or province. |
| |
| \value DistinguishedNameQualifier The distinguished name qualifier |
| |
| \value SerialNumber The certificate's serial number |
| |
| \value EmailAddress The email address associated with the certificate |
| */ |
| |
| #include <QtNetwork/qtnetworkglobal.h> |
| #ifndef QT_NO_OPENSSL |
| #include "qsslsocket_openssl_symbols_p.h" |
| #endif |
| #ifdef Q_OS_WINRT |
| #include "qsslsocket_winrt_p.h" |
| #endif |
| #ifdef QT_SECURETRANSPORT |
| #include "qsslsocket_mac_p.h" |
| #endif |
| #if QT_CONFIG(schannel) |
| #include "qsslsocket_schannel_p.h" |
| #endif |
| |
| #include "qssl_p.h" |
| #include "qsslcertificate.h" |
| #include "qsslcertificate_p.h" |
| #ifndef QT_NO_SSL |
| #include "qsslkey_p.h" |
| #endif |
| |
| #include <QtCore/qdir.h> |
| #include <QtCore/qdiriterator.h> |
| #include <QtCore/qfile.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| /*! |
| Constructs a QSslCertificate by reading \a format encoded data |
| from \a device and using the first certificate found. You can |
| later call isNull() to see if \a device contained a certificate, |
| and if this certificate was loaded successfully. |
| */ |
| 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); |
| } |
| |
| /*! |
| Constructs a QSslCertificate by parsing the \a format encoded |
| \a data and using the first available certificate found. You can |
| later call isNull() to see if \a data contained a certificate, |
| and if this certificate was loaded successfully. |
| */ |
| 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); |
| } |
| |
| /*! |
| Constructs an identical copy of \a other. |
| */ |
| QSslCertificate::QSslCertificate(const QSslCertificate &other) : d(other.d) |
| { |
| } |
| |
| /*! |
| Destroys the QSslCertificate. |
| */ |
| QSslCertificate::~QSslCertificate() |
| { |
| } |
| |
| /*! |
| Copies the contents of \a other into this certificate, making the two |
| certificates identical. |
| */ |
| QSslCertificate &QSslCertificate::operator=(const QSslCertificate &other) |
| { |
| d = other.d; |
| return *this; |
| } |
| |
| /*! |
| \fn void QSslCertificate::swap(QSslCertificate &other) |
| \since 5.0 |
| |
| Swaps this certificate instance with \a other. This function is |
| very fast and never fails. |
| */ |
| |
| /*! |
| \fn bool QSslCertificate::operator==(const QSslCertificate &other) const |
| |
| Returns \c true if this certificate is the same as \a other; otherwise |
| returns \c false. |
| */ |
| |
| /*! |
| \fn bool QSslCertificate::operator!=(const QSslCertificate &other) const |
| |
| Returns \c true if this certificate is not the same as \a other; otherwise |
| returns \c false. |
| */ |
| |
| /*! |
| \fn bool QSslCertificate::isNull() const |
| |
| Returns \c true if this is a null certificate (i.e., a certificate |
| with no contents); otherwise returns \c false. |
| |
| By default, QSslCertificate constructs a null certificate. |
| |
| \sa clear() |
| */ |
| |
| #if QT_DEPRECATED_SINCE(5,0) |
| /*! |
| \fn bool QSslCertificate::isValid() const |
| \obsolete |
| |
| To verify a certificate, use verify(). |
| To check if a certificate is blacklisted, use isBlacklisted(). |
| To check if a certificate has expired or is not yet valid, compare |
| expiryDate() and effectiveDate() with QDateTime::currentDateTime() |
| |
| This function checks that the current |
| date-time is within the date-time range during which the |
| certificate is considered valid, and checks that the |
| certificate is not in a blacklist of fraudulent certificates. |
| |
| \sa isNull(), verify(), isBlacklisted(), expiryDate(), effectiveDate() |
| */ |
| #endif |
| |
| /*! |
| Returns \c true if this certificate is blacklisted; otherwise |
| returns \c false. |
| |
| \sa isNull() |
| */ |
| bool QSslCertificate::isBlacklisted() const |
| { |
| return QSslCertificatePrivate::isBlacklisted(*this); |
| } |
| |
| /*! |
| \fn bool QSslCertificate::isSelfSigned() const |
| \since 5.4 |
| |
| Returns \c true if this certificate is self signed; otherwise |
| returns \c false. |
| |
| A certificate is considered self-signed its issuer and subject |
| are identical. |
| */ |
| |
| /*! |
| Clears the contents of this certificate, making it a null |
| certificate. |
| |
| \sa isNull() |
| */ |
| void QSslCertificate::clear() |
| { |
| if (isNull()) |
| return; |
| d = new QSslCertificatePrivate; |
| } |
| |
| /*! |
| \fn QByteArray QSslCertificate::version() const |
| Returns the certificate's version string. |
| */ |
| |
| /*! |
| \fn QByteArray QSslCertificate::serialNumber() const |
| |
| Returns the certificate's serial number string in hexadecimal format. |
| */ |
| |
| /*! |
| Returns a cryptographic digest of this certificate. By default, |
| an MD5 digest will be generated, but you can also specify a |
| custom \a algorithm. |
| */ |
| QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) const |
| { |
| return QCryptographicHash::hash(toDer(), algorithm); |
| } |
| |
| /*! |
| \fn QString QSslCertificate::issuerInfo(SubjectInfo subject) const |
| |
| Returns the issuer information for the \a subject from the |
| certificate, or an empty list if there is no information for |
| \a subject in the certificate. There can be more than one entry |
| of each type. |
| |
| \sa subjectInfo() |
| */ |
| |
| /*! |
| \fn QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const |
| |
| Returns the issuer information for \a attribute from the certificate, |
| or an empty list if there is no information for \a attribute in the |
| certificate. There can be more than one entry for an attribute. |
| |
| \sa subjectInfo() |
| */ |
| |
| /*! |
| \fn QString QSslCertificate::subjectInfo(SubjectInfo subject) const |
| |
| Returns the information for the \a subject, or an empty list if |
| there is no information for \a subject in the certificate. There |
| can be more than one entry of each type. |
| |
| \sa issuerInfo() |
| */ |
| |
| /*! |
| \fn QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const |
| |
| Returns the subject information for \a attribute, or an empty list if |
| there is no information for \a attribute in the certificate. There |
| can be more than one entry for an attribute. |
| |
| \sa issuerInfo() |
| */ |
| |
| /*! |
| \fn QList<QByteArray> QSslCertificate::subjectInfoAttributes() const |
| |
| \since 5.0 |
| Returns a list of the attributes that have values in the subject |
| information of this certificate. The information associated |
| with a given attribute can be accessed using the subjectInfo() |
| method. Note that this list may include the OIDs for any |
| elements that are not known by the SSL backend. |
| |
| \sa subjectInfo() |
| */ |
| |
| /*! |
| \fn QList<QByteArray> QSslCertificate::issuerInfoAttributes() const |
| |
| \since 5.0 |
| Returns a list of the attributes that have values in the issuer |
| information of this certificate. The information associated |
| with a given attribute can be accessed using the issuerInfo() |
| method. Note that this list may include the OIDs for any |
| elements that are not known by the SSL backend. |
| |
| \sa subjectInfo() |
| */ |
| |
| #if QT_DEPRECATED_SINCE(5,0) |
| /*! |
| \fn QMultiMap<QSsl::AlternateNameEntryType, QString> QSslCertificate::alternateSubjectNames() const |
| \obsolete |
| |
| Use QSslCertificate::subjectAlternativeNames(); |
| */ |
| #endif |
| |
| /*! |
| \fn QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlternativeNames() const |
| |
| Returns the list of alternative subject names for this |
| certificate. The alternative names typically contain host |
| names, optionally with wildcards, that are valid for this |
| certificate. |
| |
| These names are tested against the connected peer's host name, if |
| either the subject information for \l CommonName doesn't define a |
| valid host name, or the subject info name doesn't match the peer's |
| host name. |
| |
| \sa subjectInfo() |
| */ |
| |
| /*! |
| \fn QDateTime QSslCertificate::effectiveDate() const |
| |
| Returns the date-time that the certificate becomes valid, or an |
| empty QDateTime if this is a null certificate. |
| |
| \sa expiryDate() |
| */ |
| |
| /*! |
| \fn QDateTime QSslCertificate::expiryDate() const |
| |
| Returns the date-time that the certificate expires, or an empty |
| QDateTime if this is a null certificate. |
| |
| \sa effectiveDate() |
| */ |
| |
| /*! |
| \fn Qt::HANDLE QSslCertificate::handle() const |
| Returns a pointer to the native certificate handle, if there is |
| one, else \nullptr. |
| |
| You can use this handle, together with the native API, to access |
| extended information about the certificate. |
| |
| \warning Use of this function has a high probability of being |
| non-portable, and its return value may vary from platform to |
| platform or change from minor release to minor release. |
| */ |
| |
| /*! |
| \fn QSslKey QSslCertificate::publicKey() const |
| Returns the certificate subject's public key. |
| */ |
| |
| /*! |
| \fn QList<QSslCertificateExtension> QSslCertificate::extensions() const |
| |
| Returns a list containing the X509 extensions of this certificate. |
| \since 5.0 |
| */ |
| |
| /*! |
| \fn QByteArray QSslCertificate::toPem() const |
| |
| Returns this certificate converted to a PEM (Base64) encoded |
| representation. |
| */ |
| |
| /*! |
| \fn QByteArray QSslCertificate::toDer() const |
| |
| Returns this certificate converted to a DER (binary) encoded |
| representation. |
| */ |
| |
| /*! |
| \fn QString QSslCertificate::toText() const |
| |
| Returns this certificate converted to a human-readable text |
| representation. |
| |
| \since 5.0 |
| */ |
| |
| /*! |
| Searches all files in the \a path for certificates encoded in the |
| specified \a format and returns them in a list. \a path must be a file |
| or a pattern matching one or more files, as specified by \a syntax. |
| |
| Example: |
| |
| \snippet code/src_network_ssl_qsslcertificate.cpp 0 |
| |
| \sa fromData() |
| */ |
| QList<QSslCertificate> QSslCertificate::fromPath(const QString &path, |
| QSsl::EncodingFormat format, |
| QRegExp::PatternSyntax syntax) |
| { |
| // $, (,), *, +, ., ?, [, ,], ^, {, | and }. |
| |
| // make sure to use the same path separators on Windows and Unix like systems. |
| QString sourcePath = QDir::fromNativeSeparators(path); |
| |
| // Find the path without the filename |
| QString pathPrefix = sourcePath.left(sourcePath.lastIndexOf(QLatin1Char('/'))); |
| |
| // Check if the path contains any special chars |
| int pos = -1; |
| if (syntax == QRegExp::Wildcard) |
| pos = pathPrefix.indexOf(QRegExp(QLatin1String("[*?[]"))); |
| else if (syntax != QRegExp::FixedString) |
| pos = sourcePath.indexOf(QRegExp(QLatin1String("[\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\}\\|]"))); |
| 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('/')); |
| if (lastIndexOfSlash != -1) |
| pathPrefix = pathPrefix.left(lastIndexOfSlash); |
| else |
| pathPrefix.clear(); |
| } else { |
| // Check if the path is a file. |
| if (QFileInfo(sourcePath).isFile()) { |
| QFile file(sourcePath); |
| QIODevice::OpenMode openMode = QIODevice::ReadOnly; |
| if (format == QSsl::Pem) |
| openMode |= QIODevice::Text; |
| if (file.open(openMode)) |
| return QSslCertificate::fromData(file.readAll(), format); |
| return QList<QSslCertificate>(); |
| } |
| } |
| |
| // Special case - if the prefix ends up being nothing, use "." instead. |
| int startIndex = 0; |
| if (pathPrefix.isEmpty()) { |
| pathPrefix = QLatin1String("."); |
| startIndex = 2; |
| } |
| |
| // The path can be a file or directory. |
| QList<QSslCertificate> certs; |
| QRegExp pattern(sourcePath, Qt::CaseSensitive, syntax); |
| QDirIterator it(pathPrefix, QDir::Files, QDirIterator::FollowSymlinks | QDirIterator::Subdirectories); |
| while (it.hasNext()) { |
| QString filePath = startIndex == 0 ? it.next() : it.next().mid(startIndex); |
| if (!pattern.exactMatch(filePath)) |
| continue; |
| |
| QFile file(filePath); |
| QIODevice::OpenMode openMode = QIODevice::ReadOnly; |
| if (format == QSsl::Pem) |
| openMode |= QIODevice::Text; |
| if (file.open(openMode)) |
| certs += QSslCertificate::fromData(file.readAll(), format); |
| } |
| return certs; |
| } |
| |
| /*! |
| Searches for and parses all certificates in \a device that are |
| encoded in the specified \a format and returns them in a list of |
| certificates. |
| |
| \sa fromData() |
| */ |
| QList<QSslCertificate> QSslCertificate::fromDevice(QIODevice *device, QSsl::EncodingFormat format) |
| { |
| if (!device) { |
| qCWarning(lcSsl, "QSslCertificate::fromDevice: cannot read from a null device"); |
| return QList<QSslCertificate>(); |
| } |
| return fromData(device->readAll(), format); |
| } |
| |
| /*! |
| Searches for and parses all certificates in \a data that are |
| encoded in the specified \a format and returns them in a list of |
| certificates. |
| |
| \sa fromDevice() |
| */ |
| QList<QSslCertificate> QSslCertificate::fromData(const QByteArray &data, QSsl::EncodingFormat format) |
| { |
| return (format == QSsl::Pem) |
| ? QSslCertificatePrivate::certificatesFromPem(data) |
| : QSslCertificatePrivate::certificatesFromDer(data); |
| } |
| |
| #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 |
| be the leaf certificate of the chain to be verified. If \a hostName is |
| specified then the certificate is also checked to see if it is valid for |
| the specified host name. |
| |
| Note that the root (CA) certificate should not be included in the list to be verified, |
| this will be looked up automatically either using the CA list specified by |
| QSslSocket::defaultCaCertificates() or, if possible, it will be loaded on demand |
| on Unix. |
| |
| \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); |
| } |
| |
| /*! |
| \since 5.4 |
| |
| Imports a PKCS#12 (pfx) file from the specified \a device. A PKCS#12 |
| file is a bundle that can contain a number of certificates and keys. |
| This method reads a single \a key, its \a certificate and any |
| associated \a caCertificates from the bundle. If a \a passPhrase is |
| specified then this will be used to decrypt the bundle. Returns |
| \c true if the PKCS#12 file was successfully loaded. |
| |
| \note The \a device must be open and ready to be read from. |
| */ |
| bool QSslCertificate::importPkcs12(QIODevice *device, |
| QSslKey *key, QSslCertificate *certificate, |
| QList<QSslCertificate> *caCertificates, |
| const QByteArray &passPhrase) |
| { |
| return QSslSocketBackendPrivate::importPkcs12(device, key, certificate, caCertificates, passPhrase); |
| } |
| |
| #endif |
| |
| // 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 |
| static const char *const certificate_blacklist[] = { |
| "04:7e:cb:e9:fc:a5:5f:7b:d0:9e:ae:36:e1:0c:ae:1e", "mail.google.com", // Comodo |
| "f5:c8:6a:f3:61:62:f1:3a:64:f5:4f:6d:c9:58:7c:06", "www.google.com", // Comodo |
| "d7:55:8f:da:f5:f1:10:5b:b2:13:28:2b:70:77:29:a3", "login.yahoo.com", // Comodo |
| "39:2a:43:4f:0e:07:df:1f:8a:a3:05:de:34:e0:c2:29", "login.yahoo.com", // Comodo |
| "3e:75:ce:d4:6b:69:30:21:21:88:30:ae:86:a8:2a:71", "login.yahoo.com", // Comodo |
| "e9:02:8b:95:78:e4:15:dc:1a:71:0a:2b:88:15:44:47", "login.skype.com", // Comodo |
| "92:39:d5:34:8f:40:d1:69:5a:74:54:70:e1:f2:3f:43", "addons.mozilla.org", // Comodo |
| "b0:b7:13:3e:d0:96:f9:b5:6f:ae:91:c8:74:bd:3a:c0", "login.live.com", // Comodo |
| "d8:f3:5f:4e:b7:87:2b:2d:ab:06:92:e3:15:38:2f:b0", "global trustee", // Comodo |
| |
| "05:e2:e6:a4:cd:09:ea:54:d6:65:b0:75:fe:22:a2:56", "*.google.com", // leaf certificate issued by DigiNotar |
| "0c:76:da:9c:91:0c:4e:2c:9e:fe:15:d0:58:93:3c:4c", "DigiNotar Root CA", // DigiNotar root |
| "f1:4a:13:f4:87:2b:56:dc:39:df:84:ca:7a:a1:06:49", "DigiNotar Services CA", // DigiNotar intermediate signed by DigiNotar Root |
| "36:16:71:55:43:42:1b:9d:e6:cb:a3:64:41:df:24:38", "DigiNotar Services 1024 CA", // DigiNotar intermediate signed by DigiNotar Root |
| "0a:82:bd:1e:14:4e:88:14:d7:5b:1a:55:27:be:bf:3e", "DigiNotar Root CA G2", // other DigiNotar Root CA |
| "a4:b6:ce:e3:2e:d3:35:46:26:3c:b3:55:3a:a8:92:21", "CertiID Enterprise Certificate Authority", // DigiNotar intermediate signed by "DigiNotar Root CA G2" |
| "5b:d5:60:9c:64:17:68:cf:21:0e:35:fd:fb:05:ad:41", "DigiNotar Qualified CA", // DigiNotar intermediate signed by DigiNotar Root |
| |
| "46:9c:2c:b0", "DigiNotar Services 1024 CA", // DigiNotar intermediate cross-signed by Entrust |
| "07:27:10:0d", "DigiNotar Cyber CA", // DigiNotar intermediate cross-signed by CyberTrust |
| "07:27:0f:f9", "DigiNotar Cyber CA", // DigiNotar intermediate cross-signed by CyberTrust |
| "07:27:10:03", "DigiNotar Cyber CA", // DigiNotar intermediate cross-signed by CyberTrust |
| "01:31:69:b0", "DigiNotar PKIoverheid CA Overheid en Bedrijven", // DigiNotar intermediate cross-signed by the Dutch government |
| "01:31:34:bf", "DigiNotar PKIoverheid CA Organisatie - G2", // DigiNotar intermediate cross-signed by the Dutch government |
| "d6:d0:29:77:f1:49:fd:1a:83:f2:b9:ea:94:8c:5c:b4", "DigiNotar Extended Validation CA", // DigiNotar intermediate signed by DigiNotar EV Root |
| "1e:7d:7a:53:3d:45:30:41:96:40:0f:71:48:1f:45:04", "DigiNotar Public CA 2025", // DigiNotar intermediate |
| // "(has not been seen in the wild so far)", "DigiNotar Public CA - G2", // DigiNotar intermediate |
| // "(has not been seen in the wild so far)", "Koninklijke Notariele Beroepsorganisatie CA", // compromised during DigiNotar breach |
| // "(has not been seen in the wild so far)", "Stichting TTP Infos CA," // compromised during DigiNotar breach |
| "46:9c:2c:af", "DigiNotar Root CA", // DigiNotar intermediate cross-signed by Entrust |
| "46:9c:3c:c9", "DigiNotar Root CA", // DigiNotar intermediate cross-signed by Entrust |
| |
| "07:27:14:a9", "Digisign Server ID (Enrich)", // (Malaysian) Digicert Sdn. Bhd. cross-signed by Verizon CyberTrust |
| "4c:0e:63:6a", "Digisign Server ID - (Enrich)", // (Malaysian) Digicert Sdn. Bhd. cross-signed by Entrust |
| "72:03:21:05:c5:0c:08:57:3d:8e:a5:30:4e:fe:e8:b0", "UTN-USERFirst-Hardware", // comodogate test certificate |
| "41", "MD5 Collisions Inc. (http://www.phreedom.org/md5)", // http://www.phreedom.org/research/rogue-ca/ |
| |
| "08:27", "*.EGO.GOV.TR", // Turktrust mis-issued intermediate certificate |
| "08:64", "e-islem.kktcmerkezbankasi.org", // Turktrust mis-issued intermediate certificate |
| |
| "03:1d:a7", "AC DG Tr\xC3\xA9sor SSL", // intermediate certificate linking back to ANSSI French National Security Agency |
| "27:83", "NIC Certifying Authority", // intermediate certificate from NIC India (2007) |
| "27:92", "NIC CA 2011", // intermediate certificate from NIC India (2011) |
| "27:b1", "NIC CA 2014", // intermediate certificate from NIC India (2014) |
| nullptr |
| }; |
| |
| bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate) |
| { |
| for (int a = 0; certificate_blacklist[a] != nullptr; a++) { |
| QString blacklistedCommonName = QString::fromUtf8(certificate_blacklist[(a+1)]); |
| if (certificate.serialNumber() == certificate_blacklist[a++] && |
| (certificate.subjectInfo(QSslCertificate::CommonName).contains(blacklistedCommonName) || |
| certificate.issuerInfo(QSslCertificate::CommonName).contains(blacklistedCommonName))) |
| return true; |
| } |
| return false; |
| } |
| |
| 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; |
| } |
| return str; |
| } |
| |
| /*! |
| \since 5.12 |
| |
| Returns a name that describes the issuer. It returns the QSslCertificate::CommonName |
| if available, otherwise falls back to the first QSslCertificate::Organization or the |
| first QSslCertificate::OrganizationalUnitName. |
| |
| \sa issuerInfo() |
| */ |
| QString QSslCertificate::issuerDisplayName() const |
| { |
| QStringList names; |
| names = issuerInfo(QSslCertificate::CommonName); |
| if (!names.isEmpty()) |
| return names.first(); |
| names = issuerInfo(QSslCertificate::Organization); |
| if (!names.isEmpty()) |
| return names.first(); |
| names = issuerInfo(QSslCertificate::OrganizationalUnitName); |
| if (!names.isEmpty()) |
| return names.first(); |
| |
| return QString(); |
| } |
| |
| /*! |
| \since 5.12 |
| |
| Returns a name that describes the subject. It returns the QSslCertificate::CommonName |
| if available, otherwise falls back to the first QSslCertificate::Organization or the |
| first QSslCertificate::OrganizationalUnitName. |
| |
| \sa subjectInfo() |
| */ |
| QString QSslCertificate::subjectDisplayName() const |
| { |
| QStringList names; |
| names = subjectInfo(QSslCertificate::CommonName); |
| if (!names.isEmpty()) |
| return names.first(); |
| names = subjectInfo(QSslCertificate::Organization); |
| if (!names.isEmpty()) |
| return names.first(); |
| names = subjectInfo(QSslCertificate::OrganizationalUnitName); |
| if (!names.isEmpty()) |
| return names.first(); |
| |
| return QString(); |
| } |
| |
| /*! |
| \fn uint qHash(const QSslCertificate &key, uint seed) |
| |
| Returns the hash value for the \a key, using \a seed to seed the calculation. |
| \since 5.4 |
| \relates QHash |
| */ |
| |
| #ifndef QT_NO_DEBUG_STREAM |
| 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() |
| #if QT_CONFIG(datestring) |
| << ", " << certificate.effectiveDate() |
| << ", " << certificate.expiryDate() |
| #endif |
| << ')'; |
| return debug; |
| } |
| QDebug operator<<(QDebug debug, QSslCertificate::SubjectInfo info) |
| { |
| switch (info) { |
| case QSslCertificate::Organization: debug << "Organization"; break; |
| case QSslCertificate::CommonName: debug << "CommonName"; break; |
| case QSslCertificate::CountryName: debug << "CountryName"; break; |
| case QSslCertificate::LocalityName: debug << "LocalityName"; break; |
| case QSslCertificate::OrganizationalUnitName: debug << "OrganizationalUnitName"; break; |
| case QSslCertificate::StateOrProvinceName: debug << "StateOrProvinceName"; break; |
| case QSslCertificate::DistinguishedNameQualifier: debug << "DistinguishedNameQualifier"; break; |
| case QSslCertificate::SerialNumber: debug << "SerialNumber"; break; |
| case QSslCertificate::EmailAddress: debug << "EmailAddress"; break; |
| } |
| return debug; |
| } |
| #endif |
| |
| QT_END_NAMESPACE |