xmlsecurity: add initial PDFSignatureHelper

This splits most of the PDF signature code out of the pdfverify
executable, and puts it into the xmlsecurity library instead.

The PDFSignatureHelper now attempts to verify PDF signatures, and code
in sdext / sfx2 also calls it (even if PDF is not a ZIP-based format).

Change-Id: I7b8b3ac9c976e4ea4f3796b1cda07c8a2c97bd02
Reviewed-on: https://gerrit.libreoffice.org/29751
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Tested-by: Jenkins <ci@libreoffice.org>
This commit is contained in:
Miklos Vajna 2016-10-13 10:37:02 +02:00
parent 3461c9d7a2
commit 0f613adbfa
10 changed files with 1678 additions and 1500 deletions

View File

@ -31,7 +31,7 @@
<value>com.sun.star.comp.Writer.XmlFilterAdaptor</value>
</prop>
<prop oor:name="Flags" oor:type="oor:string-list">
<value>3RDPARTYFILTER ALIEN IMPORT PREFERRED</value>
<value>3RDPARTYFILTER ALIEN IMPORT PREFERRED SUPPORTSSIGNING</value>
</prop>
<prop oor:name="Type" oor:type="xs:string">
<value>pdf_Portable_Document_Format</value>

View File

@ -102,6 +102,8 @@
#include <sfx2/saveastemplatedlg.hxx>
#include <memory>
#include <cppuhelper/implbase.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/streamwrap.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::lang;
@ -1291,7 +1293,7 @@ uno::Sequence< security::DocumentSignatureInformation > SfxObjectShell::ImplAnal
uno::Reference< security::XDocumentDigitalSignatures > xLocSigner = xSigner;
bool bSupportsSigning = GetMedium() && GetMedium()->GetFilter() && GetMedium()->GetFilter()->GetSupportsSigning();
if (GetMedium() && !GetMedium()->GetName().isEmpty() && (IsOwnStorageFormat(*GetMedium()) || bSupportsSigning) && GetMedium()->GetStorage().is())
if (GetMedium() && !GetMedium()->GetName().isEmpty() && ((IsOwnStorageFormat(*GetMedium()) && GetMedium()->GetStorage().is()) || bSupportsSigning))
{
try
{
@ -1315,8 +1317,22 @@ uno::Sequence< security::DocumentSignatureInformation > SfxObjectShell::ImplAnal
aResult = xLocSigner->verifyScriptingContentSignatures( GetMedium()->GetZipStorageToSign_Impl(),
uno::Reference< io::XInputStream >() );
else
aResult = xLocSigner->verifyDocumentContentSignatures( GetMedium()->GetZipStorageToSign_Impl(),
uno::Reference< io::XInputStream >() );
{
if (GetMedium()->GetStorage().is())
{
// Something ZIP-based.
aResult = xLocSigner->verifyDocumentContentSignatures( GetMedium()->GetZipStorageToSign_Impl(),
uno::Reference< io::XInputStream >() );
}
else
{
// Not ZIP-based, e.g. PDF.
SvStream* pStream = utl::UcbStreamHelper::CreateStream(GetMedium()->GetName(), StreamMode::READ);
uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(*pStream));
uno::Reference<io::XInputStream> xInputStream(xStream, uno::UNO_QUERY);
aResult = xLocSigner->verifyDocumentContentSignatures(uno::Reference<embed::XStorage>(), xInputStream);
}
}
}
catch( css::uno::Exception& )
{

View File

@ -13,29 +13,18 @@ $(eval $(call gb_Executable_use_sdk_api,pdfverify))
$(eval $(call gb_Executable_set_include,pdfverify,\
$$(INCLUDE) \
-I$(SRCDIR)/xmlsecurity/inc \
))
$(eval $(call gb_Executable_use_libraries,pdfverify,\
comphelper \
sal \
tl \
xmlsecurity \
))
$(eval $(call gb_Executable_add_exception_objects,pdfverify,\
xmlsecurity/source/pdfio/pdfverify \
))
ifeq ($(OS)-$(COM),WNT-MSC)
$(eval $(call gb_Executable_add_defs,pdfverify,\
-DXMLSEC_CRYPTO_MSCRYPTO \
))
else
$(eval $(call gb_Executable_add_defs,pdfverify,\
-DXMLSEC_CRYPTO_NSS \
))
$(eval $(call gb_Executable_use_externals,pdfverify,\
nss3 \
))
endif
# vim:set noet sw=4 ts=4:

View File

@ -57,12 +57,27 @@ $(eval $(call gb_Library_add_exception_objects,xmlsecurity,\
xmlsecurity/source/helper/documentsignaturemanager \
xmlsecurity/source/helper/ooxmlsecparser \
xmlsecurity/source/helper/ooxmlsecexporter \
xmlsecurity/source/helper/pdfsignaturehelper \
xmlsecurity/source/helper/xmlsignaturehelper2 \
xmlsecurity/source/helper/xmlsignaturehelper \
xmlsecurity/source/helper/xsecctl \
xmlsecurity/source/helper/xsecparser \
xmlsecurity/source/helper/xsecsign \
xmlsecurity/source/helper/xsecverify \
xmlsecurity/source/pdfio/pdfdocument \
))
ifeq ($(OS)-$(COM),WNT-MSC)
$(eval $(call gb_Library_add_defs,xmlsecurity,\
-DXMLSEC_CRYPTO_MSCRYPTO \
))
else
$(eval $(call gb_Library_add_defs,xmlsecurity,\
-DXMLSEC_CRYPTO_NSS \
))
$(eval $(call gb_Library_use_externals,xmlsecurity,\
nss3 \
))
endif
# vim: set noet sw=4 ts=4:

View File

@ -0,0 +1,70 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#ifndef INCLUDED_XMLSECURITY_INC_PDFIO_PDFDOCUMENT_HXX
#define INCLUDED_XMLSECURITY_INC_PDFIO_PDFDOCUMENT_HXX
#include <vector>
#include <tools/stream.hxx>
#include <xmlsecuritydllapi.h>
namespace xmlsecurity
{
namespace pdfio
{
class PDFTrailerElement;
class PDFObjectElement;
/// A byte range in a PDF file.
class PDFElement
{
public:
virtual bool Read(SvStream& rStream) = 0;
virtual ~PDFElement() { }
};
/// In-memory representation of an on-disk PDF document.
class XMLSECURITY_DLLPUBLIC PDFDocument
{
/// This vector owns all elements.
std::vector< std::unique_ptr<PDFElement> > m_aElements;
// List of object offsets we know.
std::vector<size_t> m_aXRef;
PDFTrailerElement* m_pTrailer;
static int AsHex(char ch);
public:
PDFDocument();
PDFDocument& operator=(const PDFDocument&) = delete;
PDFDocument(const PDFDocument&) = delete;
static OString ReadKeyword(SvStream& rStream);
static size_t FindStartXRef(SvStream& rStream);
void ReadXRef(SvStream& rStream);
static void SkipWhitespace(SvStream& rStream);
size_t GetObjectOffset(size_t nIndex) const;
const std::vector< std::unique_ptr<PDFElement> >& GetElements();
std::vector<PDFObjectElement*> GetPages();
bool Read(SvStream& rStream);
std::vector<PDFObjectElement*> GetSignatureWidgets();
/// Return value is about if we can determine a result, bDigestMatch is about the actual result.
static bool ValidateSignature(SvStream& rStream, PDFObjectElement* pSignature, bool& bDigestMatch);
};
} // namespace pdfio
} // namespace xmlsecurity
#endif // INCLUDED_XMLSECURITY_INC_PDFIO_PDFDOCUMENT_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@ -0,0 +1,33 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#ifndef INCLUDED_XMLSECURITY_INC_PDFSIGNATUREHELPER_HXX
#define INCLUDED_XMLSECURITY_INC_PDFSIGNATUREHELPER_HXX
#include <xmlsecuritydllapi.h>
#include <vector>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/security/DocumentSignatureInformation.hpp>
/// Handles signatures of a PDF file.
class XMLSECURITY_DLLPUBLIC PDFSignatureHelper
{
std::vector<css::security::DocumentSignatureInformation> m_aSignatureInfos;
public:
bool ReadAndVerifySignature(const css::uno::Reference<css::io::XInputStream>& xInputStream);
css::uno::Sequence<css::security::DocumentSignatureInformation> GetDocumentSignatureInformations();
};
#endif // INCLUDED_XMLSECURITY_INC_PDFSIGNATUREHELPER_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@ -24,6 +24,7 @@
#include <macrosecurity.hxx>
#include <biginteger.hxx>
#include <global.hrc>
#include <pdfsignaturehelper.hxx>
#include <sax/tools/converter.hxx>
@ -259,6 +260,14 @@ DocumentDigitalSignatures::ImplVerifySignatures(
{
if (!rxStorage.is())
{
if (xSignStream.is())
{
// Something not ZIP-based, try PDF.
PDFSignatureHelper aSignatureHelper;
if (aSignatureHelper.ReadAndVerifySignature(xSignStream))
return aSignatureHelper.GetDocumentSignatureInformations();
}
SAL_WARN( "xmlsecurity.comp", "Error, no XStorage provided");
return Sequence<css::security::DocumentSignatureInformation>();
}

View File

@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <pdfsignaturehelper.hxx>
#include <memory>
#include <comphelper/sequence.hxx>
#include <tools/stream.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <pdfio/pdfdocument.hxx>
using namespace ::com::sun::star;
bool PDFSignatureHelper::ReadAndVerifySignature(const uno::Reference<io::XInputStream>& xInputStream)
{
if (!xInputStream.is())
{
SAL_WARN("xmlsecurity.helper", "input stream missing");
return false;
}
std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
xmlsecurity::pdfio::PDFDocument aDocument;
if (!aDocument.Read(*pStream))
{
SAL_WARN("xmlsecurity.helper", "failed to read the document");
return false;
}
std::vector<xmlsecurity::pdfio::PDFObjectElement*> aSignatures = aDocument.GetSignatureWidgets();
if (aSignatures.empty())
return true;
for (size_t i = 0; i < aSignatures.size(); ++i)
{
security::DocumentSignatureInformation aInfo;
bool bDigestMatch;
if (!xmlsecurity::pdfio::PDFDocument::ValidateSignature(*pStream, aSignatures[i], bDigestMatch))
{
SAL_WARN("xmlsecurity.helper", "failed to determine digest match");
continue;
}
aInfo.SignatureIsValid = bDigestMatch;
m_aSignatureInfos.push_back(aInfo);
}
return true;
}
uno::Sequence<security::DocumentSignatureInformation> PDFSignatureHelper::GetDocumentSignatureInformations()
{
return comphelper::containerToSequence(m_aSignatureInfos);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff