File indexing completed on 2024-05-12 16:06:47

0001 /*
0002     SPDX-FileCopyrightText: 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "pdfsignatureutils.h"
0008 
0009 #include <KLocalizedString>
0010 #include <QDebug>
0011 #include <QInputDialog>
0012 
0013 static Okular::CertificateInfo::KeyUsageExtensions fromPoppler(Poppler::CertificateInfo::KeyUsageExtensions popplerKu)
0014 {
0015     using namespace Okular;
0016     CertificateInfo::KeyUsageExtensions ku = CertificateInfo::KuNone;
0017     if (popplerKu.testFlag(Poppler::CertificateInfo::KuDigitalSignature)) {
0018         ku |= CertificateInfo::KuDigitalSignature;
0019     }
0020     if (popplerKu.testFlag(Poppler::CertificateInfo::KuNonRepudiation)) {
0021         ku |= CertificateInfo::KuNonRepudiation;
0022     }
0023     if (popplerKu.testFlag(Poppler::CertificateInfo::KuKeyEncipherment)) {
0024         ku |= CertificateInfo::KuKeyEncipherment;
0025     }
0026     if (popplerKu.testFlag(Poppler::CertificateInfo::KuDataEncipherment)) {
0027         ku |= CertificateInfo::KuDataEncipherment;
0028     }
0029     if (popplerKu.testFlag(Poppler::CertificateInfo::KuKeyAgreement)) {
0030         ku |= CertificateInfo::KuKeyAgreement;
0031     }
0032     if (popplerKu.testFlag(Poppler::CertificateInfo::KuKeyCertSign)) {
0033         ku |= CertificateInfo::KuKeyCertSign;
0034     }
0035     if (popplerKu.testFlag(Poppler::CertificateInfo::KuClrSign)) {
0036         ku |= CertificateInfo::KuClrSign;
0037     }
0038     if (popplerKu.testFlag(Poppler::CertificateInfo::KuEncipherOnly)) {
0039         ku |= CertificateInfo::KuEncipherOnly;
0040     }
0041     return ku;
0042 }
0043 
0044 static Okular::CertificateInfo::PublicKeyType fromPoppler(Poppler::CertificateInfo::PublicKeyType type)
0045 {
0046     switch (type) {
0047     case Poppler::CertificateInfo::RsaKey:
0048         return Okular::CertificateInfo::RsaKey;
0049     case Poppler::CertificateInfo::DsaKey:
0050         return Okular::CertificateInfo::DsaKey;
0051     case Poppler::CertificateInfo::EcKey:
0052         return Okular::CertificateInfo::EcKey;
0053     case Poppler::CertificateInfo::OtherKey:
0054         return Okular::CertificateInfo::OtherKey;
0055     }
0056     return Okular::CertificateInfo::OtherKey;
0057 }
0058 
0059 #if POPPLER_VERSION_MACRO > QT_VERSION_CHECK(23, 8, 0)
0060 static Okular::CertificateInfo::KeyLocation fromPoppler(Poppler::CertificateInfo::KeyLocation location)
0061 {
0062     switch (location) {
0063     case Poppler::CertificateInfo::KeyLocation::Computer:
0064         return Okular::CertificateInfo::KeyLocation::Computer;
0065     case Poppler::CertificateInfo::KeyLocation::Unknown:
0066         return Okular::CertificateInfo::KeyLocation::Unknown;
0067     case Poppler::CertificateInfo::KeyLocation::HardwareToken:
0068         return Okular::CertificateInfo::KeyLocation::HardwareToken;
0069     case Poppler::CertificateInfo::KeyLocation::Other:
0070         return Okular::CertificateInfo::KeyLocation::Other;
0071     }
0072     return Okular::CertificateInfo::KeyLocation::Unknown;
0073 }
0074 #endif
0075 
0076 Okular::CertificateInfo fromPoppler(const Poppler::CertificateInfo &pInfo)
0077 {
0078     Okular::CertificateInfo oInfo;
0079     if (pInfo.isNull()) {
0080         return oInfo;
0081     }
0082     oInfo.setNull(false);
0083     oInfo.setVersion(pInfo.version());
0084     oInfo.setSerialNumber(pInfo.serialNumber());
0085     for (auto key :
0086          {Poppler::CertificateInfo::EntityInfoKey::CommonName, Poppler::CertificateInfo::EntityInfoKey::DistinguishedName, Poppler::CertificateInfo::EntityInfoKey::EmailAddress, Poppler::CertificateInfo::EntityInfoKey::Organization}) {
0087         oInfo.setIssuerInfo(static_cast<Okular::CertificateInfo::EntityInfoKey>(key), pInfo.issuerInfo(key));
0088         oInfo.setSubjectInfo(static_cast<Okular::CertificateInfo::EntityInfoKey>(key), pInfo.subjectInfo(key));
0089     }
0090     oInfo.setNickName(pInfo.nickName());
0091     oInfo.setValidityStart(pInfo.validityStart());
0092     oInfo.setValidityEnd(pInfo.validityEnd());
0093     oInfo.setKeyUsageExtensions(fromPoppler(pInfo.keyUsageExtensions()));
0094     oInfo.setPublicKey(pInfo.publicKey());
0095     oInfo.setPublicKeyType(fromPoppler(pInfo.publicKeyType()));
0096     oInfo.setPublicKeyStrength(pInfo.publicKeyStrength());
0097     oInfo.setSelfSigned(pInfo.isSelfSigned());
0098     oInfo.setCertificateData(pInfo.certificateData());
0099 #if POPPLER_VERSION_MACRO > QT_VERSION_CHECK(23, 8, 0)
0100     oInfo.setKeyLocation(fromPoppler(pInfo.keyLocation()));
0101 #endif
0102     oInfo.setCheckPasswordFunction([pInfo](const QString &password) {
0103 #if POPPLER_VERSION_MACRO >= QT_VERSION_CHECK(23, 06, 0)
0104         auto backend = Poppler::activeCryptoSignBackend();
0105         if (!backend) {
0106             return false;
0107         }
0108         if (Poppler::hasCryptoSignBackendFeature(backend.value(), Poppler::CryptoSignBackendFeature::BackendAsksPassphrase)) {
0109             // we shouldn't ask anyone about passwords. The backend will do that themselves, so just assume everything is okay.
0110             return true;
0111         }
0112 #endif
0113         return pInfo.checkPassword(password);
0114     });
0115 #if POPPLER_VERSION_MACRO >= QT_VERSION_CHECK(23, 06, 0)
0116     if (Poppler::activeCryptoSignBackend() == Poppler::CryptoSignBackend::GPG) {
0117         oInfo.setBackend(Okular::CertificateInfo::Backend::Gpg);
0118     }
0119 #endif
0120     return oInfo;
0121 }
0122 
0123 Okular::SignatureInfo::CertificateStatus fromPoppler(Poppler::SignatureValidationInfo::CertificateStatus status)
0124 {
0125     switch (status) {
0126     case Poppler::SignatureValidationInfo::CertificateTrusted:
0127         return Okular::SignatureInfo::CertificateTrusted;
0128     case Poppler::SignatureValidationInfo::CertificateUntrustedIssuer:
0129         return Okular::SignatureInfo::CertificateUntrustedIssuer;
0130     case Poppler::SignatureValidationInfo::CertificateUnknownIssuer:
0131         return Okular::SignatureInfo::CertificateUnknownIssuer;
0132     case Poppler::SignatureValidationInfo::CertificateRevoked:
0133         return Okular::SignatureInfo::CertificateRevoked;
0134     case Poppler::SignatureValidationInfo::CertificateExpired:
0135         return Okular::SignatureInfo::CertificateExpired;
0136     case Poppler::SignatureValidationInfo::CertificateGenericError:
0137         return Okular::SignatureInfo::CertificateGenericError;
0138     case Poppler::SignatureValidationInfo::CertificateNotVerified:
0139         return Okular::SignatureInfo::CertificateNotVerified;
0140     default:
0141         return Okular::SignatureInfo::CertificateStatusUnknown;
0142     }
0143 }
0144 
0145 Okular::SignatureInfo::SignatureStatus fromPoppler(Poppler::SignatureValidationInfo::SignatureStatus status)
0146 {
0147     switch (status) {
0148     case Poppler::SignatureValidationInfo::SignatureValid:
0149         return Okular::SignatureInfo::SignatureValid;
0150     case Poppler::SignatureValidationInfo::SignatureInvalid:
0151         return Okular::SignatureInfo::SignatureInvalid;
0152     case Poppler::SignatureValidationInfo::SignatureDigestMismatch:
0153         return Okular::SignatureInfo::SignatureDigestMismatch;
0154     case Poppler::SignatureValidationInfo::SignatureDecodingError:
0155         return Okular::SignatureInfo::SignatureDecodingError;
0156     case Poppler::SignatureValidationInfo::SignatureGenericError:
0157         return Okular::SignatureInfo::SignatureGenericError;
0158     case Poppler::SignatureValidationInfo::SignatureNotFound:
0159         return Okular::SignatureInfo::SignatureNotFound;
0160     case Poppler::SignatureValidationInfo::SignatureNotVerified:
0161         return Okular::SignatureInfo::SignatureNotVerified;
0162     default:
0163         return Okular::SignatureInfo::SignatureStatusUnknown;
0164     }
0165 }
0166 
0167 Okular::SignatureInfo::HashAlgorithm fromPoppler(Poppler::SignatureValidationInfo::HashAlgorithm hash)
0168 {
0169     switch (hash) {
0170     case Poppler::SignatureValidationInfo::HashAlgorithmMd2:
0171         return Okular::SignatureInfo::HashAlgorithmMd2;
0172     case Poppler::SignatureValidationInfo::HashAlgorithmMd5:
0173         return Okular::SignatureInfo::HashAlgorithmMd5;
0174     case Poppler::SignatureValidationInfo::HashAlgorithmSha1:
0175         return Okular::SignatureInfo::HashAlgorithmSha1;
0176     case Poppler::SignatureValidationInfo::HashAlgorithmSha256:
0177         return Okular::SignatureInfo::HashAlgorithmSha256;
0178     case Poppler::SignatureValidationInfo::HashAlgorithmSha384:
0179         return Okular::SignatureInfo::HashAlgorithmSha384;
0180     case Poppler::SignatureValidationInfo::HashAlgorithmSha512:
0181         return Okular::SignatureInfo::HashAlgorithmSha512;
0182     case Poppler::SignatureValidationInfo::HashAlgorithmSha224:
0183         return Okular::SignatureInfo::HashAlgorithmSha224;
0184     default:
0185         return Okular::SignatureInfo::HashAlgorithmUnknown;
0186     }
0187 }
0188 
0189 Okular::SignatureInfo fromPoppler(const Poppler::SignatureValidationInfo &pInfo)
0190 {
0191     Okular::SignatureInfo oInfo;
0192     oInfo.setCertificateInfo(fromPoppler(pInfo.certificateInfo()));
0193     oInfo.setSignatureStatus(fromPoppler(pInfo.signatureStatus()));
0194     oInfo.setCertificateStatus(fromPoppler(pInfo.certificateStatus()));
0195     oInfo.setHashAlgorithm(fromPoppler(pInfo.hashAlgorithm()));
0196     oInfo.setSignerName(pInfo.signerName());
0197     oInfo.setSignerSubjectDN(pInfo.signerSubjectDN());
0198     oInfo.setLocation(pInfo.location());
0199     oInfo.setReason(pInfo.reason());
0200     oInfo.setSigningTime(QDateTime::fromSecsSinceEpoch(pInfo.signingTime()));
0201     oInfo.setSignature(pInfo.signature());
0202     oInfo.setSignedRangeBounds(pInfo.signedRangeBounds());
0203     oInfo.setSignsTotalDocument(pInfo.signsTotalDocument());
0204     return oInfo;
0205 }
0206 
0207 PopplerCertificateStore::~PopplerCertificateStore() = default;
0208 
0209 QList<Okular::CertificateInfo> PopplerCertificateStore::signingCertificates(bool *userCancelled) const
0210 {
0211     *userCancelled = false;
0212     auto PDFGeneratorNSSPasswordCallback = [&userCancelled](const char *element) -> char * {
0213         bool ok;
0214         const QString pwd = QInputDialog::getText(nullptr, i18n("Enter Password"), i18n("Enter password to open %1:", QString::fromUtf8(element)), QLineEdit::Password, QString(), &ok);
0215         *userCancelled = !ok;
0216         return ok ? strdup(pwd.toUtf8().constData()) : nullptr;
0217     };
0218     Poppler::setNSSPasswordCallback(PDFGeneratorNSSPasswordCallback);
0219 
0220     const QVector<Poppler::CertificateInfo> certs = Poppler::getAvailableSigningCertificates();
0221     QList<Okular::CertificateInfo> vReturnCerts;
0222     for (const auto &cert : certs) {
0223         vReturnCerts.append(fromPoppler(cert));
0224     }
0225 
0226     Poppler::setNSSPasswordCallback(nullptr);
0227 
0228     return vReturnCerts;
0229 }