diff --git a/okular/core/document.cpp b/okular/core/document.cpp index a4a08cb36..8698cdc8c 100644 --- a/okular/core/document.cpp +++ b/okular/core/document.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -5257,6 +5258,30 @@ QByteArray Document::requestSignedRevisionData(const Okular::SignatureInfo &info return data; } +QByteArray Document::requestSignedRevisionDataNew(const Okular::SignatureInfo &info) const +{ + QFile f(d->m_docFileName); + if (!f.open(QIODevice::ReadOnly)) { + QMessageBox::critical(nullptr, QString(), i18n("Could not open '%1'. File does not exist", d->m_docFileName)); + return {}; + } + + const QList byteRange = info.signedRangeBounds(); + if (byteRange.count() % 2) { + QMessageBox::critical(nullptr, QString(), i18n("Invalid format of signed range bounds")); + return {}; + } + + QByteArray data; + for (int i = 0; i < byteRange.count(); i += 2) { + f.seek(byteRange[i]); + data.append(f.read(byteRange[i+1] - byteRange[i])); + } + f.close(); + + return data; +} + void Document::refreshPixmaps(int pageNumber) { d->refreshPixmaps(pageNumber); diff --git a/okular/core/document.h b/okular/core/document.h index 558d94ddd..71fdaa506 100644 --- a/okular/core/document.h +++ b/okular/core/document.h @@ -1113,6 +1113,7 @@ public Q_SLOTS: * @since 1.7 */ QByteArray requestSignedRevisionData(const Okular::SignatureInfo &info); + QByteArray requestSignedRevisionDataNew(const Okular::SignatureInfo &info) const; /** * Refresh the pixmaps for the given @p pageNumber. diff --git a/okular/core/signatureutils.cpp b/okular/core/signatureutils.cpp index 454a8493f..86b215288 100644 --- a/okular/core/signatureutils.cpp +++ b/okular/core/signatureutils.cpp @@ -101,8 +101,9 @@ SignatureInfo::~SignatureInfo() { } -SignatureInfo::SignatureStatus SignatureInfo::signatureStatus() const +SignatureInfo::SignatureStatus SignatureInfo::signatureStatus(const Document *doc) const { + Q_UNUSED(doc) return SignatureStatusUnknown; } diff --git a/okular/core/signatureutils.h b/okular/core/signatureutils.h index c17c5133d..dc0382265 100644 --- a/okular/core/signatureutils.h +++ b/okular/core/signatureutils.h @@ -8,6 +8,7 @@ #define OKULAR_SIGNATUREUTILS_H #include "okularcore_export.h" +#include "document.h" #include #include @@ -183,7 +184,7 @@ public: /** * The signature status of the signature. */ - virtual SignatureStatus signatureStatus() const; + virtual SignatureStatus signatureStatus(const Document *) const; /** * The certificate status of the signature. diff --git a/okular/generators/poppler/pdfsignatureutils.cpp b/okular/generators/poppler/pdfsignatureutils.cpp index 75530904e..fe48f1814 100644 --- a/okular/generators/poppler/pdfsignatureutils.cpp +++ b/okular/generators/poppler/pdfsignatureutils.cpp @@ -6,6 +6,9 @@ #include "pdfsignatureutils.h" +#include +#include +#include #include #include #include @@ -153,6 +156,56 @@ PopplerSignatureInfo::~PopplerSignatureInfo() delete m_certfiticateInfo; } +bool PopplerSignatureInfo::writeSignature(const Okular::Document *doc, const QString &file, const QString &sig) const +{ + if (file.isEmpty() || sig.isEmpty()) + return false; + + QFile f(file); + QFile g(sig); + if (!f.open(QIODevice::WriteOnly) || !g.open(QIODevice::WriteOnly)) + return false; + + f.write(doc->requestSignedRevisionDataNew(*this)); + f.close(); + + /* Extract signature */ + g.write(signature()); + g.close(); + + return true; +} + +PopplerSignatureInfo::SignatureStatus PopplerSignatureInfo::signatureStatus(const Okular::Document *doc) const +{ + QString program = "/usr/bin/alt-csp-cryptopro"; + QFile cryptoproTool(program); + if (!cryptoproTool.exists()) + return signatureStatus(); + + QString fileName, sig; + if (!m_tempDir || !m_tempDir->isValid()) + m_tempDir.reset(new QTemporaryDir(QDir::tempPath() + "/.okular-XXXXXX")); + + if (!m_tempDir->isValid()) + return signatureStatus(); + + QString base = m_tempDir->path() + QDir::separator(); + fileName = base + "file"; + sig = base + "signature"; + + if (!(QFile::exists(fileName) && QFile::exists(sig)) + && !writeSignature(doc, fileName, sig)) + return signatureStatus(); + + QStringList args = {"--verify", fileName, sig}; + int exitCode = QProcess::execute(program, args); + if (!exitCode) + return PopplerSignatureInfo::SignatureValid; + else + return signatureStatus(); +} + PopplerSignatureInfo::SignatureStatus PopplerSignatureInfo::signatureStatus() const { switch (m_info.signatureStatus()) { diff --git a/okular/generators/poppler/pdfsignatureutils.h b/okular/generators/poppler/pdfsignatureutils.h index 48b68f194..faaf4e891 100644 --- a/okular/generators/poppler/pdfsignatureutils.h +++ b/okular/generators/poppler/pdfsignatureutils.h @@ -13,6 +13,8 @@ #include +#include + class PopplerCertificateInfo : public Okular::CertificateInfo { public: @@ -45,7 +47,7 @@ public: explicit PopplerSignatureInfo(const Poppler::SignatureValidationInfo &info); ~PopplerSignatureInfo() override; - SignatureStatus signatureStatus() const override; + SignatureStatus signatureStatus(const Okular::Document *) const override; CertificateStatus certificateStatus() const override; QString signerName() const override; QString signerSubjectDN() const override; @@ -59,6 +61,10 @@ public: const Okular::CertificateInfo &certificateInfo() const override; private: + SignatureStatus signatureStatus() const; + bool writeSignature(const Okular::Document *, const QString&, const QString&) const; + + mutable QScopedPointer m_tempDir; Poppler::SignatureValidationInfo m_info; Okular::CertificateInfo *m_certfiticateInfo; }; diff --git a/okular/gui/signatureguiutils.cpp b/okular/gui/signatureguiutils.cpp index eacd8bbb4..49918e165 100644 --- a/okular/gui/signatureguiutils.cpp +++ b/okular/gui/signatureguiutils.cpp @@ -154,9 +154,9 @@ QString getReadableKeyUsageNewLineSeparated(Okular::CertificateInfo::KeyUsageExt return getReadableKeyUsage(kuExtensions, QStringLiteral("\n")); } -QString getReadableModificationSummary(const Okular::SignatureInfo &signatureInfo) +QString getReadableModificationSummary(const Okular::SignatureInfo &signatureInfo, const Okular::Document *doc) { - const Okular::SignatureInfo::SignatureStatus signatureStatus = signatureInfo.signatureStatus(); + const Okular::SignatureInfo::SignatureStatus signatureStatus = signatureInfo.signatureStatus(doc); // signature validation status if (signatureStatus == Okular::SignatureInfo::SignatureValid) { if (signatureInfo.signsTotalDocument()) { @@ -195,7 +195,7 @@ std::pair documentSignatureMessageWidgetTe anySignatureUnsigned = true; } else { const Okular::SignatureInfo &info = signature->signatureInfo(); - if (info.signatureStatus() != Okular::SignatureInfo::SignatureValid) { + if (info.signatureStatus(doc) != Okular::SignatureInfo::SignatureValid) { allSignaturesValid = false; } } diff --git a/okular/gui/signatureguiutils.h b/okular/gui/signatureguiutils.h index 538878ab2..30e0ffdb0 100644 --- a/okular/gui/signatureguiutils.h +++ b/okular/gui/signatureguiutils.h @@ -31,7 +31,7 @@ QString getReadableHashAlgorithm(Okular::SignatureInfo::HashAlgorithm hashAlg); QString getReadablePublicKeyType(Okular::CertificateInfo::PublicKeyType type); QString getReadableKeyUsageCommaSeparated(Okular::CertificateInfo::KeyUsageExtensions kuExtensions); QString getReadableKeyUsageNewLineSeparated(Okular::CertificateInfo::KeyUsageExtensions kuExtensions); -QString getReadableModificationSummary(const Okular::SignatureInfo &signatureInfo); +QString getReadableModificationSummary(const Okular::SignatureInfo &signatureInfo, const Okular::Document *doc); std::pair documentSignatureMessageWidgetText(const Okular::Document *doc); } diff --git a/okular/gui/signaturemodel.cpp b/okular/gui/signaturemodel.cpp index a90fde392..0374b035c 100644 --- a/okular/gui/signaturemodel.cpp +++ b/okular/gui/signaturemodel.cpp @@ -152,7 +152,7 @@ void SignatureModelPrivate::notifySetup(const QVector &pages, in parentItem->displayString = i18n("Rev. %1: Signed By %2", revNumber, info.signerName()); auto childItem1 = new SignatureItem(parentItem, nullptr, SignatureItem::ValidityStatus, pageNumber); - childItem1->displayString = SignatureGuiUtils::getReadableSignatureStatus(info.signatureStatus()); + childItem1->displayString = SignatureGuiUtils::getReadableSignatureStatus(info.signatureStatus(document)); auto childItem2 = new SignatureItem(parentItem, nullptr, SignatureItem::SigningTime, pageNumber); childItem2->displayString = i18n("Signing Time: %1", info.signingTime().toString(Qt::DefaultLocaleLongDate)); @@ -225,7 +225,7 @@ QVariant SignatureModel::data(const QModelIndex &index, int role) const return item->displayString; case Qt::DecorationRole: if (item->type == SignatureItem::RevisionInfo) { - const Okular::SignatureInfo::SignatureStatus signatureStatus = form->signatureInfo().signatureStatus(); + const Okular::SignatureInfo::SignatureStatus signatureStatus = form->signatureInfo().signatureStatus(d->document); switch (signatureStatus) { case Okular::SignatureInfo::SignatureValid: return QIcon::fromTheme(QStringLiteral("dialog-ok")); @@ -243,9 +243,9 @@ QVariant SignatureModel::data(const QModelIndex &index, int role) const case PageRole: return item->page; case ReadableStatusRole: - return SignatureGuiUtils::getReadableSignatureStatus(form->signatureInfo().signatureStatus()); + return SignatureGuiUtils::getReadableSignatureStatus(form->signatureInfo().signatureStatus(d->document)); case ReadableModificationSummary: - return SignatureGuiUtils::getReadableModificationSummary(form->signatureInfo()); + return SignatureGuiUtils::getReadableModificationSummary(form->signatureInfo(), d->document); case SignerNameRole: return form->signatureInfo().signerName(); case SigningTimeRole: @@ -265,7 +265,7 @@ QVariant SignatureModel::data(const QModelIndex &index, int role) const } case SignatureRevisionIndexRole: { const Okular::SignatureInfo &signatureInfo = form->signatureInfo(); - const Okular::SignatureInfo::SignatureStatus signatureStatus = signatureInfo.signatureStatus(); + const Okular::SignatureInfo::SignatureStatus signatureStatus = signatureInfo.signatureStatus(d->document); if (signatureStatus != Okular::SignatureInfo::SignatureStatusUnknown && !signatureInfo.signsTotalDocument()) { const QVector signatureFormFields = SignatureGuiUtils::getSignatureFormFields(d->document); return signatureFormFields.indexOf(form); diff --git a/okular/part/signaturepropertiesdialog.cpp b/okular/part/signaturepropertiesdialog.cpp index 8b0dc5811..8b0593262 100644 --- a/okular/part/signaturepropertiesdialog.cpp +++ b/okular/part/signaturepropertiesdialog.cpp @@ -38,9 +38,9 @@ SignaturePropertiesDialog::SignaturePropertiesDialog(Okular::Document *doc, cons setWindowTitle(i18n("Signature Properties")); const Okular::SignatureInfo &signatureInfo = form->signatureInfo(); - const Okular::SignatureInfo::SignatureStatus signatureStatus = signatureInfo.signatureStatus(); + const Okular::SignatureInfo::SignatureStatus signatureStatus = signatureInfo.signatureStatus(doc); const QString readableSignatureStatus = SignatureGuiUtils::getReadableSignatureStatus(signatureStatus); - const QString modificationSummary = SignatureGuiUtils::getReadableModificationSummary(signatureInfo); + const QString modificationSummary = SignatureGuiUtils::getReadableModificationSummary(signatureInfo, doc); const QString signerName = getValidDisplayString(signatureInfo.signerName()); const QString signingTime = getValidDisplayString(signatureInfo.signingTime().toString(Qt::DefaultLocaleLongDate)); const QString signingLocation = getValidDisplayString(signatureInfo.location());