Commit 7486e499 authored by Albert Astals Cid's avatar Albert Astals Cid Committed by Albert Astals Cid

pdfsig: add -nssdir option

Contains code inspired in code by Hans-Ulrich Jüttner and Adrian Johnson
parent 8076bc66
......@@ -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;
......
......@@ -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);
......
......@@ -7,7 +7,7 @@
// Copyright 2015 André Guerreiro <aguerreiro1985@gmail.com>
// Copyright 2015 André Esser <bepandre@hotmail.com>
// Copyright 2017 Hans-Ulrich Jüttner <huj@froreich-bioscientia.de>
// Copyright 2017, 2018 Albert Astals Cid <aacid@kde.org>
// Copyright 2017-2019 Albert Astals Cid <aacid@kde.org>
// Copyright 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@protonmail.com>
// Copyright 2018 Oliver Sander <oliver.sander@tu-dresden.de>
//
......@@ -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)
......
......@@ -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)
......@@ -6,10 +6,10 @@
//
// Copyright 2015 André Guerreiro <aguerreiro1985@gmail.com>
// Copyright 2015 André Esser <bepandre@hotmail.com>
// Copyright 2015, 2017, 2018 Albert Astals Cid <aacid@kde.org>
// Copyright 2015, 2017-2019 Albert Astals Cid <aacid@kde.org>
// Copyright 2016 Markus Kilås <digital@markuspage.com>
// Copyright 2017 Hans-Ulrich Jüttner <huj@froreich-bioscientia.de>
// Copyright 2017 Adrian Johnson <ajohnson@redneon.com>
// Copyright 2017, 2019 Hans-Ulrich Jüttner <huj@froreich-bioscientia.de>
// Copyright 2017, 2019 Adrian Johnson <ajohnson@redneon.com>
// Copyright 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@protonmail.com>
// Copyright 2019 Alexey Pavlov <alexpux@gmail.com>
//
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment