Certificate store tool

This commit is contained in:
Jakub Melka 2020-11-02 19:24:27 +01:00
parent d335aaa266
commit 78215e89af
8 changed files with 242 additions and 3 deletions

View File

@ -2044,3 +2044,33 @@ void pdf::PDFPublicKeySignatureHandler::addTrustedCertificates(X509_STORE* store
}
#endif
}
pdf::PDFCertificateStore::CertificateEntries pdf::PDFCertificateStore::getSystemCertificates()
{
CertificateEntries result;
#ifdef Q_OS_WIN
HCERTSTORE certStore = CertOpenSystemStore(NULL, L"ROOT");
PCCERT_CONTEXT context = nullptr;
if (certStore)
{
while (context = CertEnumCertificatesInStore(certStore, context))
{
const unsigned char* pointer = context->pbCertEncoded;
QByteArray data(reinterpret_cast<const char*>(pointer), context->cbCertEncoded);
std::optional<PDFCertificateInfo> info = PDFCertificateInfo::getCertificateInfo(data);
if (info)
{
CertificateEntry entry;
entry.type = EntryType::System;
entry.info = qMove(*info);
result.emplace_back(qMove(entry));
}
}
CertCloseStore(certStore, CERT_CLOSE_STORE_FORCE_FLAG);
}
#endif
return result;
}

View File

@ -473,8 +473,9 @@ public:
enum class EntryType : int
{
User, ///< Certificate has been added manually by the user
EUTL ///< Certificate comes EU trusted list
User, ///< Certificate has been added manually by the user
EUTL, ///< Certificate comes EU trusted list
System, ///< System certificate
};
struct CertificateEntry
@ -532,6 +533,9 @@ public:
/// Creates default directory for certificate store
void createDirectoryForDefaultUserCertificatesStore();
/// Returns a list of system certificates
static CertificateEntries getSystemCertificates();
private:
static constexpr int persist_version = 1;

View File

@ -587,6 +587,10 @@ void PDFViewerSettingsDialog::updateTrustedCertificatesTable()
type = tr("EUTL");
break;
case pdf::PDFCertificateStore::EntryType::System:
type = tr("System");
break;
default:
Q_ASSERT(false);
break;

View File

@ -44,6 +44,7 @@ SOURCES += \
pdftoolabstractapplication.cpp \
pdftoolattachments.cpp \
pdftoolaudiobook.cpp \
pdftoolcertstore.cpp \
pdftoolcolorprofiles.cpp \
pdftoolfetchimages.cpp \
pdftoolfetchtext.cpp \
@ -75,6 +76,7 @@ HEADERS += \
pdftoolabstractapplication.h \
pdftoolattachments.h \
pdftoolaudiobook.h \
pdftoolcertstore.h \
pdftoolcolorprofiles.h \
pdftoolfetchimages.h \
pdftoolfetchtext.h \

View File

@ -311,6 +311,12 @@ void PDFToolAbstractApplication::initializeCommandLineParser(QCommandLineParser*
parser->addOption(QCommandLineOption(info.option, info.description));
}
}
if (optionFlags.testFlag(CertStore))
{
parser->addOption(QCommandLineOption("list-user-certs", "Show list of user certificates.", "bool", "1"));
parser->addOption(QCommandLineOption("list-system-certs", "Show list of system certificates.", "bool", "0"));
}
}
PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser) const
@ -840,6 +846,12 @@ PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser
}
}
if (optionFlags.testFlag(CertStore))
{
options.certStoreEnumerateSystemCertificates = parser->value("list-system-certs").toInt();
options.certStoreEnumerateUserCertificates = parser->value("list-user-certs").toInt();
}
return options;
}

View File

@ -139,6 +139,10 @@ struct PDFToolOptions
// For option 'Optimize'
pdf::PDFOptimizer::OptimizationFlags optimizeFlags = pdf::PDFOptimizer::None;
// For option 'CertStore'
bool certStoreEnumerateSystemCertificates = false;
bool certStoreEnumerateUserCertificates = true;
/// Returns page range. If page range is invalid, then \p errorMessage is empty.
/// \param pageCount Page count
/// \param[out] errorMessage Error message
@ -217,7 +221,8 @@ public:
RenderFlags = 0x00020000, ///< Render flags for page image rasterizer
Separate = 0x00040000, ///< Settings for Separate tool
Unite = 0x00080000, ///< Settings for Unite tool
Optimize = 0x00100000, ///< Settings for Optimize
Optimize = 0x00100000, ///< Settings for Optimize tool
CertStore = 0x00200000, ///< Settings for certificate store tool
};
Q_DECLARE_FLAGS(Options, Option)

View File

@ -0,0 +1,146 @@
// Copyright (C) 2020 Jakub Melka
//
// This file is part of PdfForQt.
//
// PdfForQt is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// PdfForQt is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
#include "pdftoolcertstore.h"
#include "pdfsignaturehandler.h"
namespace pdftool
{
static PDFToolCertStore s_certStoreApplication;
QString PDFToolCertStore::getStandardString(PDFToolAbstractApplication::StandardString standardString) const
{
switch (standardString)
{
case Command:
return "cert-store";
case Name:
return PDFToolTranslationContext::tr("Certificate Store");
case Description:
return PDFToolTranslationContext::tr("Certificate store operations (list, add, remove certificates).");
default:
Q_ASSERT(false);
break;
}
return QString();
}
int PDFToolCertStore::execute(const PDFToolOptions& options)
{
// Certificate store
pdf::PDFCertificateStore certificateStore;
if (options.certStoreEnumerateUserCertificates)
{
certificateStore.loadDefaultUserCertificates();
}
pdf::PDFCertificateStore::CertificateEntries certificates = certificateStore.getCertificates();
if (options.certStoreEnumerateSystemCertificates)
{
pdf::PDFCertificateStore::CertificateEntries systemCertificates = pdf::PDFCertificateStore::getSystemCertificates();
certificates.insert(certificates.end(), std::make_move_iterator(systemCertificates.begin()), std::make_move_iterator(systemCertificates.end()));
}
PDFOutputFormatter formatter(options.outputStyle, options.outputCodec);
formatter.beginDocument("cert-store", PDFToolTranslationContext::tr("Certificates used in signature verification"));
formatter.endl();
formatter.beginTable("certificate-list", PDFToolTranslationContext::tr("Certificates"));
formatter.beginTableHeaderRow("header");
formatter.writeTableHeaderColumn("no", PDFToolTranslationContext::tr("No."));
formatter.writeTableHeaderColumn("type", PDFToolTranslationContext::tr("Type"));
formatter.writeTableHeaderColumn("certificate", PDFToolTranslationContext::tr("Certificate"));
formatter.writeTableHeaderColumn("organization", PDFToolTranslationContext::tr("Organization"));
formatter.writeTableHeaderColumn("valid-from", PDFToolTranslationContext::tr("Valid from"));
formatter.writeTableHeaderColumn("valid-to", PDFToolTranslationContext::tr("Valid to"));
formatter.endTableHeaderRow();
int ref = 1;
QLocale locale;
for (const pdf::PDFCertificateStore::CertificateEntry& entry : certificates)
{
QString type;
switch (entry.type)
{
case pdf::PDFCertificateStore::EntryType::User:
type = PDFToolTranslationContext::tr("User");
break;
case pdf::PDFCertificateStore::EntryType::EUTL:
type = PDFToolTranslationContext::tr("EUTL");
break;
case pdf::PDFCertificateStore::EntryType::System:
type = PDFToolTranslationContext::tr("System");
break;
default:
Q_ASSERT(false);
break;
}
QDateTime notValidBefore = entry.info.getNotValidBefore().toLocalTime();
QDateTime notValidAfter = entry.info.getNotValidAfter().toLocalTime();
QString notValidBeforeText;
QString notValidAfterText;
if (notValidBefore.isValid())
{
notValidBeforeText = notValidBefore.toString(options.outputDateFormat);
}
if (notValidAfter.isValid())
{
notValidAfterText = notValidAfter.toString(options.outputDateFormat);
}
formatter.beginTableRow("certificate", ref);
formatter.writeTableColumn("no", locale.toString(ref++), Qt::AlignRight);
formatter.writeTableColumn("type", type);
formatter.writeTableColumn("certificate", entry.info.getName(pdf::PDFCertificateInfo::CommonName));
formatter.writeTableColumn("organization", entry.info.getName(pdf::PDFCertificateInfo::OrganizationName));
formatter.writeTableColumn("valid-from", notValidBeforeText);
formatter.writeTableColumn("valid-to", notValidAfterText);
formatter.endTableRow();
}
formatter.endTable();
formatter.endDocument();
PDFConsole::writeText(formatter.getString(), options.outputCodec);
return ExitSuccess;
}
PDFToolAbstractApplication::Options PDFToolCertStore::getOptionsFlags() const
{
return ConsoleFormat | DateFormat | CertStore;
}
} // namespace pdftool

View File

@ -0,0 +1,36 @@
// Copyright (C) 2020 Jakub Melka
//
// This file is part of PdfForQt.
//
// PdfForQt is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// PdfForQt is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
#ifndef PDFTOOLCERTSTORE_H
#define PDFTOOLCERTSTORE_H
#include "pdftoolabstractapplication.h"
namespace pdftool
{
class PDFToolCertStore : public PDFToolAbstractApplication
{
public:
virtual QString getStandardString(StandardString standardString) const override;
virtual int execute(const PDFToolOptions& options) override;
virtual Options getOptionsFlags() const override;
};
} // namespace pdftool
#endif // PDFTOOLCERTSTORE_H