xmlsecurity PDF sign: handle AdES when writing SubFilter
Page 21 of "PAdES baseline signatures" specification from <http://www.etsi.org/deliver/etsi_en/319100_319199/31914201/01.01.01_60/en_31914201v010101p.pdf> says: "The Signature Dictionary shall contain a value of ETSI.CAdES.detached for the key SubFilter." So in case the UI has the adescompliant checkbox enabled, write that value instead of the Adobe default. Change-Id: I69e606a32fb09bebd5e9b25b32150d1b8672f544
This commit is contained in:
@@ -59,7 +59,7 @@ public:
|
||||
bool isXML(const OUString& rURI);
|
||||
SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 eStreamMode, bool bTempStream);
|
||||
/// Add a new signature, using xCert as a signing certificate, and rDescription as description.
|
||||
bool add(const css::uno::Reference<css::security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bXAdESCompliantIfODF);
|
||||
bool add(const css::uno::Reference<css::security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant);
|
||||
/// Remove signature at nPosition.
|
||||
void remove(sal_uInt16 nPosition);
|
||||
/// Read signatures from either a temp stream or the real storage.
|
||||
|
@@ -117,7 +117,7 @@ class XMLSECURITY_DLLPUBLIC PDFDocument
|
||||
/// Suggest a minimal, yet free signature ID to use for the next signature.
|
||||
sal_uInt32 GetNextSignature();
|
||||
/// Write the signature object as part of signing.
|
||||
sal_Int32 WriteSignatureObject(const OUString& rDescription, sal_uInt64& rLastByteRangeOffset, sal_Int64& rSignatureContentOffset);
|
||||
sal_Int32 WriteSignatureObject(const OUString& rDescription, bool bAdES, sal_uInt64& rLastByteRangeOffset, sal_Int64& rSignatureContentOffset);
|
||||
/// Write the appearance object as part of signing.
|
||||
sal_Int32 WriteAppearanceObject();
|
||||
/// Write the annot object as part of signing.
|
||||
@@ -162,7 +162,7 @@ public:
|
||||
/// Read elements from the start of the stream till its end.
|
||||
bool Read(SvStream& rStream);
|
||||
/// Sign the read document with xCertificate in the edit buffer.
|
||||
bool Sign(const css::uno::Reference<css::security::XCertificate>& xCertificate, const OUString& rDescription);
|
||||
bool Sign(const css::uno::Reference<css::security::XCertificate>& xCertificate, const OUString& rDescription, bool bAdES);
|
||||
/// Serializes the contents of the edit buffer.
|
||||
bool Write(SvStream& rStream);
|
||||
/// Get a list of signatures embedded into this document.
|
||||
|
@@ -43,7 +43,7 @@ public:
|
||||
/// Comment / reason to be used next time signing is performed.
|
||||
void SetDescription(const OUString& rDescription);
|
||||
/// Append a new signature at the end of xInputStream.
|
||||
bool Sign(const css::uno::Reference<css::io::XInputStream>& xInputStream);
|
||||
bool Sign(const css::uno::Reference<css::io::XInputStream>& xInputStream, bool bAdES);
|
||||
/// Remove the signature at nPosition (and all dependent signatures) from xInputStream.
|
||||
static bool RemoveSignature(const css::uno::Reference<css::io::XInputStream>& xInputStream, sal_uInt16 nPosition);
|
||||
};
|
||||
|
@@ -142,7 +142,7 @@ bool PDFSigningTest::sign(const OUString& rInURL, const OUString& rOutURL, size_
|
||||
// NSS failed to parse it's own profile or Windows has no certificates installed.
|
||||
return false;
|
||||
}
|
||||
CPPUNIT_ASSERT(aDocument.Sign(aCertificates[0], "test"));
|
||||
CPPUNIT_ASSERT(aDocument.Sign(aCertificates[0], "test", /*bAdES=*/true));
|
||||
SvFileStream aOutStream(rOutURL, StreamMode::WRITE | StreamMode::TRUNC);
|
||||
CPPUNIT_ASSERT(aDocument.Write(aOutStream));
|
||||
}
|
||||
|
@@ -232,7 +232,7 @@ SignatureStreamHelper DocumentSignatureManager::ImplOpenSignatureStream(sal_Int3
|
||||
return aHelper;
|
||||
}
|
||||
|
||||
bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bXAdESCompliantIfODF)
|
||||
bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>& xCert, const OUString& rDescription, sal_Int32& nSecurityId, bool bAdESCompliant)
|
||||
{
|
||||
if (!xCert.is())
|
||||
{
|
||||
@@ -255,7 +255,7 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
|
||||
getPDFSignatureHelper().SetX509Certificate(xCert);
|
||||
getPDFSignatureHelper().SetDescription(rDescription);
|
||||
uno::Reference<io::XInputStream> xInputStream(mxSignatureStream, uno::UNO_QUERY);
|
||||
if (!getPDFSignatureHelper().Sign(xInputStream))
|
||||
if (!getPDFSignatureHelper().Sign(xInputStream, bAdESCompliant))
|
||||
{
|
||||
SAL_WARN("xmlsecurity.helper", "PDFSignatureHelper::Sign() failed");
|
||||
return false;
|
||||
@@ -299,7 +299,7 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
|
||||
for (sal_Int32 n = 0; n < nElements; n++)
|
||||
{
|
||||
bool bBinaryMode = !isXML(aElements[n]);
|
||||
maSignatureHelper.AddForSigning(nSecurityId, aElements[n], aElements[n], bBinaryMode, bXAdESCompliantIfODF);
|
||||
maSignatureHelper.AddForSigning(nSecurityId, aElements[n], aElements[n], bBinaryMode, bAdESCompliant);
|
||||
}
|
||||
|
||||
maSignatureHelper.SetDateTime(nSecurityId, Date(Date::SYSTEM), tools::Time(tools::Time::SYSTEM));
|
||||
@@ -321,10 +321,10 @@ bool DocumentSignatureManager::add(const uno::Reference<security::XCertificate>&
|
||||
uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter, uno::UNO_QUERY_THROW);
|
||||
std::size_t nInfos = maCurrentSignatureInformations.size();
|
||||
for (std::size_t n = 0; n < nInfos; n++)
|
||||
XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n], bXAdESCompliantIfODF);
|
||||
XMLSignatureHelper::ExportSignature(xDocumentHandler, maCurrentSignatureInformations[n], bAdESCompliant);
|
||||
|
||||
// Create a new one...
|
||||
maSignatureHelper.CreateAndWriteSignature(xDocumentHandler, bXAdESCompliantIfODF);
|
||||
maSignatureHelper.CreateAndWriteSignature(xDocumentHandler, bAdESCompliant);
|
||||
|
||||
// That's it...
|
||||
XMLSignatureHelper::CloseDocumentHandler(xDocumentHandler);
|
||||
|
@@ -118,7 +118,7 @@ void PDFSignatureHelper::SetDescription(const OUString& rDescription)
|
||||
m_aDescription = rDescription;
|
||||
}
|
||||
|
||||
bool PDFSignatureHelper::Sign(const uno::Reference<io::XInputStream>& xInputStream)
|
||||
bool PDFSignatureHelper::Sign(const uno::Reference<io::XInputStream>& xInputStream, bool bAdES)
|
||||
{
|
||||
std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
|
||||
xmlsecurity::pdfio::PDFDocument aDocument;
|
||||
@@ -128,7 +128,7 @@ bool PDFSignatureHelper::Sign(const uno::Reference<io::XInputStream>& xInputStre
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aDocument.Sign(m_xCertificate, m_aDescription))
|
||||
if (!aDocument.Sign(m_xCertificate, m_aDescription, bAdES))
|
||||
{
|
||||
SAL_WARN("xmlsecurity.helper", "failed to sign");
|
||||
return false;
|
||||
|
@@ -357,7 +357,7 @@ sal_uInt32 PDFDocument::GetNextSignature()
|
||||
return nRet + 1;
|
||||
}
|
||||
|
||||
sal_Int32 PDFDocument::WriteSignatureObject(const OUString& rDescription, sal_uInt64& rLastByteRangeOffset, sal_Int64& rContentOffset)
|
||||
sal_Int32 PDFDocument::WriteSignatureObject(const OUString& rDescription, bool bAdES, sal_uInt64& rLastByteRangeOffset, sal_Int64& rContentOffset)
|
||||
{
|
||||
// Write signature object.
|
||||
sal_Int32 nSignatureId = m_aXRef.size();
|
||||
@@ -374,7 +374,11 @@ sal_Int32 PDFDocument::WriteSignatureObject(const OUString& rDescription, sal_uI
|
||||
OStringBuffer aContentFiller(MAX_SIGNATURE_CONTENT_LENGTH);
|
||||
comphelper::string::padToLength(aContentFiller, MAX_SIGNATURE_CONTENT_LENGTH, '0');
|
||||
aSigBuffer.append(aContentFiller.makeStringAndClear());
|
||||
aSigBuffer.append(">\n/Type/Sig/SubFilter/adbe.pkcs7.detached");
|
||||
aSigBuffer.append(">\n/Type/Sig/SubFilter");
|
||||
if (bAdES)
|
||||
aSigBuffer.append("/ETSI.CAdES.detached");
|
||||
else
|
||||
aSigBuffer.append("/adbe.pkcs7.detached");
|
||||
|
||||
// Time of signing.
|
||||
aSigBuffer.append(" /M (");
|
||||
@@ -941,14 +945,14 @@ void PDFDocument::WriteXRef(sal_uInt64 nXRefOffset, PDFReferenceElement* pRoot)
|
||||
}
|
||||
}
|
||||
|
||||
bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificate, const OUString& rDescription)
|
||||
bool PDFDocument::Sign(const uno::Reference<security::XCertificate>& xCertificate, const OUString& rDescription, bool bAdES)
|
||||
{
|
||||
m_aEditBuffer.Seek(STREAM_SEEK_TO_END);
|
||||
m_aEditBuffer.WriteCharPtr("\n");
|
||||
|
||||
sal_uInt64 nSignatureLastByteRangeOffset = 0;
|
||||
sal_Int64 nSignatureContentOffset = 0;
|
||||
sal_Int32 nSignatureId = WriteSignatureObject(rDescription, nSignatureLastByteRangeOffset, nSignatureContentOffset);
|
||||
sal_Int32 nSignatureId = WriteSignatureObject(rDescription, bAdES, nSignatureLastByteRangeOffset, nSignatureContentOffset);
|
||||
|
||||
sal_Int32 nAppearanceId = WriteAppearanceObject();
|
||||
|
||||
@@ -2021,7 +2025,7 @@ bool PDFDocument::ValidateSignature(SvStream& rStream, PDFObjectElement* pSignat
|
||||
}
|
||||
|
||||
auto pSubFilter = dynamic_cast<PDFNameElement*>(pValue->Lookup("SubFilter"));
|
||||
if (!pSubFilter || pSubFilter->GetValue() != "adbe.pkcs7.detached")
|
||||
if (!pSubFilter || (pSubFilter->GetValue() != "adbe.pkcs7.detached" && pSubFilter->GetValue() != "ETSI.CAdES.detached"))
|
||||
{
|
||||
SAL_WARN("xmlsecurity.pdfio", "PDFDocument::ValidateSignature: no or unsupported sub-filter");
|
||||
return false;
|
||||
|
@@ -136,7 +136,7 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(nArgc, pArgv)
|
||||
SAL_WARN("xmlsecurity.pdfio", "no signing certificates found");
|
||||
return 1;
|
||||
}
|
||||
if (!aDocument.Sign(aCertificates[0], "pdfverify"))
|
||||
if (!aDocument.Sign(aCertificates[0], "pdfverify", /*bAdES=*/true))
|
||||
{
|
||||
SAL_WARN("xmlsecurity.pdfio", "failed to sign");
|
||||
return 1;
|
||||
|
Reference in New Issue
Block a user