poppler/SignatureHandler.cc | 56 +++++++++++++++++++++++++++++--------------- poppler/SignatureHandler.h | 9 ++++--- poppler/SignatureInfo.cc | 4 +-- utils/pdfsig.1 | 15 ++++++++++- utils/pdfsig.cc | 12 +++++++-- 5 files changed, 68 insertions(+), 28 deletions(-)
New commits: commit 7486e4995d66f1a8676f3e65e408e8cdab049f6b Author: Albert Astals Cid <[email protected]> Date: Wed Jan 16 22:56:42 2019 +0100 pdfsig: add -nssdir option Contains code inspired in code by Hans-Ulrich Jüttner and Adrian Johnson diff --git a/poppler/SignatureHandler.cc b/poppler/SignatureHandler.cc index f616afbb..18033b48 100644 --- a/poppler/SignatureHandler.cc +++ b/poppler/SignatureHandler.cc @@ -45,7 +45,7 @@ unsigned int SignatureHandler::digestLength(SECOidTag digestAlgId) char *SignatureHandler::getSignerName() { - if (!CMSSignerInfo) + if (!CMSSignerInfo || !NSS_IsInitialized()) return nullptr; CERTCertificate *cert = NSS_CMSSignerInfo_GetSigningCertificate(CMSSignerInfo, CERT_GetDefaultCertDB()); @@ -182,8 +182,7 @@ std::unique_ptr<X509CertificateInfo> SignatureHandler::getCertificateInfo() cons return certInfo; } - -GooString *SignatureHandler::getDefaultFirefoxCertDB_Linux() +static GooString *getDefaultFirefoxCertDB_Linux() { GooString * finalPath = nullptr; DIR *toSearchIn; @@ -215,27 +214,45 @@ GooString *SignatureHandler::getDefaultFirefoxCertDB_Linux() /** * Initialise NSS */ -void SignatureHandler::init_nss() +void SignatureHandler::setNSSDir(const GooString &nssDir) { - GooString *certDBPath = getDefaultFirefoxCertDB_Linux(); + static bool setNssDirCalled = false; + + if (NSS_IsInitialized() && nssDir.getLength() > 0) { + error(errInternal, 0, "You need to call setNSSDir before signature validation related operations happen"); + return; + } + + if (setNssDirCalled) + return; + + setNssDirCalled = true; + bool initSuccess = false; - if (certDBPath == nullptr) { - initSuccess = (NSS_Init("sql:/etc/pki/nssdb") == SECSuccess); + if (nssDir.getLength() > 0) { + initSuccess = (NSS_Init(nssDir.c_str()) == SECSuccess); } else { - initSuccess = (NSS_Init(certDBPath->c_str()) == SECSuccess); - } - if (!initSuccess) { - GooString homeNssDb(getenv("HOME")); - homeNssDb.append("/.pki/nssdb"); - initSuccess = (NSS_Init(homeNssDb.c_str()) == SECSuccess); + GooString *certDBPath = getDefaultFirefoxCertDB_Linux(); + if (certDBPath == nullptr) { + initSuccess = (NSS_Init("sql:/etc/pki/nssdb") == SECSuccess); + } else { + initSuccess = (NSS_Init(certDBPath->c_str()) == SECSuccess); + } if (!initSuccess) { - NSS_NoDB_Init(nullptr); + GooString homeNssDb(getenv("HOME")); + homeNssDb.append("/.pki/nssdb"); + initSuccess = (NSS_Init(homeNssDb.c_str()) == SECSuccess); + if (!initSuccess) { + NSS_NoDB_Init(nullptr); + } } + delete certDBPath; } - //Make sure NSS root certificates module is loaded - SECMOD_AddNewModule("Root Certs", "libnssckbi.so", 0, 0); - delete certDBPath; + if (initSuccess) { + //Make sure NSS root certificates module is loaded + SECMOD_AddNewModule("Root Certs", "libnssckbi.so", 0, 0); + } } @@ -246,7 +263,7 @@ SignatureHandler::SignatureHandler(unsigned char *p7, int p7_length) CMSSignerInfo(nullptr), temp_certs(nullptr) { - init_nss(); + setNSSDir({}); CMSitem.data = p7; CMSitem.len = p7_length; CMSMessage = CMS_MessageCreate(&CMSitem); @@ -377,6 +394,9 @@ SignatureValidationStatus SignatureHandler::validateSignature() if (!CMSSignedData) return SIGNATURE_GENERIC_ERROR; + if (!NSS_IsInitialized()) + return SIGNATURE_GENERIC_ERROR; + digest_buffer = (unsigned char *)PORT_Alloc(hash_length); unsigned int result_len = 0; diff --git a/poppler/SignatureHandler.h b/poppler/SignatureHandler.h index f49d4286..40ca990c 100644 --- a/poppler/SignatureHandler.h +++ b/poppler/SignatureHandler.h @@ -49,13 +49,16 @@ public: CertificateValidationStatus validateCertificate(time_t validation_time); std::unique_ptr<X509CertificateInfo> getCertificateInfo() const; + // Initializes the NSS dir with the custom given directory + // calling it with an empty string means use the default firefox db, /etc/pki/nssdb, ~/.pki/nssdb + // If you don't want a custom NSS dir and the default entries are fine for you, not calling this function is fine + // If wanted, this has to be called before doing signature validation calls + static void setNSSDir(const GooString &nssDir); + private: SignatureHandler(const SignatureHandler &); SignatureHandler& operator=(const SignatureHandler &); - void init_nss(); - - GooString * getDefaultFirefoxCertDB_Linux(); unsigned int digestLength(SECOidTag digestAlgId); NSSCMSMessage *CMS_MessageCreate(SECItem * cms_item); NSSCMSSignedData *CMS_SignedDataCreate(NSSCMSMessage * cms_msg); diff --git a/poppler/SignatureInfo.cc b/poppler/SignatureInfo.cc index b48ce146..3ab6f91f 100644 --- a/poppler/SignatureInfo.cc +++ b/poppler/SignatureInfo.cc @@ -7,7 +7,7 @@ // Copyright 2015 André Guerreiro <[email protected]> // Copyright 2015 André Esser <[email protected]> // Copyright 2017 Hans-Ulrich Jüttner <[email protected]> -// Copyright 2017, 2018 Albert Astals Cid <[email protected]> +// Copyright 2017-2019 Albert Astals Cid <[email protected]> // Copyright 2018 Chinmoy Ranjan Pradhan <[email protected]> // Copyright 2018 Oliver Sander <[email protected]> // @@ -133,7 +133,7 @@ void SignatureInfo::setSignerName(char *signerName) void SignatureInfo::setSubjectDN(const char *subjectDN) { free(subject_dn); - subject_dn = strdup(subjectDN); + subject_dn = subjectDN ? strdup(subjectDN) : nullptr; } void SignatureInfo::setLocation(const char *loc) diff --git a/utils/pdfsig.1 b/utils/pdfsig.1 index 0a5cc62d..3567e96c 100644 --- a/utils/pdfsig.1 +++ b/utils/pdfsig.1 @@ -15,13 +15,23 @@ the time and date of the signature, the hash algorithm used for signing, the type of the signature as stated in the PDF and the signed ranges with a statement wether the total document is signed. .PP -The signer certificate validation uses the trusted certificates stored in the following locations: +The signer certificate validation uses the trusted certificates stored in the +Network Security Services (NSS) Database. The NSS Database is searched for in the following locations: .IP \(bu -The NSS Certificate database in the default Firefox profile. +If the \-nssdir option is specified, the directory specified by this option. +.IP \(bu +The NSS Certificate database in the default Firefox profile. i.e. $HOME/.mozilla/firefox/*.default. .IP \(bu The NSS Certificate database in /etc/pki/nssdb. .SH OPTIONS .TP +.B \-nssdir "[prefix]directory" +Specify the database directory containing the certificate and key +database files. See certutil(1) -d option for details of the +prefix. If not specified the other search locations described in +.B DESCRIPTION +are used. +.TP .B \-nocert Do not validate the certificate. .TP @@ -52,3 +62,4 @@ and copyright 2005-2015 The Poppler Developers - http://poppler.freedesktop.org .BR pdftotext (1) .BR pdfseparate (1), .BR pdfunite (1) +.BR certutil (1) diff --git a/utils/pdfsig.cc b/utils/pdfsig.cc index 82c0616b..64299690 100644 --- a/utils/pdfsig.cc +++ b/utils/pdfsig.cc @@ -6,10 +6,10 @@ // // Copyright 2015 André Guerreiro <[email protected]> // Copyright 2015 André Esser <[email protected]> -// Copyright 2015, 2017, 2018 Albert Astals Cid <[email protected]> +// Copyright 2015, 2017-2019 Albert Astals Cid <[email protected]> // Copyright 2016 Markus Kilås <[email protected]> -// Copyright 2017 Hans-Ulrich Jüttner <[email protected]> -// Copyright 2017 Adrian Johnson <[email protected]> +// Copyright 2017, 2019 Hans-Ulrich Jüttner <[email protected]> +// Copyright 2017, 2019 Adrian Johnson <[email protected]> // Copyright 2018 Chinmoy Ranjan Pradhan <[email protected]> // Copyright 2019 Alexey Pavlov <[email protected]> // @@ -33,6 +33,7 @@ #include "PDFDocFactory.h" #include "Error.h" #include "GlobalParams.h" +#include "SignatureHandler.h" #include "SignatureInfo.h" #include "Win32Console.h" #include "numberofcharacters.h" @@ -118,12 +119,15 @@ static void dumpSignature(int sig_num, int sigCount, FormWidgetSignature *sig_wi delete path; } +static GooString nssDir; static bool printVersion = false; static bool printHelp = false; static bool dontVerifyCert = false; static bool dumpSignatures = false; static const ArgDesc argDesc[] = { + {"-nssdir", argGooString, &nssDir, 0, + "path to directory of libnss3 database"}, {"-nocert", argFlag, &dontVerifyCert, 0, "don't perform certificate validation"}, {"-dump", argFlag, &dumpSignatures, 0, @@ -171,6 +175,8 @@ int main(int argc, char *argv[]) fileName = new GooString(argv[argc - 1]); + SignatureHandler::setNSSDir(nssDir); + // open PDF file doc = PDFDocFactory().createPDFDoc(*fileName, nullptr, nullptr); _______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
