diff --git a/glib/demo/forms.c b/glib/demo/forms.c index 8fa8785..9ba6eb7 100644 --- a/glib/demo/forms.c +++ b/glib/demo/forms.c @@ -129,6 +129,7 @@ static void pgd_form_field_view_set_field (GtkWidget *field_view, PopplerFormField *field) { + PopplerSignatureInfo *psig_info; GtkWidget *table; PopplerAction *action; GEnumValue *enum_value; @@ -247,7 +248,23 @@ pgd_form_field_view_set_field (GtkWidget *field_view, g_free (text); } break; - case POPPLER_FORM_FIELD_SIGNATURE: + case POPPLER_FORM_FIELD_SIGNATURE: { + guint validation_flags = POPPLER_SIGNATURE_VERIFY_CERT; + + psig_info = poppler_form_field_signature_validate(field, validation_flags); + pgd_table_add_property (GTK_GRID (table), "Signer Name:", psig_info->signer_name ? psig_info->signer_name : "Signers name found", &row); + text = (gchar *) g_malloc(64); + strftime(text, 64, "%b %d %Y %H:%M:%S", localtime(&(psig_info->signing_time))); + pgd_table_add_property (GTK_GRID (table), "Signing Time:", text, &row); + pgd_table_add_property (GTK_GRID (table), "Signature Val Status:", + psig_info->sig_status == POPPLER_SIGNATURE_VALID ? "Signature is Valid" : "Signature is Invalid", &row); + pgd_table_add_property (GTK_GRID (table), "Certificate Val Status:", + psig_info->cert_status == POPPLER_CERTIFICATE_TRUSTED ? "Certificate is Trusted" : "Certificate cannot be Trusted", &row); + + poppler_signature_info_free(psig_info); + g_free (text); + } + break; case POPPLER_FORM_FIELD_UNKNOWN: break; default: diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc index 61d92e8..512cfd7 100644 --- a/glib/poppler-document.cc +++ b/glib/poppler-document.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -67,7 +68,7 @@ enum { PROP_PAGE_MODE, PROP_VIEWER_PREFERENCES, PROP_PERMISSIONS, - PROP_METADATA + PROP_METADATA, }; static void poppler_document_layers_free (PopplerDocument *document); @@ -1103,6 +1104,25 @@ poppler_document_is_linearized (PopplerDocument *document) } /** + * poppler_document_n_signatures: + * @document: A #PopplerDocument + * + * Returns how many digital signatures @document contains. + * PDF digital signatures ensure that the content hash not been altered since last edit and + * that it was produced by someone the user can trust + * + * Return value: The number of signatures found in the document + * + **/ +guint +poppler_document_n_signatures(PopplerDocument *document) +{ + g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), 0); + return document->doc->getSignatureWidgets().size(); +} + + +/** * poppler_document_get_page_layout: * @document: A #PopplerDocument * diff --git a/glib/poppler-document.h b/glib/poppler-document.h index a34e88c..81c7b26 100644 --- a/glib/poppler-document.h +++ b/glib/poppler-document.h @@ -227,6 +227,10 @@ PopplerDest *poppler_document_find_dest (PopplerDocument *do PopplerFormField *poppler_document_get_form_field (PopplerDocument *document, gint id); +/* Signatures */ + +guint poppler_document_n_signatures (PopplerDocument *document); + /* Interface for getting the Index of a poppler_document */ #define POPPLER_TYPE_INDEX_ITER (poppler_index_iter_get_type ()) GType poppler_index_iter_get_type (void) G_GNUC_CONST; diff --git a/glib/poppler-form-field.cc b/glib/poppler-form-field.cc index df184dd..8adb05d 100644 --- a/glib/poppler-form-field.cc +++ b/glib/poppler-form-field.cc @@ -689,3 +689,112 @@ poppler_form_field_choice_get_text (PopplerFormField *field) tmp = static_cast(field->widget)->getEditChoice (); return tmp ? _poppler_goo_string_to_utf8 (tmp) : NULL; } + +POPPLER_DEFINE_BOXED_TYPE (PopplerSignatureInfo, poppler_signature_info, + poppler_signature_info_copy, + poppler_signature_info_free) + +PopplerSignatureInfo * +poppler_signature_info_copy (PopplerSignatureInfo *sig_info) +{ + PopplerSignatureInfo *new_info; + + g_return_val_if_fail (sig_info != NULL, NULL); + + new_info = g_new0(PopplerSignatureInfo, 1); + *new_info = *sig_info; + + new_info->signer_name = g_strdup(sig_info->signer_name); + + return new_info; +} + +void +poppler_signature_info_free (PopplerSignatureInfo *siginfo) +{ + g_free((char *)siginfo->signer_name); + g_free(siginfo); +} + +/** +* poppler_form_field_signature_validate: +* +* @ signature_field: a #PopplerFormField that represents a signature annotation +* @ validation_flags: Combination of values of #PopplerSignatureValidationOptions using bitwise OR +* that specify your validation options +* +* Validates the cryptographic signature contained in @signature_field. +* Using validation_flags you can enable certificate validation (recommended) and +* force revalidation at the poppler core level +* +* Return value: a #PopplerSignatureInfo structure containing signature metadata and validation status +**/ + +PopplerSignatureInfo * +poppler_form_field_signature_validate (PopplerFormField *signature_field, guint validation_flags) +{ + if(poppler_form_field_get_field_type(signature_field) != POPPLER_FORM_FIELD_SIGNATURE) + return NULL; + + FormFieldSignature * sig_field = static_cast(signature_field->widget->getField()); + + SignatureInfo * sig_info = sig_field->validateSignature(validation_flags & POPPLER_SIGNATURE_VERIFY_CERT, + validation_flags & POPPLER_SIGNATURE_FORCE_REVALIDATION); + + PopplerSignatureInfo * poppler_sig_info; + poppler_sig_info = g_new0(PopplerSignatureInfo, 1); + switch(sig_info->getSignatureValStatus()) + { + case SIGNATURE_VALID: + poppler_sig_info->sig_status = POPPLER_SIGNATURE_VALID; + break; + case SIGNATURE_INVALID: + poppler_sig_info->sig_status = POPPLER_SIGNATURE_INVALID; + break; + case SIGNATURE_DIGEST_MISMATCH: + poppler_sig_info->sig_status = POPPLER_SIGNATURE_DIGEST_MISMATCH; + break; + case SIGNATURE_DECODING_ERROR: + poppler_sig_info->sig_status = POPPLER_SIGNATURE_DECODING_ERROR; + break; + case SIGNATURE_GENERIC_ERROR: + poppler_sig_info->sig_status = POPPLER_SIGNATURE_GENERIC_ERROR; + break; + case SIGNATURE_NOT_FOUND: + poppler_sig_info->sig_status = POPPLER_SIGNATURE_NOT_FOUND; + break; + case SIGNATURE_NOT_VERIFIED: + poppler_sig_info->sig_status = POPPLER_SIGNATURE_NOT_VERIFIED; + break; + } + + switch(sig_info->getCertificateValStatus()) + { + case CERTIFICATE_TRUSTED: + poppler_sig_info->cert_status = POPPLER_CERTIFICATE_TRUSTED; + break; + case CERTIFICATE_UNTRUSTED_ISSUER: + poppler_sig_info->cert_status = POPPLER_CERTIFICATE_UNTRUSTED_ISSUER; + break; + case CERTIFICATE_UNKNOWN_ISSUER: + poppler_sig_info->cert_status = POPPLER_CERTIFICATE_UNKNOWN_ISSUER; + break; + case CERTIFICATE_REVOKED: + poppler_sig_info->cert_status = POPPLER_CERTIFICATE_REVOKED; + break; + case CERTIFICATE_EXPIRED: + poppler_sig_info->cert_status = POPPLER_CERTIFICATE_EXPIRED; + break; + case CERTIFICATE_GENERIC_ERROR: + poppler_sig_info->cert_status = POPPLER_CERTIFICATE_GENERIC_ERROR; + break; + case CERTIFICATE_NOT_VERIFIED: + poppler_sig_info->cert_status = POPPLER_CERTIFICATE_NOT_VERIFIED; + break; + } + + poppler_sig_info->signer_name = g_strdup(sig_info->getSignerName()); + poppler_sig_info->signing_time = sig_info->getSigningTime(); + + return poppler_sig_info; +} diff --git a/glib/poppler-form-field.h b/glib/poppler-form-field.h index 898e0f6..8d4846f 100644 --- a/glib/poppler-form-field.h +++ b/glib/poppler-form-field.h @@ -29,6 +29,69 @@ G_BEGIN_DECLS #define POPPLER_FORM_FIELD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), POPPLER_TYPE_FORM_FIELD, PopplerFormField)) #define POPPLER_IS_FORM_FIELD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POPPLER_TYPE_FORM_FIELD)) + +/** + * PopplerSignatureStatus + * @POPPLER_SIGNATURE_VALID: signature is cryptographically valid + * @POPPLER_SIGNATURE_INVALID: signature is cryptographically invalid + * @POPPLER_SIGNATURE_DIGEST_MISMATCH: document content was changed after the signature was applied + * @POPPLER_SIGNATURE_DECODING_ERROR: signature CMS/PKCS7 structure is malformed + * @POPPLER_SIGNATURE_GENERIC_ERROR: failed to verify signature + * @POPPLER_SIGNATURE_NOT_FOUND: requested signature is not present in the document + * @POPPLER_SIGNATURE_NOT_VERIFIED: signature not yet verified + * + * Signature verification results + */ +typedef enum +{ + POPPLER_SIGNATURE_VALID, + POPPLER_SIGNATURE_INVALID, + POPPLER_SIGNATURE_DIGEST_MISMATCH, + POPPLER_SIGNATURE_DECODING_ERROR, + POPPLER_SIGNATURE_GENERIC_ERROR, + POPPLER_SIGNATURE_NOT_FOUND, + POPPLER_SIGNATURE_NOT_VERIFIED +} PopplerSignatureStatus; + +/** + * PopplerSignatureCertificateStatus + * @POPPLER_CERTIFICATE_TRUSTED: certificate is considered trusted + * @POPPLER_CERTIFICATE_UNTRUSTED_ISSUER: the issuer of this certificate has been marked as untrusted by the user + * @POPPLER_CERTIFICATE_UNKNOWN_ISSUER: this certificate trust chain has not finished in a trusted root certificate + * @POPPLER_CERTIFICATE_REVOKED: certificate was revoked by the issuing certificate authority + * @POPPLER_CERTIFICATE_EXPIRED: signing time is outside the validity bounds of this certificate + * @POPPLER_CERTIFICATE_GENERIC_ERROR: failed to verify certificate + * @POPPLER_CERTIFICATE_NOT_VERIFIED: certificate not yet verified + * + * Signature certificate verification results + */ + +typedef enum +{ + POPPLER_CERTIFICATE_TRUSTED, + POPPLER_CERTIFICATE_UNTRUSTED_ISSUER, + POPPLER_CERTIFICATE_UNKNOWN_ISSUER, + POPPLER_CERTIFICATE_REVOKED, + POPPLER_CERTIFICATE_EXPIRED, + POPPLER_CERTIFICATE_GENERIC_ERROR, + POPPLER_CERTIFICATE_NOT_VERIFIED +} PopplerSignatureCertificateStatus; + +typedef enum +{ + POPPLER_SIGNATURE_VERIFY_CERT = 1, + POPPLER_SIGNATURE_FORCE_REVALIDATION = 2 + +} PopplerSignatureValidationOptions; + +struct _PopplerSignatureInfo +{ + PopplerSignatureStatus sig_status; + PopplerSignatureCertificateStatus cert_status; + const char *signer_name; + time_t signing_time; +}; + typedef enum { POPPLER_FORM_FIELD_UNKNOWN, @@ -106,6 +169,13 @@ void poppler_form_field_choice_set_text (PopplerFormFie const gchar *text); gchar *poppler_form_field_choice_get_text (PopplerFormField *field); +/* Signature Field */ +#define POPPLER_TYPE_SIGNATURE_INFO (poppler_signature_info_get_type ()) +GType poppler_signature_info_get_type (void) G_GNUC_CONST; +PopplerSignatureInfo *poppler_form_field_signature_validate(PopplerFormField *field, guint flags); +PopplerSignatureInfo * poppler_signature_info_copy (PopplerSignatureInfo *siginfo); +void poppler_signature_info_free(PopplerSignatureInfo *siginfo); + G_END_DECLS #endif /* __POPPLER_FORM_FIELD_H__ */ diff --git a/glib/poppler-private.h b/glib/poppler-private.h index 9abdd7c..1a532b7 100644 --- a/glib/poppler-private.h +++ b/glib/poppler-private.h @@ -18,6 +18,7 @@ #include #include #include +#include #endif struct _PopplerDocument diff --git a/glib/poppler.h b/glib/poppler.h index 1e78050..7d6a245 100644 --- a/glib/poppler.h +++ b/glib/poppler.h @@ -204,6 +204,7 @@ typedef struct _PopplerQuadrilateral PopplerQuadrilateral; typedef struct _PopplerStructureElement PopplerStructureElement; typedef struct _PopplerStructureElementIter PopplerStructureElementIter; typedef struct _PopplerTextSpan PopplerTextSpan; +typedef struct _PopplerSignatureInfo PopplerSignatureInfo; /** * PopplerBackend: diff --git a/poppler/SignatureInfo.cc b/poppler/SignatureInfo.cc index 8f7ec45..9b4b201 100644 --- a/poppler/SignatureInfo.cc +++ b/poppler/SignatureInfo.cc @@ -38,7 +38,7 @@ SignatureInfo::SignatureInfo(SignatureValidationStatus sig_val_status, Certifica SignatureInfo::~SignatureInfo() { - free(signer_name); + free((char*)signer_name); } /* GETTERS */ @@ -53,7 +53,7 @@ CertificateValidationStatus SignatureInfo::getCertificateValStatus() return cert_status; } -char *SignatureInfo::getSignerName() +const char *SignatureInfo::getSignerName() { return signer_name; } @@ -75,9 +75,9 @@ void SignatureInfo::setCertificateValStatus(enum CertificateValidationStatus cer cert_status = cert_val_status; } -void SignatureInfo::setSignerName(char *signerName) +void SignatureInfo::setSignerName(const char *signerName) { - free(signer_name); + free((char*)signer_name); signer_name = signerName; } diff --git a/poppler/SignatureInfo.h b/poppler/SignatureInfo.h index 82b4ec4..3aafed9 100644 --- a/poppler/SignatureInfo.h +++ b/poppler/SignatureInfo.h @@ -46,14 +46,14 @@ public: /* GETTERS */ SignatureValidationStatus getSignatureValStatus(); CertificateValidationStatus getCertificateValStatus(); - char *getSignerName(); + const char *getSignerName(); time_t getSigningTime(); bool isSubfilterSupported() { return sig_subfilter_supported; } /* SETTERS */ void setSignatureValStatus(enum SignatureValidationStatus ); void setCertificateValStatus(enum CertificateValidationStatus ); - void setSignerName(char *); + void setSignerName(const char *); void setSigningTime(time_t); void setSubFilterSupport(bool isSupported) { sig_subfilter_supported = isSupported; } @@ -63,7 +63,7 @@ private: SignatureValidationStatus sig_status; CertificateValidationStatus cert_status; - char *signer_name; + const char *signer_name; time_t signing_time; bool sig_subfilter_supported; };