From 9d8693a746836e4fba85b28339e4b58ab575c32d Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Tue, 5 Sep 2017 22:02:53 +0930 Subject: [PATCH 1/2] pdfsig: add -nssdir option to specify nssdb directory --- poppler/Form.cc | 12 ++++++------ poppler/Form.h | 7 ++++--- poppler/SignatureHandler.cc | 24 ++++++++++++++++-------- poppler/SignatureHandler.h | 6 +++--- qt5/src/poppler-form.cc | 4 ++-- utils/pdfsig.1 | 3 +++ utils/pdfsig.cc | 7 +++++-- 7 files changed, 39 insertions(+), 24 deletions(-) diff --git a/poppler/Form.cc b/poppler/Form.cc index 6d8b261c..2a9c3cf7 100644 --- a/poppler/Form.cc +++ b/poppler/Form.cc @@ -440,12 +440,12 @@ FormWidgetSignature::FormWidgetSignature(PDFDoc *docA, Object *aobj, unsigned nu type = formSignature; } -SignatureInfo *FormWidgetSignature::validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime) +SignatureInfo *FormWidgetSignature::validateSignature(const char *nssDir, bool doVerifyCert, bool forceRevalidation, time_t validationTime) { - return static_cast(field)->validateSignature(doVerifyCert, forceRevalidation, validationTime); + return static_cast(field)->validateSignature(nssDir, doVerifyCert, forceRevalidation, validationTime); } -GBool FormWidgetSignature::signDocument(const char* certNickname, const char* digestName, +GBool FormWidgetSignature::signDocument(const char *nssDir, const char* certNickname, const char* digestName, const char* password, const char* reason) { GBool ok = gFalse; @@ -453,7 +453,7 @@ GBool FormWidgetSignature::signDocument(const char* certNickname, const char* di { unsigned char tmp_buffer[4]; memcpy(tmp_buffer, "PDF", 4); - SignatureHandler sigHandler(certNickname, SignatureHandler::getHashOidTag(digestName)); + SignatureHandler sigHandler(nssDir, certNickname, SignatureHandler::getHashOidTag(digestName)); sigHandler.updateHash(tmp_buffer, 4); // calculate a signature over tmp_buffer with the certificate to get its size GooString* tmpSignature = sigHandler.signDetached(password); @@ -1778,7 +1778,7 @@ void FormWidgetSignature::setSignatureType(FormSignatureType type) static_cast(field)->signature_type = type; } -SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime) +SignatureInfo *FormFieldSignature::validateSignature(const char *nssDir, bool doVerifyCert, bool forceRevalidation, time_t validationTime) { #ifdef ENABLE_NSS3 if (!signature_info->isSubfilterSupported()) { @@ -1811,7 +1811,7 @@ SignatureInfo *FormFieldSignature::validateSignature(bool doVerifyCert, bool for const int signature_len = signature->getLength(); unsigned char *signatureuchar = (unsigned char *)gmalloc(signature_len); memcpy(signatureuchar, signature->getCString(), signature_len); - SignatureHandler signature_handler(signatureuchar, signature_len); + SignatureHandler signature_handler(nssDir, signatureuchar, signature_len); Goffset fileLength = doc->getBaseStream()->getLength(); for (int i = 0; i < arrayLen/2; i++) { diff --git a/poppler/Form.h b/poppler/Form.h index 60e5622d..b1edfbf5 100644 --- a/poppler/Form.h +++ b/poppler/Form.h @@ -264,7 +264,7 @@ public: void setSignatureType(FormSignatureType type); // Use -1 for now as validationTime - SignatureInfo *validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime); + SignatureInfo *validateSignature(const char *nssDir, bool doVerifyCert, bool forceRevalidation, time_t validationTime); // creates or replaces the dictionary name "V" in the signature dictionary and // fills it with the fields of the signature; the field "Contents" is the signature @@ -272,7 +272,8 @@ public: // document except for the signature itself; this byte range is specified in the // field "ByteRange" in the dictionary "V" // return success - GBool signDocument(const char *certNickname, const char *digestName, + GBool signDocument(const char *nssDir, + const char *certNickname, const char *digestName, const char *password, const char *reason = nullptr); // returns a list with the boundaries of the signed ranges @@ -534,7 +535,7 @@ public: FormFieldSignature(PDFDoc *docA, Object *dict, const Ref& ref, FormField *parent, std::set *usedParents); // Use -1 for now as validationTime - SignatureInfo *validateSignature(bool doVerifyCert, bool forceRevalidation, time_t validationTime); + SignatureInfo *validateSignature(const char *nssDir, bool doVerifyCert, bool forceRevalidation, time_t validationTime); ~FormFieldSignature(); Object* getByteRange() { return &byte_range; } diff --git a/poppler/SignatureHandler.cc b/poppler/SignatureHandler.cc index c2f3ef8f..6bcf7c0c 100644 --- a/poppler/SignatureHandler.cc +++ b/poppler/SignatureHandler.cc @@ -149,14 +149,22 @@ GooString *SignatureHandler::getDefaultFirefoxCertDB_Linux() /** * Initialise NSS */ -void SignatureHandler::init_nss() +void SignatureHandler::init_nss(const char *nssDir) { + SECStatus status; + GooString *certDBPath = getDefaultFirefoxCertDB_Linux(); - if (certDBPath == NULL) { - NSS_Init("sql:/etc/pki/nssdb"); + if (nssDir) { + status = NSS_Init(nssDir); + } else if (certDBPath) { + status = NSS_Init(certDBPath->getCString()); } else { - NSS_Init(certDBPath->getCString()); + status = NSS_Init("sql:/etc/pki/nssdb"); + } + if (status != SECSuccess) { + fprintf(stderr, "NSS_Init failedl: %s\n", PR_ErrorToString(PORT_GetError(), PR_LANGUAGE_I_DEFAULT)); } + //Make sure NSS root certificates module is loaded SECMOD_AddNewModule("Root Certs", "libnssckbi.so", 0, 0); @@ -164,7 +172,7 @@ void SignatureHandler::init_nss() } -SignatureHandler::SignatureHandler(unsigned char *p7, int p7_length) +SignatureHandler::SignatureHandler(const char *nssDir, unsigned char *p7, int p7_length) : hash_context(NULL), CMSMessage(NULL), CMSSignedData(NULL), @@ -172,7 +180,7 @@ SignatureHandler::SignatureHandler(unsigned char *p7, int p7_length) signing_cert(nullptr), temp_certs(NULL) { - init_nss(); + init_nss(nssDir); CMSitem.data = p7; CMSitem.len = p7_length; CMSMessage = CMS_MessageCreate(&CMSitem); @@ -183,7 +191,7 @@ SignatureHandler::SignatureHandler(unsigned char *p7, int p7_length) } } -SignatureHandler::SignatureHandler(const char *certNickname, SECOidTag digestAlgTag) +SignatureHandler::SignatureHandler(const char *nssDir, const char *certNickname, SECOidTag digestAlgTag) : hash_length(digestLength(digestAlgTag)), digest_alg_tag(digestAlgTag), CMSitem(), @@ -194,7 +202,7 @@ SignatureHandler::SignatureHandler(const char *certNickname, SECOidTag digestAlg signing_cert(nullptr), temp_certs(nullptr) { - init_nss(); + init_nss(nssDir); CMSMessage = NSS_CMSMessage_Create(nullptr); signing_cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), certNickname); hash_context = HASH_Create(HASH_GetHashTypeByOidTag(digestAlgTag)); diff --git a/poppler/SignatureHandler.h b/poppler/SignatureHandler.h index 0f4e3b1f..c844c9cb 100644 --- a/poppler/SignatureHandler.h +++ b/poppler/SignatureHandler.h @@ -33,8 +33,8 @@ class SignatureHandler { public: - SignatureHandler(unsigned char *p7, int p7_length); - SignatureHandler(const char *certNickname, SECOidTag digestAlgTag); + SignatureHandler(const char *nssDir, unsigned char *p7, int p7_length); + SignatureHandler(const char *nssDir, const char *certNickname, SECOidTag digestAlgTag); ~SignatureHandler(); time_t getSigningTime(); char * getSignerName(); @@ -67,7 +67,7 @@ private: SignatureHandler(const SignatureHandler &); SignatureHandler& operator=(const SignatureHandler &); - void init_nss(); + void init_nss(const char *nssDir); GooString * getDefaultFirefoxCertDB_Linux(); unsigned int digestLength(SECOidTag digestAlgId); diff --git a/qt5/src/poppler-form.cc b/qt5/src/poppler-form.cc index 7c02ccb3..afb0b02f 100644 --- a/qt5/src/poppler-form.cc +++ b/qt5/src/poppler-form.cc @@ -652,7 +652,7 @@ bool FormFieldSignature::sign(const QString& certNickname, const QString& passwo } if (!reason.isEmpty()) rs = reason.toUtf8().constData(); - GBool ok = fws->signDocument(name, digest, pw, rs); + GBool ok = fws->signDocument(nullptr, name, digest, pw, rs); free(name); free(pw); return ok; @@ -667,7 +667,7 @@ SignatureValidationInfo FormFieldSignature::validate(int opt, const QDateTime& v { FormWidgetSignature* fws = static_cast(m_formData->fm); const time_t validationTimeT = validationTime.isValid() ? validationTime.toTime_t() : -1; - SignatureInfo* si = fws->validateSignature(opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation, validationTimeT); + SignatureInfo* si = fws->validateSignature(nullptr, opt & ValidateVerifyCertificate, opt & ValidateForceRevalidation, validationTimeT); SignatureValidationInfoPrivate* priv = new SignatureValidationInfoPrivate; switch (si->getSignatureValStatus()) { case SIGNATURE_VALID: diff --git a/utils/pdfsig.1 b/utils/pdfsig.1 index ef2e0c3d..8d09d6c1 100644 --- a/utils/pdfsig.1 +++ b/utils/pdfsig.1 @@ -24,6 +24,9 @@ The NSS Certificate database in the default Firefox profile. 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. +.TP .B \-nocert Do not validate the certificate. .TP diff --git a/utils/pdfsig.cc b/utils/pdfsig.cc index 24a4fb5b..a4d83e63 100644 --- a/utils/pdfsig.cc +++ b/utils/pdfsig.cc @@ -86,6 +86,7 @@ char *getReadableTime(time_t unix_time) return time_str; } +static GooString nssDir; static GBool printVersion = gFalse; static GBool printHelp = gFalse; static GBool dontVerifyCert = gFalse; @@ -97,6 +98,8 @@ static char digestName[256] = "SHA256"; static char reason[256] = ""; static const ArgDesc argDesc[] = { + {"-nssdir", argGooString, &nssDir, 0, + "don't perform certificate validation"}, {"-nocert", argFlag, &dontVerifyCert, 0, "don't perform certificate validation"}, {"-sign", argInt, &signatureNumber, 0, @@ -194,7 +197,7 @@ int main(int argc, char *argv[]) fws->setSignatureType(ETSI_CAdES_detached); const char* pw = (strlen(password) == 0) ? nullptr : password; const char* rs = (strlen(reason) == 0) ? nullptr : reason; - if (fws->signDocument(certNickname, digestName, pw, rs)) { + if (fws->signDocument(nssDir.getCString(), certNickname, digestName, pw, rs)) { GooString* out = new GooString(argv[2]); exitCode = doc->saveAs(out); delete out; @@ -214,7 +217,7 @@ int main(int argc, char *argv[]) } for (unsigned int i = 0; i < sigCount; i++) { - sig_info = sig_widgets.at(i)->validateSignature(!dontVerifyCert, false, -1 /* now */); + sig_info = sig_widgets.at(i)->validateSignature(nssDir.getCString(), !dontVerifyCert, false, -1 /* now */); printf("Signature #%u:\n", i+1); printf(" - Signer Certificate Common Name: %s\n", sig_info->getSignerName()); printf(" - Signer full Distinguished Name: %s\n", sig_info->getSubjectDN()); -- 2.11.0