mirror of https://github.com/JakubMelka/PDF4QT.git
Digital signatures verification tool (first part)
This commit is contained in:
parent
13563a7bcc
commit
ddf852d34e
|
@ -353,6 +353,14 @@ void PDFSignatureVerificationResult::setSignatureFieldReference(PDFObjectReferen
|
||||||
m_signatureFieldReference = signatureFieldReference;
|
m_signatureFieldReference = signatureFieldReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFSignatureVerificationResult::addHashAlgorithm(const QString& algorithm)
|
||||||
|
{
|
||||||
|
if (!m_hashAlgorithms.contains(algorithm))
|
||||||
|
{
|
||||||
|
m_hashAlgorithms << algorithm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PDFSignatureVerificationResult::validate()
|
void PDFSignatureVerificationResult::validate()
|
||||||
{
|
{
|
||||||
if (isCertificateValid() && isSignatureValid())
|
if (isCertificateValid() && isSignatureValid())
|
||||||
|
@ -660,6 +668,13 @@ void PDFPublicKeySignatureHandler::verifySignature(PDFSignatureVerificationResul
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (signerInfoValue->digest_alg && signerInfoValue->digest_alg->algorithm)
|
||||||
|
{
|
||||||
|
std::array<char, 64> buffer = { };
|
||||||
|
OBJ_obj2txt(buffer.data(), int(buffer.size() - 1), signerInfoValue->digest_alg->algorithm, 0);
|
||||||
|
result.addHashAlgorithm(QString::fromLatin1(buffer.data()));
|
||||||
|
}
|
||||||
|
|
||||||
const int verification = PKCS7_signatureVerify(dataBio, pkcs7, signerInfoValue, signer);
|
const int verification = PKCS7_signatureVerify(dataBio, pkcs7, signerInfoValue, signer);
|
||||||
if (verification <= 0)
|
if (verification <= 0)
|
||||||
{
|
{
|
||||||
|
@ -1339,7 +1354,7 @@ void PDFSignatureHandler_adbe_pkcs7_rsa_sha1::verifyRSASignature(PDFSignatureVer
|
||||||
const unsigned int encryptedSignLength = signKey.length();
|
const unsigned int encryptedSignLength = signKey.length();
|
||||||
if (ASN1_OCTET_STRING* encryptedString = d2i_ASN1_OCTET_STRING(nullptr, &encryptedSign, encryptedSignLength))
|
if (ASN1_OCTET_STRING* encryptedString = d2i_ASN1_OCTET_STRING(nullptr, &encryptedSign, encryptedSignLength))
|
||||||
{
|
{
|
||||||
int algorithmNID = 0;
|
int algorithmNID = NID_undef;
|
||||||
QByteArray digestBuffer;
|
QByteArray digestBuffer;
|
||||||
if (!getMessageDigest(outputBuffer, encryptedString, rsa, algorithmNID, digestBuffer))
|
if (!getMessageDigest(outputBuffer, encryptedString, rsa, algorithmNID, digestBuffer))
|
||||||
{
|
{
|
||||||
|
@ -1353,6 +1368,10 @@ void PDFSignatureHandler_adbe_pkcs7_rsa_sha1::verifyRSASignature(PDFSignatureVer
|
||||||
const unsigned char* digest = convertByteArrayToUcharPtr(digestBuffer);
|
const unsigned char* digest = convertByteArrayToUcharPtr(digestBuffer);
|
||||||
const unsigned int digestLength = digestBuffer.length();
|
const unsigned int digestLength = digestBuffer.length();
|
||||||
|
|
||||||
|
std::array<char, 64> buffer = { };
|
||||||
|
OBJ_obj2txt(buffer.data(), int(buffer.size() - 1), OBJ_nid2obj(algorithmNID), 0);
|
||||||
|
result.addHashAlgorithm(QString::fromLatin1(buffer.data()));
|
||||||
|
|
||||||
const int verifyValue = RSA_verify(algorithmNID, digest, digestLength, encryptedString->data, encryptedString->length, rsa);
|
const int verifyValue = RSA_verify(algorithmNID, digest, digestLength, encryptedString->data, encryptedString->length, rsa);
|
||||||
ASN1_OCTET_STRING_free(encryptedString);
|
ASN1_OCTET_STRING_free(encryptedString);
|
||||||
|
|
||||||
|
@ -1760,6 +1779,53 @@ bool PDFCertificateStore::contains(const PDFCertificateInfo& info)
|
||||||
return std::find_if(m_certificates.cbegin(), m_certificates.cend(), [&info](const auto& entry) { return entry.info == info; }) != m_certificates.cend();
|
return std::find_if(m_certificates.cbegin(), m_certificates.cend(), [&info](const auto& entry) { return entry.info == info; }) != m_certificates.cend();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString PDFCertificateStore::getDefaultCertificateStoreFileName() const
|
||||||
|
{
|
||||||
|
return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/TrustedCertStorage.bin";
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFCertificateStore::loadDefaultUserCertificates()
|
||||||
|
{
|
||||||
|
QString trustedCertificateStoreFileName = getDefaultCertificateStoreFileName();
|
||||||
|
QString trustedCertificateStoreLockFileName = trustedCertificateStoreFileName + ".lock";
|
||||||
|
|
||||||
|
QLockFile lockFile(trustedCertificateStoreLockFileName);
|
||||||
|
if (lockFile.lock())
|
||||||
|
{
|
||||||
|
QFile trustedCertificateStoreFile(trustedCertificateStoreFileName);
|
||||||
|
if (trustedCertificateStoreFile.open(QFile::ReadOnly))
|
||||||
|
{
|
||||||
|
QDataStream stream(&trustedCertificateStoreFile);
|
||||||
|
deserialize(stream);
|
||||||
|
trustedCertificateStoreFile.close();
|
||||||
|
}
|
||||||
|
lockFile.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFCertificateStore::saveDefaultUserCertificates()
|
||||||
|
{
|
||||||
|
QString trustedCertificateStoreFileName = getDefaultCertificateStoreFileName();
|
||||||
|
QString trustedCertificateStoreLockFileName = trustedCertificateStoreFileName + ".lock";
|
||||||
|
|
||||||
|
QFileInfo fileInfo(trustedCertificateStoreFileName);
|
||||||
|
QDir dir = fileInfo.dir();
|
||||||
|
dir.mkpath(dir.path());
|
||||||
|
|
||||||
|
QLockFile lockFile(trustedCertificateStoreLockFileName);
|
||||||
|
if (lockFile.lock())
|
||||||
|
{
|
||||||
|
QFile trustedCertificateStoreFile(trustedCertificateStoreFileName);
|
||||||
|
if (trustedCertificateStoreFile.open(QFile::WriteOnly | QFile::Truncate))
|
||||||
|
{
|
||||||
|
QDataStream stream(&trustedCertificateStoreFile);
|
||||||
|
serialize(stream);
|
||||||
|
trustedCertificateStoreFile.close();
|
||||||
|
}
|
||||||
|
lockFile.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|
|
@ -365,12 +365,14 @@ public:
|
||||||
const QString& getSignatureFieldQualifiedName() const { return m_signatureFieldQualifiedName; }
|
const QString& getSignatureFieldQualifiedName() const { return m_signatureFieldQualifiedName; }
|
||||||
const QStringList& getErrors() const { return m_errors; }
|
const QStringList& getErrors() const { return m_errors; }
|
||||||
const QStringList& getWarnings() const { return m_warnings; }
|
const QStringList& getWarnings() const { return m_warnings; }
|
||||||
|
const QStringList& getHashAlgorithms() const { return m_hashAlgorithms; }
|
||||||
const PDFCertificateInfos& getCertificateInfos() const { return m_certificateInfos; }
|
const PDFCertificateInfos& getCertificateInfos() const { return m_certificateInfos; }
|
||||||
|
|
||||||
void setSignatureFieldQualifiedName(const QString& signatureFieldQualifiedName);
|
void setSignatureFieldQualifiedName(const QString& signatureFieldQualifiedName);
|
||||||
void setSignatureFieldReference(PDFObjectReference signatureFieldReference);
|
void setSignatureFieldReference(PDFObjectReference signatureFieldReference);
|
||||||
|
|
||||||
void addCertificateInfo(PDFCertificateInfo info) { m_certificateInfos.emplace_back(qMove(info)); }
|
void addCertificateInfo(PDFCertificateInfo info) { m_certificateInfos.emplace_back(qMove(info)); }
|
||||||
|
void addHashAlgorithm(const QString& algorithm);
|
||||||
|
|
||||||
/// Adds OK flag, if both certificate and signature are valid
|
/// Adds OK flag, if both certificate and signature are valid
|
||||||
void validate();
|
void validate();
|
||||||
|
@ -382,6 +384,7 @@ private:
|
||||||
QString m_signatureFieldQualifiedName;
|
QString m_signatureFieldQualifiedName;
|
||||||
QStringList m_errors;
|
QStringList m_errors;
|
||||||
QStringList m_warnings;
|
QStringList m_warnings;
|
||||||
|
QStringList m_hashAlgorithms;
|
||||||
PDFCertificateInfos m_certificateInfos;
|
PDFCertificateInfos m_certificateInfos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -480,6 +483,15 @@ public:
|
||||||
/// Set certificates
|
/// Set certificates
|
||||||
void setCertificates(CertificateEntries certificates) { m_certificates = qMove(certificates); }
|
void setCertificates(CertificateEntries certificates) { m_certificates = qMove(certificates); }
|
||||||
|
|
||||||
|
/// Returns default certificate store file name
|
||||||
|
QString getDefaultCertificateStoreFileName() const;
|
||||||
|
|
||||||
|
/// Load from default user certificate storage
|
||||||
|
void loadDefaultUserCertificates();
|
||||||
|
|
||||||
|
/// Save to default user certificate storage
|
||||||
|
void saveDefaultUserCertificates();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr int persist_version = 1;
|
static constexpr int persist_version = 1;
|
||||||
|
|
||||||
|
|
|
@ -430,6 +430,13 @@ void PDFSidebarWidget::updateSignatures(const std::vector<pdf::PDFSignatureVerif
|
||||||
item->setIcon(0, warningIcon);
|
item->setIcon(0, warningIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString hashAlgorithms = signature.getHashAlgorithms().join(", ");
|
||||||
|
if (!hashAlgorithms.isEmpty())
|
||||||
|
{
|
||||||
|
QTreeWidgetItem* item = new QTreeWidgetItem(rootItem, QStringList(tr("Hash algorithms: %1").arg(hashAlgorithms)));
|
||||||
|
item->setIcon(0, infoIcon);
|
||||||
|
}
|
||||||
|
|
||||||
if (certificateInfo)
|
if (certificateInfo)
|
||||||
{
|
{
|
||||||
QTreeWidgetItem* certChainRoot = new QTreeWidgetItem(rootItem, QStringList(tr("Certificate validation chain")));
|
QTreeWidgetItem* certChainRoot = new QTreeWidgetItem(rootItem, QStringList(tr("Certificate validation chain")));
|
||||||
|
|
|
@ -735,21 +735,7 @@ void PDFViewerMainWindow::readActionSettings()
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
// Load trusted certificates
|
// Load trusted certificates
|
||||||
QString trustedCertificateStoreFileName = getTrustedCertificateStoreFileName();
|
m_certificateStore.loadDefaultUserCertificates();
|
||||||
QString trustedCertificateStoreLockFileName = trustedCertificateStoreFileName + ".lock";
|
|
||||||
|
|
||||||
QLockFile lockFile(trustedCertificateStoreLockFileName);
|
|
||||||
if (lockFile.lock())
|
|
||||||
{
|
|
||||||
QFile trustedCertificateStoreFile(trustedCertificateStoreFileName);
|
|
||||||
if (trustedCertificateStoreFile.open(QFile::ReadOnly))
|
|
||||||
{
|
|
||||||
QDataStream stream(&trustedCertificateStoreFile);
|
|
||||||
m_certificateStore.deserialize(stream);
|
|
||||||
trustedCertificateStoreFile.close();
|
|
||||||
}
|
|
||||||
lockFile.unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFViewerMainWindow::writeSettings()
|
void PDFViewerMainWindow::writeSettings()
|
||||||
|
@ -780,25 +766,7 @@ void PDFViewerMainWindow::writeSettings()
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
// Save trusted certificates
|
// Save trusted certificates
|
||||||
QString trustedCertificateStoreFileName = getTrustedCertificateStoreFileName();
|
m_certificateStore.saveDefaultUserCertificates();
|
||||||
QString trustedCertificateStoreLockFileName = trustedCertificateStoreFileName + ".lock";
|
|
||||||
|
|
||||||
QFileInfo fileInfo(trustedCertificateStoreFileName);
|
|
||||||
QDir dir = fileInfo.dir();
|
|
||||||
dir.mkpath(dir.path());
|
|
||||||
|
|
||||||
QLockFile lockFile(trustedCertificateStoreLockFileName);
|
|
||||||
if (lockFile.lock())
|
|
||||||
{
|
|
||||||
QFile trustedCertificateStoreFile(trustedCertificateStoreFileName);
|
|
||||||
if (trustedCertificateStoreFile.open(QFile::WriteOnly | QFile::Truncate))
|
|
||||||
{
|
|
||||||
QDataStream stream(&trustedCertificateStoreFile);
|
|
||||||
m_certificateStore.serialize(stream);
|
|
||||||
trustedCertificateStoreFile.close();
|
|
||||||
}
|
|
||||||
lockFile.unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFViewerMainWindow::updateTitle()
|
void PDFViewerMainWindow::updateTitle()
|
||||||
|
@ -1200,11 +1168,6 @@ QList<QAction*> PDFViewerMainWindow::getActions() const
|
||||||
return findChildren<QAction*>(QString(), Qt::FindChildrenRecursively);
|
return findChildren<QAction*>(QString(), Qt::FindChildrenRecursively);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PDFViewerMainWindow::getTrustedCertificateStoreFileName() const
|
|
||||||
{
|
|
||||||
return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/TrustedCertStorage.bin";
|
|
||||||
}
|
|
||||||
|
|
||||||
int PDFViewerMainWindow::adjustDpiX(int value)
|
int PDFViewerMainWindow::adjustDpiX(int value)
|
||||||
{
|
{
|
||||||
const int physicalDpiX = this->physicalDpiX();
|
const int physicalDpiX = this->physicalDpiX();
|
||||||
|
|
|
@ -148,8 +148,6 @@ private:
|
||||||
std::vector<QAction*> getRenderingOptionActions() const;
|
std::vector<QAction*> getRenderingOptionActions() const;
|
||||||
QList<QAction*> getActions() const;
|
QList<QAction*> getActions() const;
|
||||||
|
|
||||||
QString getTrustedCertificateStoreFileName() const;
|
|
||||||
|
|
||||||
int adjustDpiX(int value);
|
int adjustDpiX(int value);
|
||||||
|
|
||||||
struct AsyncReadingResult
|
struct AsyncReadingResult
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
|
# along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
QT -= gui
|
|
||||||
|
|
||||||
CONFIG += c++11 console
|
CONFIG += c++11 console
|
||||||
CONFIG -= app_bundle
|
CONFIG -= app_bundle
|
||||||
|
|
||||||
|
@ -43,7 +41,8 @@ LIBS += -lPDFForQtLib
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
pdfoutputformatter.cpp \
|
pdfoutputformatter.cpp \
|
||||||
pdftoolabstractapplication.cpp
|
pdftoolabstractapplication.cpp \
|
||||||
|
pdftoolverifysignatures.cpp
|
||||||
|
|
||||||
# Default rules for deployment.
|
# Default rules for deployment.
|
||||||
qnx: target.path = /tmp/$${TARGET}/bin
|
qnx: target.path = /tmp/$${TARGET}/bin
|
||||||
|
@ -56,4 +55,5 @@ INSTALLS += application
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
pdfoutputformatter.h \
|
pdfoutputformatter.h \
|
||||||
pdftoolabstractapplication.h
|
pdftoolabstractapplication.h \
|
||||||
|
pdftoolverifysignatures.h
|
||||||
|
|
|
@ -630,4 +630,13 @@ void PDFConsole::writeText(QString text)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFConsole::writeError(QString text)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), text.utf16(), text.size(), nullptr, nullptr);
|
||||||
|
#else
|
||||||
|
QTextStream(stdout) << text;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // pdftool
|
} // pdftool
|
||||||
|
|
|
@ -95,6 +95,9 @@ public:
|
||||||
/// Writes text to the console
|
/// Writes text to the console
|
||||||
static void writeText(QString text);
|
static void writeText(QString text);
|
||||||
|
|
||||||
|
/// Writes error to the console
|
||||||
|
static void writeError(QString text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit PDFConsole() = delete;
|
explicit PDFConsole() = delete;
|
||||||
};
|
};
|
||||||
|
|
|
@ -130,12 +130,30 @@ void PDFToolAbstractApplication::initializeCommandLineParser(QCommandLineParser*
|
||||||
{
|
{
|
||||||
parser->addOption(QCommandLineOption("console-format", "Console output text format (valid values: text|xml|html).", "console-format", "text"));
|
parser->addOption(QCommandLineOption("console-format", "Console output text format (valid values: text|xml|html).", "console-format", "text"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (optionFlags.testFlag(OpenDocument))
|
||||||
|
{
|
||||||
|
parser->addOption(QCommandLineOption("pswd", "Password for encrypted document.", "password"));
|
||||||
|
parser->addPositionalArgument("document", "Processed document.");
|
||||||
|
parser->addOption(QCommandLineOption("no-permissive-reading", "Do not attempt to fix damaged documents."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optionFlags.testFlag(SignatureVerification))
|
||||||
|
{
|
||||||
|
parser->addOption(QCommandLineOption("ver-no-user-cert", "Disable user certificate store."));
|
||||||
|
parser->addOption(QCommandLineOption("ver-no-sys-cert", "Disable system certificate store."));
|
||||||
|
parser->addOption(QCommandLineOption("ver-no-cert-check", "Disable certificate validation."));
|
||||||
|
parser->addOption(QCommandLineOption("ver-cert-details", "Print certificate details (including chain, if found)."));
|
||||||
|
parser->addOption(QCommandLineOption("ver-ignore-exp-date", "Ignore certificate expiration date."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser) const
|
PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser) const
|
||||||
{
|
{
|
||||||
PDFToolOptions options;
|
PDFToolOptions options;
|
||||||
|
|
||||||
|
QStringList positionalArguments = parser->positionalArguments();
|
||||||
|
|
||||||
Options optionFlags = getOptionsFlags();
|
Options optionFlags = getOptionsFlags();
|
||||||
if (optionFlags.testFlag(ConsoleFormat))
|
if (optionFlags.testFlag(ConsoleFormat))
|
||||||
{
|
{
|
||||||
|
@ -154,10 +172,31 @@ PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (!consoleFormat.isEmpty())
|
||||||
|
{
|
||||||
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Unknown console format '%1'. Defaulting to text console format.").arg(consoleFormat));
|
||||||
|
}
|
||||||
|
|
||||||
options.outputStyle = PDFOutputFormatter::Style::Text;
|
options.outputStyle = PDFOutputFormatter::Style::Text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (optionFlags.testFlag(OpenDocument))
|
||||||
|
{
|
||||||
|
options.document = positionalArguments.isEmpty() ? QString() : positionalArguments.front();
|
||||||
|
options.password = parser->value("password");
|
||||||
|
options.permissiveReading = !parser->isSet("no-permissive-reading");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optionFlags.testFlag(SignatureVerification))
|
||||||
|
{
|
||||||
|
options.verificationUseUserCertificates = !parser->isSet("ver-no-user-cert");
|
||||||
|
options.verificationUseSystemCertificates = !parser->isSet("ver-no-sys-cert");
|
||||||
|
options.verificationOmitCertificateCheck = parser->isSet("ver-no-cert-check");
|
||||||
|
options.verificationPrintCertificateDetails = parser->isSet("ver-cert-details");
|
||||||
|
options.verificationIgnoreExpirationDate = parser->isSet("ver-ignore-exp-date");
|
||||||
|
}
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,20 @@ struct PDFToolTranslationContext
|
||||||
|
|
||||||
struct PDFToolOptions
|
struct PDFToolOptions
|
||||||
{
|
{
|
||||||
|
// For option 'ConsoleFormat'
|
||||||
|
PDFOutputFormatter::Style outputStyle = PDFOutputFormatter::Style::Text;
|
||||||
|
|
||||||
|
// For option 'OpenDocument'
|
||||||
QString document;
|
QString document;
|
||||||
QString password;
|
QString password;
|
||||||
PDFOutputFormatter::Style outputStyle = PDFOutputFormatter::Style::Text;
|
bool permissiveReading = true;
|
||||||
|
|
||||||
|
// For option 'SignatureVerification'
|
||||||
|
bool verificationUseUserCertificates = true;
|
||||||
|
bool verificationUseSystemCertificates = true;
|
||||||
|
bool verificationOmitCertificateCheck = false;
|
||||||
|
bool verificationPrintCertificateDetails = false;
|
||||||
|
bool verificationIgnoreExpirationDate = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Base class for all applications
|
/// Base class for all applications
|
||||||
|
@ -52,7 +63,9 @@ public:
|
||||||
|
|
||||||
enum ExitCodes
|
enum ExitCodes
|
||||||
{
|
{
|
||||||
ExitSuccess = EXIT_SUCCESS
|
ExitSuccess = EXIT_SUCCESS,
|
||||||
|
ErrorNoDocumentSpecified,
|
||||||
|
ErrorDocumentReading
|
||||||
};
|
};
|
||||||
|
|
||||||
enum StandardString
|
enum StandardString
|
||||||
|
@ -65,6 +78,8 @@ public:
|
||||||
enum Option
|
enum Option
|
||||||
{
|
{
|
||||||
ConsoleFormat = 0x0001, ///< Set format of console output (text, xml or html)
|
ConsoleFormat = 0x0001, ///< Set format of console output (text, xml or html)
|
||||||
|
OpenDocument = 0x0002, ///< Flags for document reading
|
||||||
|
SignatureVerification = 0x0004, ///< Flags for signature verification
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Options, Option)
|
Q_DECLARE_FLAGS(Options, Option)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
// 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 "pdftoolverifysignatures.h"
|
||||||
|
|
||||||
|
#include "pdfdocumentreader.h"
|
||||||
|
#include "pdfsignaturehandler.h"
|
||||||
|
#include "pdfform.h"
|
||||||
|
|
||||||
|
namespace pdftool
|
||||||
|
{
|
||||||
|
|
||||||
|
static PDFToolVerifySignaturesApplication s_verifySignaturesApplication;
|
||||||
|
|
||||||
|
QString PDFToolVerifySignaturesApplication::getStandardString(StandardString standardString) const
|
||||||
|
{
|
||||||
|
switch (standardString)
|
||||||
|
{
|
||||||
|
case Command:
|
||||||
|
return "verify-signatures";
|
||||||
|
|
||||||
|
case Name:
|
||||||
|
return PDFToolTranslationContext::tr("Signature verification");
|
||||||
|
|
||||||
|
case Description:
|
||||||
|
return PDFToolTranslationContext::tr("Verify signatures and timestamps in pdf document.");
|
||||||
|
|
||||||
|
default:
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int PDFToolVerifySignaturesApplication::execute(const PDFToolOptions& options)
|
||||||
|
{
|
||||||
|
// No document specified?
|
||||||
|
if (options.document.isEmpty())
|
||||||
|
{
|
||||||
|
PDFConsole::writeError(PDFToolTranslationContext::tr("No document specified."));
|
||||||
|
return ErrorNoDocumentSpecified;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isFirstPasswordAttempt = true;
|
||||||
|
auto passwordCallback = [&options, &isFirstPasswordAttempt](bool* ok) -> QString
|
||||||
|
{
|
||||||
|
*ok = isFirstPasswordAttempt;
|
||||||
|
isFirstPasswordAttempt = false;
|
||||||
|
return options.password;
|
||||||
|
};
|
||||||
|
pdf::PDFDocumentReader reader(nullptr, passwordCallback, options.permissiveReading);
|
||||||
|
pdf::PDFDocument document = reader.readFromFile(options.document);
|
||||||
|
|
||||||
|
switch (reader.getReadingResult())
|
||||||
|
{
|
||||||
|
case pdf::PDFDocumentReader::Result::OK:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case pdf::PDFDocumentReader::Result::Cancelled:
|
||||||
|
return ExitSuccess;
|
||||||
|
|
||||||
|
case pdf::PDFDocumentReader::Result::Failed:
|
||||||
|
{
|
||||||
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Error occured during document reading. %1").arg(reader.getErrorMessage()));
|
||||||
|
return ErrorDocumentReading;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return ErrorDocumentReading;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const QString& warning : reader.getWarnings())
|
||||||
|
{
|
||||||
|
PDFConsole::writeError(PDFToolTranslationContext::tr("Warning: %1").arg(warning));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify signatures
|
||||||
|
pdf::PDFCertificateStore certificateStore;
|
||||||
|
if (options.verificationUseUserCertificates)
|
||||||
|
{
|
||||||
|
certificateStore.loadDefaultUserCertificates();
|
||||||
|
}
|
||||||
|
|
||||||
|
pdf::PDFSignatureHandler::Parameters parameters;
|
||||||
|
parameters.store = &certificateStore;
|
||||||
|
parameters.dss = &document.getCatalog()->getDocumentSecurityStore();
|
||||||
|
parameters.enableVerification = true;
|
||||||
|
parameters.ignoreExpirationDate = options.verificationIgnoreExpirationDate;
|
||||||
|
parameters.useSystemCertificateStore = options.verificationUseSystemCertificates;
|
||||||
|
|
||||||
|
pdf::PDFForm form = pdf::PDFForm::parse(&document, document.getCatalog()->getFormObject());
|
||||||
|
std::vector<pdf::PDFSignatureVerificationResult> signatures = pdf::PDFSignatureHandler::verifySignatures(form, reader.getSource(), parameters);
|
||||||
|
|
||||||
|
return ExitSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFToolAbstractApplication::Options PDFToolVerifySignaturesApplication::getOptionsFlags() const
|
||||||
|
{
|
||||||
|
return PDFToolAbstractApplication::ConsoleFormat | PDFToolAbstractApplication::OpenDocument | PDFToolAbstractApplication::SignatureVerification;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pdftool
|
|
@ -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 PDFTOOLVERIFYSIGNATURES_H
|
||||||
|
#define PDFTOOLVERIFYSIGNATURES_H
|
||||||
|
|
||||||
|
#include "pdftoolabstractapplication.h"
|
||||||
|
|
||||||
|
namespace pdftool
|
||||||
|
{
|
||||||
|
|
||||||
|
class PDFToolVerifySignaturesApplication : 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 // PDFTOOLVERIFYSIGNATURES_H
|
Loading…
Reference in New Issue