diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,6 +193,7 @@ core/utils.cpp core/view.cpp core/fileprinter.cpp + core/signatureinfo.cpp core/script/event.cpp core/synctex/synctex_parser.c core/synctex/synctex_parser_utils.c diff --git a/core/form.h b/core/form.h --- a/core/form.h +++ b/core/form.h @@ -13,6 +13,7 @@ #include "okularcore_export.h" #include "area.h" #include "annotations.h" +#include "signatureinfo.h" #include @@ -25,6 +26,7 @@ class FormFieldButtonPrivate; class FormFieldTextPrivate; class FormFieldChoicePrivate; +class FormFieldSignaturePrivate; /** * @short The base interface of a form field. @@ -387,6 +389,46 @@ Q_DISABLE_COPY( FormFieldChoice ) }; +/** + * @short Interface of a signature form field. + * + * This is the base interface to reimplement to represent a signature field. + */ +class OKULARCORE_EXPORT FormFieldSignature : public FormField +{ + public: + /** + * The types of signature. + */ + enum SignatureType { + AdbePkcs7sha1, + AdbePkcs7detached, + EtsiCAdESdetached, + UnknownType + }; + + ~FormFieldSignature(); + + /** + * The signature type + */ + virtual SignatureType signatureType() const = 0; + + /** + * Validate the signature with 'now' as validation time. + * + */ + virtual SignatureInfo* validate() const = 0; + + + protected: + FormFieldSignature(); + + private: + Q_DECLARE_PRIVATE( FormFieldSignature ) + Q_DISABLE_COPY( FormFieldSignature ) +}; + } #endif diff --git a/core/form.cpp b/core/form.cpp --- a/core/form.cpp +++ b/core/form.cpp @@ -294,3 +294,32 @@ return false; } +class Okular::FormFieldSignaturePrivate : public Okular::FormFieldPrivate +{ + public: + FormFieldSignaturePrivate() + : FormFieldPrivate( FormField::FormSignature ) + { + } + + Q_DECLARE_PUBLIC( FormFieldSignature ) + + void setValue( const QString& v ) override + { + Q_UNUSED( v ) + } + + QString value() const override + { + return QString(); + } +}; + +FormFieldSignature::FormFieldSignature() + : FormField( *new FormFieldSignaturePrivate() ) +{ +} + +FormFieldSignature::~FormFieldSignature() +{ +} diff --git a/core/signatureinfo.h b/core/signatureinfo.h new file mode 100644 --- /dev/null +++ b/core/signatureinfo.h @@ -0,0 +1,131 @@ +/*************************************************************************** + * Copyright (C) 2018 by Chinmoy Ranjan Pradhan * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef OKULAR_SIGNATUREINFO_H +#define OKULAR_SIGNATUREINFO_H + +#include "okularcore_export.h" + +#include +#include +#include + +namespace Okular { + +/** + * @short A helper class to information about digital signature + */ +class OKULARCORE_EXPORT SignatureInfo +{ + public: + + /** + * The verfication result of the signature. + */ + enum SignatureStatus { + SignatureStatusUnknown, ///< The signature status is unknown for some reason. + SignatureValid, ///< The signature is cryptographically valid. + SignatureInvalid, ///< The signature is cryptographically invalid. + SignatureDigestMismatch, ///< The document content was changed after the signature was applied. + SignatureDecodingError, ///< The signature CMS/PKCS7 structure is malformed. + SignatureGenericError, ///< The signature could not be verified. + SignatureNotFound, ///< The requested signature is not present in the document. + SignatureNotVerified ///< The signature is not yet verified. + }; + + /** + * The verification result of the certificate. + */ + enum CertificateStatus { + CertificateStatusUnknown, ///< The certificate status is unknown for some reason. + CertificateTrusted, ///< The certificate is considered trusted. + CertificateUntrustedIssuer, ///< The issuer of this certificate has been marked as untrusted by the user. + CertificateUnknownIssuer, ///< The certificate trust chain has not finished in a trusted root certificate. + CertificateRevoked, ///< The certificate was revoked by the issuing certificate authority. + CertificateExpired, ///< The signing time is outside the validity bounds of this certificate. + CertificateGenericError, ///< The certificate could not be verified. + CertificateNotVerified ///< The certificate is not yet verified. + }; + + /** + * The hash algorithm of the signature + */ + enum HashAlgorithm + { + HashAlgorithmUnknown, + HashAlgorithmMd2, + HashAlgorithmMd5, + HashAlgorithmSha1, + HashAlgorithmSha256, + HashAlgorithmSha384, + HashAlgorithmSha512, + HashAlgorithmSha224 + }; + + /** + * Destructor. + */ + virtual ~SignatureInfo(); + + /** + * The signature status of the signature. + */ + virtual SignatureStatus signatureStatus() const; + + /** + * The certificate status of the signature. + */ + virtual CertificateStatus certificateStatus() const; + + /** + * The signer subject common name associated with the signature. + */ + virtual QString subjectCN() const; + + /** + * The signer subject distinguished name associated with the signature. + */ + virtual QString subjectDN() const; + + /** + * The the hash algorithm used for the signature. + */ + virtual HashAlgorithm hashAlgorithm() const; + + /** + * The signing time associated with the signature. + */ + virtual QDateTime signingTime() const; + + /** + * Get the signature binary data. + */ + virtual QByteArray signature() const; + + /** + * Get the bounds of the ranges of the document which are signed. + */ + virtual QList signedRangeBounds() const; + + /** + * Checks whether the signature authenticates the total document + * except for the signature itself. + */ + virtual bool signsTotalDocument() const; + + protected: + SignatureInfo(); + + private: + Q_DISABLE_COPY( SignatureInfo ) +}; + +} + +#endif diff --git a/core/signatureinfo.cpp b/core/signatureinfo.cpp new file mode 100644 --- /dev/null +++ b/core/signatureinfo.cpp @@ -0,0 +1,65 @@ +/*************************************************************************** + * Copyright (C) 2018 by Chinmoy Ranjan Pradhan * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "signatureinfo.h" + +using namespace Okular; + +SignatureInfo::SignatureInfo() +{ +} + +SignatureInfo::~SignatureInfo() +{ +} + +SignatureInfo::SignatureStatus SignatureInfo::signatureStatus() const +{ + return SignatureStatusUnknown; +} + +SignatureInfo::CertificateStatus SignatureInfo::certificateStatus() const +{ + return CertificateStatusUnknown; +} + +QString SignatureInfo::subjectCN() const +{ + return QString(); +} + +QString SignatureInfo::subjectDN() const +{ + return QString(); +} + +SignatureInfo::HashAlgorithm SignatureInfo::hashAlgorithm() const +{ + return HashAlgorithmUnknown; +} + +QDateTime SignatureInfo::signingTime() const +{ + return QDateTime(); +} + +QByteArray SignatureInfo::signature() const +{ + return QByteArray(); +} + +QList SignatureInfo::signedRangeBounds() const +{ + return QList(); +} + +bool SignatureInfo::signsTotalDocument() const +{ + return false; +} diff --git a/generators/poppler/CMakeLists.txt b/generators/poppler/CMakeLists.txt --- a/generators/poppler/CMakeLists.txt +++ b/generators/poppler/CMakeLists.txt @@ -111,6 +111,7 @@ generator_pdf.cpp formfields.cpp annots.cpp + pdfsignatureinfo.cpp ) ki18n_wrap_ui(okularGenerator_poppler_PART_SRCS diff --git a/generators/poppler/formfields.h b/generators/poppler/formfields.h --- a/generators/poppler/formfields.h +++ b/generators/poppler/formfields.h @@ -111,4 +111,28 @@ }; +class PopplerFormFieldSignature : public Okular::FormFieldSignature +{ + public: + PopplerFormFieldSignature( Poppler::FormFieldSignature * field ); + virtual ~PopplerFormFieldSignature(); + + // inherited from Okular::FormField + Okular::NormalizedRect rect() const override; + int id() const override; + QString name() const override; + QString uiName() const override; + bool isReadOnly() const override; + bool isVisible() const override; + + // inherited from Okular::FormFieldSignature + SignatureType signatureType() const override; + Okular::SignatureInfo* validate() const override; + + private: + Poppler::FormFieldSignature * m_field; + Okular::NormalizedRect m_rect; + int m_id; +}; + #endif diff --git a/generators/poppler/formfields.cpp b/generators/poppler/formfields.cpp --- a/generators/poppler/formfields.cpp +++ b/generators/poppler/formfields.cpp @@ -12,6 +12,8 @@ #include "core/action.h" +#include "pdfsignatureinfo.h" + #include #include @@ -367,4 +369,66 @@ return m_field->canBeSpellChecked(); } +PopplerFormFieldSignature::PopplerFormFieldSignature( Poppler::FormFieldSignature * field ) + : Okular::FormFieldSignature(), m_field( field ) +{ + m_rect = Okular::NormalizedRect::fromQRectF( m_field->rect() ); + m_id = m_field->id(); + SET_ACTIONS +} +PopplerFormFieldSignature::~PopplerFormFieldSignature() +{ + delete m_field; +} + +Okular::NormalizedRect PopplerFormFieldSignature::rect() const +{ + return m_rect; +} + +int PopplerFormFieldSignature::id() const +{ + return m_id; +} + +QString PopplerFormFieldSignature::name() const +{ + return m_field->name(); +} + +QString PopplerFormFieldSignature::uiName() const +{ + return m_field->uiName(); +} + +bool PopplerFormFieldSignature::isReadOnly() const +{ + return m_field->isReadOnly(); +} + +bool PopplerFormFieldSignature::isVisible() const +{ + return m_field->isVisible(); +} + +PopplerFormFieldSignature::SignatureType PopplerFormFieldSignature::signatureType() const +{ + switch ( m_field->signatureType() ) + { + case Poppler::FormFieldSignature::AdbePkcs7sha1: + return Okular::FormFieldSignature::AdbePkcs7sha1; + case Poppler::FormFieldSignature::AdbePkcs7detached: + return Okular::FormFieldSignature::AdbePkcs7detached; + case Poppler::FormFieldSignature::EtsiCAdESdetached: + return Okular::FormFieldSignature::EtsiCAdESdetached; + default: + return Okular::FormFieldSignature::UnknownType; + } +} + +Okular::SignatureInfo* PopplerFormFieldSignature::validate() const +{ + auto sigInfo = m_field->validate( Poppler::FormFieldSignature::ValidateVerifyCertificate ); + return ( new PopplerSignatureInfo( sigInfo ) ); +} diff --git a/generators/poppler/generator_pdf.cpp b/generators/poppler/generator_pdf.cpp --- a/generators/poppler/generator_pdf.cpp +++ b/generators/poppler/generator_pdf.cpp @@ -1857,6 +1857,10 @@ case Poppler::FormField::FormChoice: of = new PopplerFormFieldChoice( static_cast( f ) ); break; + case Poppler::FormField::FormSignature: { + of = new PopplerFormFieldSignature( static_cast( f ) ); + break; + } default: ; } if ( of ) diff --git a/generators/poppler/pdfsignatureinfo.h b/generators/poppler/pdfsignatureinfo.h new file mode 100644 --- /dev/null +++ b/generators/poppler/pdfsignatureinfo.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2018 by Chinmoy Ranjan Pradhan * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#ifndef _OKULAR_GENERATOR_PDF_SIGNATUREINFO_H_ +#define _OKULAR_GENERATOR_PDF_SIGNATUREINFO_H_ + +#include + +#include "core/signatureinfo.h" + +class PopplerSignatureInfoPrivate; + +class PopplerSignatureInfo : public Okular::SignatureInfo +{ + public: + PopplerSignatureInfo( const Poppler::SignatureValidationInfo &info ); + virtual ~PopplerSignatureInfo(); + + SignatureStatus signatureStatus() const override; + CertificateStatus certificateStatus() const override; + QString subjectCN() const override; + QString subjectDN() const override; + HashAlgorithm hashAlgorithm() const override; + QDateTime signingTime() const override; + QByteArray signature() const override; + QList signedRangeBounds() const override; + bool signsTotalDocument() const override; + + private: + QScopedPointer d_ptr; + Q_DECLARE_PRIVATE( PopplerSignatureInfo ) +}; + +#endif diff --git a/generators/poppler/pdfsignatureinfo.cpp b/generators/poppler/pdfsignatureinfo.cpp new file mode 100644 --- /dev/null +++ b/generators/poppler/pdfsignatureinfo.cpp @@ -0,0 +1,147 @@ +/*************************************************************************** + * Copyright (C) 2018 by Chinmoy Ranjan Pradhan * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +#include "pdfsignatureinfo.h" + +class PopplerSignatureInfoPrivate +{ + public: + QList rangeBounds; + QDateTime signingTime; + QByteArray signature; + QString subjectCN; + QString subjectDN; + int signatureStatus; + int certficateStatus; + int hashAlgorithm; + bool signsTotalDoc; +}; + +PopplerSignatureInfo::PopplerSignatureInfo( const Poppler::SignatureValidationInfo &info ) + : d_ptr( new PopplerSignatureInfoPrivate() ) +{ + Q_D( PopplerSignatureInfo ); + d->signatureStatus = info.signatureStatus(); + d->certficateStatus = info.certificateStatus(); + d->subjectCN = info.signerName(); + d->subjectDN = info.signerSubjectDN(); + d->hashAlgorithm = info.hashAlgorithm(); + d->signingTime = QDateTime::fromTime_t( info.signingTime() ); + d->signature = info.signature(); + d->rangeBounds = info.signedRangeBounds(); + d->signsTotalDoc = info.signsTotalDocument(); +} + +PopplerSignatureInfo::~PopplerSignatureInfo() +{ +} + +PopplerSignatureInfo::SignatureStatus PopplerSignatureInfo::signatureStatus() const +{ + Q_D( const PopplerSignatureInfo ); + switch ( d->signatureStatus ) + { + case Poppler::SignatureValidationInfo::SignatureValid: + return SignatureValid; + case Poppler::SignatureValidationInfo::SignatureInvalid: + return SignatureInvalid; + case Poppler::SignatureValidationInfo::SignatureDigestMismatch: + return SignatureDigestMismatch; + case Poppler::SignatureValidationInfo::SignatureDecodingError: + return SignatureDecodingError; + case Poppler::SignatureValidationInfo::SignatureGenericError: + return SignatureGenericError; + case Poppler::SignatureValidationInfo::SignatureNotFound: + return SignatureNotFound; + case Poppler::SignatureValidationInfo::SignatureNotVerified: + return SignatureNotVerified; + default: + return SignatureStatusUnknown; + } +} + +PopplerSignatureInfo::CertificateStatus PopplerSignatureInfo::certificateStatus() const +{ + Q_D( const PopplerSignatureInfo ); + switch ( d->certficateStatus ) + { + case Poppler::SignatureValidationInfo::CertificateTrusted: + return CertificateTrusted; + case Poppler::SignatureValidationInfo::CertificateUntrustedIssuer: + return CertificateUntrustedIssuer; + case Poppler::SignatureValidationInfo::CertificateUnknownIssuer: + return CertificateUnknownIssuer; + case Poppler::SignatureValidationInfo::CertificateRevoked: + return CertificateRevoked; + case Poppler::SignatureValidationInfo::CertificateExpired: + return CertificateExpired; + case Poppler::SignatureValidationInfo::CertificateGenericError: + return CertificateGenericError; + case Poppler::SignatureValidationInfo::CertificateNotVerified: + return CertificateNotVerified; + default: + return CertificateStatusUnknown; + } +} + +PopplerSignatureInfo::HashAlgorithm PopplerSignatureInfo::hashAlgorithm() const +{ + Q_D( const PopplerSignatureInfo ); + switch ( d->hashAlgorithm ) + { + case Poppler::SignatureValidationInfo::HashAlgorithmMd2: + return HashAlgorithmMd2; + case Poppler::SignatureValidationInfo::HashAlgorithmMd5: + return HashAlgorithmMd5; + case Poppler::SignatureValidationInfo::HashAlgorithmSha1: + return HashAlgorithmSha1; + case Poppler::SignatureValidationInfo::HashAlgorithmSha256: + return HashAlgorithmSha256; + case Poppler::SignatureValidationInfo::HashAlgorithmSha384: + return HashAlgorithmSha384; + case Poppler::SignatureValidationInfo::HashAlgorithmSha512: + return HashAlgorithmSha512; + case Poppler::SignatureValidationInfo::HashAlgorithmSha224: + return HashAlgorithmSha224; + default: + return HashAlgorithmUnknown; + } +} + +QString PopplerSignatureInfo::subjectCN() const +{ + Q_D( const PopplerSignatureInfo ); + return d->subjectCN; +} +QString PopplerSignatureInfo::subjectDN() const +{ + Q_D( const PopplerSignatureInfo ); + return d->subjectDN; +} + +QDateTime PopplerSignatureInfo::signingTime() const +{ + Q_D( const PopplerSignatureInfo ); + return d->signingTime; +} +QByteArray PopplerSignatureInfo::signature() const +{ + Q_D( const PopplerSignatureInfo ); + return d->signature; +} +QList PopplerSignatureInfo::signedRangeBounds() const +{ + Q_D( const PopplerSignatureInfo ); + return d->rangeBounds; +} +bool PopplerSignatureInfo::signsTotalDocument() const +{ + Q_D( const PopplerSignatureInfo ); + return d->signsTotalDoc; +}