QSslCertificate: add fromFile() method
QSslCertificate::fromPath() does some extra work: - matching wildcard glob or regular expression patterns - checks if the string it's called on is a file or a dir That extra work isn't needed when you already have the path to a specific certificate file. E.g. qtlsbackend_openssl.cpp:systemCaCertificates() used to call fromPath() on *.pem/*.crt files that it got from iterating over system certifcates dirs. This also de-duplicates the code in fromPath(). [ChangeLog][QtNetwork][QSslCertificate] Added fromFile() method. Change-Id: I92ab358e4711866dd4510da42c47905c7dae58b1 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
2875c4358b
commit
2be51c6923
@ -633,6 +633,9 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
|
||||
if (path.isEmpty())
|
||||
return {};
|
||||
|
||||
if (syntax == PatternSyntax::FixedString && QFileInfo(path).isFile())
|
||||
return fromFile(path, format);
|
||||
|
||||
// $, (,), *, +, ., ?, [, ,], ^, {, | and }.
|
||||
|
||||
// make sure to use the same path separators on Windows and Unix like systems.
|
||||
@ -665,15 +668,8 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
|
||||
pathPrefix = {};
|
||||
} 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>();
|
||||
}
|
||||
if (QFileInfo(sourcePath).isFile())
|
||||
return fromFile(sourcePath, format);
|
||||
}
|
||||
|
||||
// Special case - if the prefix ends up being nothing, use "." instead.
|
||||
@ -710,12 +706,7 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
|
||||
continue;
|
||||
#endif
|
||||
|
||||
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);
|
||||
certs += QSslCertificate::fromFile(filePath, format);
|
||||
}
|
||||
return certs;
|
||||
}
|
||||
@ -760,6 +751,30 @@ QList<QSslCertificate> QSslCertificate::fromData(const QByteArray &data, QSsl::E
|
||||
return reader(data, -1);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.10
|
||||
|
||||
Reads the data from the file \a filePath and parses all certificates
|
||||
that are encoded in the specified \a format and returns a list of
|
||||
QSslCertificate objects.
|
||||
|
||||
If \a filePath isn't a regular file, this method will return an empty
|
||||
list.
|
||||
|
||||
\sa fromData(), fromPath()
|
||||
*/
|
||||
QList<QSslCertificate> QSslCertificate::fromFile(const QString &filePath,
|
||||
QSsl::EncodingFormat format)
|
||||
{
|
||||
QFile file(filePath);
|
||||
QIODevice::OpenMode openMode = QIODevice::ReadOnly;
|
||||
if (format == QSsl::Pem)
|
||||
openMode |= QIODevice::Text;
|
||||
if (file.open(openMode))
|
||||
return QSslCertificate::fromData(file.readAll(), format);
|
||||
return {};
|
||||
}
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
/*!
|
||||
Verifies a certificate chain. The chain to be verified is passed in the
|
||||
|
@ -107,6 +107,8 @@ public:
|
||||
QIODevice *device, QSsl::EncodingFormat format = QSsl::Pem);
|
||||
static QList<QSslCertificate> fromData(
|
||||
const QByteArray &data, QSsl::EncodingFormat format = QSsl::Pem);
|
||||
static QList<QSslCertificate> fromFile(
|
||||
const QString &filePath, QSsl::EncodingFormat format = QSsl::Pem);
|
||||
|
||||
#ifndef QT_NO_SSL
|
||||
static QList<QSslError> verify(const QList<QSslCertificate> &certificateChain, const QString &hostName = QString());
|
||||
|
@ -410,7 +410,7 @@ QList<QSslCertificate> systemCaCertificates()
|
||||
}
|
||||
}
|
||||
for (const QString& file : std::as_const(certFiles))
|
||||
systemCerts.append(QSslCertificate::fromPath(file, QSsl::Pem));
|
||||
systemCerts.append(QSslCertificate::fromFile(file, QSsl::Pem));
|
||||
}
|
||||
#endif // platform
|
||||
#ifdef QSSLSOCKET_DEBUG
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include <openssl/obj_mac.h>
|
||||
#endif
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
class tst_QSslCertificate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -97,6 +99,9 @@ private slots:
|
||||
// helper for verbose test failure messages
|
||||
QString toString(const QList<QSslError>&);
|
||||
|
||||
private:
|
||||
void certInfo_helper(const char *methodName);
|
||||
|
||||
// ### add tests for certificate bundles (multiple certificates concatenated into a single
|
||||
// structure); both PEM and DER formatted
|
||||
#endif // QT_CONFIG(ssl)
|
||||
@ -494,12 +499,23 @@ void tst_QSslCertificate::subjectIssuerDisplayName()
|
||||
QFETCH(const QString, certName);
|
||||
QFETCH(const QString, expectedName);
|
||||
|
||||
{
|
||||
const auto chain = QSslCertificate::fromPath(testDataDir + certName);
|
||||
QCOMPARE(chain.size(), 1);
|
||||
const auto cert = chain.at(0);
|
||||
QVERIFY(!cert.isNull());
|
||||
QCOMPARE(cert.subjectDisplayName(), expectedName);
|
||||
QCOMPARE(cert.issuerDisplayName(), expectedName);
|
||||
}
|
||||
|
||||
{
|
||||
const auto chain = QSslCertificate::fromFile(testDataDir + certName);
|
||||
QCOMPARE(chain.size(), 1);
|
||||
const auto cert = chain.at(0);
|
||||
QVERIFY(!cert.isNull());
|
||||
QCOMPARE(cert.subjectDisplayName(), expectedName);
|
||||
QCOMPARE(cert.issuerDisplayName(), expectedName);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QSslCertificate::utf8SubjectNames()
|
||||
@ -701,9 +717,14 @@ void tst_QSslCertificate::fromPath_qregularexpression()
|
||||
pemencoding ? QSsl::Pem : QSsl::Der,
|
||||
QSslCertificate::PatternSyntax(syntax)).size(),
|
||||
numCerts);
|
||||
|
||||
if (QSslCertificate::PatternSyntax(syntax) == QSslCertificate::PatternSyntax::FixedString) {
|
||||
const auto list = QSslCertificate::fromFile(path, pemencoding ? QSsl::Pem : QSsl::Der);
|
||||
QCOMPARE(list.size(), numCerts);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QSslCertificate::certInfo()
|
||||
void tst_QSslCertificate::certInfo_helper(const char *methodName)
|
||||
{
|
||||
// MD5 Fingerprint=B6:CF:57:34:DA:A9:73:21:82:F7:CF:4D:3D:85:31:88
|
||||
// SHA1 Fingerprint=B6:D1:51:82:E0:29:CA:59:96:38:BD:B6:F9:40:05:91:6D:49:09:60
|
||||
@ -788,8 +809,14 @@ void tst_QSslCertificate::certInfo()
|
||||
"dc:c2:eb:b7:bb:50:18:05:ba:ad:af:08:49:fe:98:63"
|
||||
"55:ba:e7:fb:95:5d:91";
|
||||
|
||||
QSslCertificate cert = QSslCertificate::fromPath(testDataDir + "certificates/cert.pem", QSsl::Pem,
|
||||
QSslCertificate::PatternSyntax::FixedString).first();
|
||||
QSslCertificate cert;
|
||||
if (methodName == "fromPath"_L1) {
|
||||
cert = QSslCertificate::fromPath(testDataDir + "certificates/cert.pem", QSsl::Pem,
|
||||
QSslCertificate::PatternSyntax::FixedString).first();
|
||||
} else if (methodName == "fromFile"_L1) {
|
||||
cert = QSslCertificate::fromFile(testDataDir + "certificates/cert.pem", QSsl::Pem).first();
|
||||
}
|
||||
|
||||
QVERIFY(!cert.isNull());
|
||||
|
||||
QCOMPARE(cert.issuerInfo(QSslCertificate::Organization)[0], QString("CryptSoft Pty Ltd"));
|
||||
@ -845,8 +872,15 @@ void tst_QSslCertificate::certInfo()
|
||||
QCOMPARE(cert, QSslCertificate(QByteArray::fromHex(der), QSsl::Der));
|
||||
}
|
||||
|
||||
void tst_QSslCertificate::certInfo()
|
||||
{
|
||||
certInfo_helper("fromPath");
|
||||
certInfo_helper("fromFile");
|
||||
}
|
||||
|
||||
void tst_QSslCertificate::certInfoQByteArray()
|
||||
{
|
||||
{
|
||||
QSslCertificate cert = QSslCertificate::fromPath(testDataDir + "certificates/cert.pem", QSsl::Pem,
|
||||
QSslCertificate::PatternSyntax::FixedString).first();
|
||||
QVERIFY(!cert.isNull());
|
||||
@ -855,6 +889,18 @@ void tst_QSslCertificate::certInfoQByteArray()
|
||||
// we fixed a bug we had with lazy initialization of the values.
|
||||
QCOMPARE(cert.issuerInfo("CN")[0], QString("Test CA (1024 bit)"));
|
||||
QCOMPARE(cert.subjectInfo("CN")[0], QString("name/with/slashes"));
|
||||
}
|
||||
|
||||
{
|
||||
QSslCertificate cert =
|
||||
QSslCertificate::fromFile(testDataDir + "certificates/cert.pem", QSsl::Pem).first();
|
||||
QVERIFY(!cert.isNull());
|
||||
|
||||
// in this test, check the bytearray variants before the enum variants to see if
|
||||
// we fixed a bug we had with lazy initialization of the values.
|
||||
QCOMPARE(cert.issuerInfo("CN")[0], QString("Test CA (1024 bit)"));
|
||||
QCOMPARE(cert.subjectInfo("CN")[0], QString("name/with/slashes"));
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QSslCertificate::task256066toPem()
|
||||
|
Loading…
x
Reference in New Issue
Block a user