1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <pdfsignaturehelper.hxx>
14 #include <com/sun/star/io/XTruncate.hpp>
15 #include <com/sun/star/security/CertificateValidity.hpp>
16 #include <com/sun/star/uno/SecurityException.hpp>
17 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
19 #include <comphelper/sequence.hxx>
20 #include <tools/stream.hxx>
21 #include <unotools/ucbstreamhelper.hxx>
23 #include <pdfio/pdfdocument.hxx>
25 using namespace ::com::sun::star
;
27 PDFSignatureHelper::PDFSignatureHelper() = default;
29 bool PDFSignatureHelper::ReadAndVerifySignature(const uno::Reference
<io::XInputStream
>& xInputStream
)
31 if (!xInputStream
.is())
33 SAL_WARN("xmlsecurity.helper", "input stream missing");
37 std::unique_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(xInputStream
, true));
38 vcl::filter::PDFDocument aDocument
;
39 if (!aDocument
.Read(*pStream
))
41 SAL_WARN("xmlsecurity.helper", "failed to read the document");
45 std::vector
<vcl::filter::PDFObjectElement
*> aSignatures
= aDocument
.GetSignatureWidgets();
46 if (aSignatures
.empty())
49 m_aSignatureInfos
.clear();
51 for (size_t i
= 0; i
< aSignatures
.size(); ++i
)
53 SignatureInformation
aInfo(i
);
55 bool bLast
= i
== aSignatures
.size() - 1;
56 if (!xmlsecurity::pdfio::ValidateSignature(*pStream
, aSignatures
[i
], aInfo
, bLast
))
57 SAL_WARN("xmlsecurity.helper", "failed to determine digest match");
59 m_aSignatureInfos
.push_back(aInfo
);
65 SignatureInformations
PDFSignatureHelper::GetSignatureInformations() const
67 return m_aSignatureInfos
;
70 uno::Sequence
<security::DocumentSignatureInformation
> PDFSignatureHelper::GetDocumentSignatureInformations(const uno::Reference
<xml::crypto::XSecurityEnvironment
>& xSecEnv
) const
72 uno::Sequence
<security::DocumentSignatureInformation
> aRet(m_aSignatureInfos
.size());
74 for (size_t i
= 0; i
< m_aSignatureInfos
.size(); ++i
)
76 const SignatureInformation
& rInternal
= m_aSignatureInfos
[i
];
77 security::DocumentSignatureInformation
& rExternal
= aRet
[i
];
78 rExternal
.SignatureIsValid
= rInternal
.nStatus
== xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED
;
79 if (!rInternal
.ouX509Certificate
.isEmpty())
80 rExternal
.Signer
= xSecEnv
->createCertificateFromAscii(rInternal
.ouX509Certificate
);
81 rExternal
.PartialDocumentSignature
= rInternal
.bPartialDocumentSignature
;
83 // Verify certificate.
84 if (rExternal
.Signer
.is())
88 rExternal
.CertificateStatus
= xSecEnv
->verifyCertificate(rExternal
.Signer
, {});
90 catch (const uno::SecurityException
& rException
)
92 SAL_WARN("xmlsecurity.helper", "failed to verify certificate: " << rException
);
93 rExternal
.CertificateStatus
= security::CertificateValidity::INVALID
;
97 rExternal
.CertificateStatus
= security::CertificateValidity::INVALID
;
103 sal_Int32
PDFSignatureHelper::GetNewSecurityId() const
105 return m_aSignatureInfos
.size();
108 void PDFSignatureHelper::SetX509Certificate(const uno::Reference
<security::XCertificate
>& xCertificate
)
110 m_xCertificate
= xCertificate
;
113 void PDFSignatureHelper::SetDescription(const OUString
& rDescription
)
115 m_aDescription
= rDescription
;
118 bool PDFSignatureHelper::Sign(const uno::Reference
<io::XInputStream
>& xInputStream
, bool bAdES
)
120 std::unique_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(xInputStream
, true));
121 vcl::filter::PDFDocument aDocument
;
122 if (!aDocument
.Read(*pStream
))
124 SAL_WARN("xmlsecurity.helper", "failed to read the document");
128 if (!aDocument
.Sign(m_xCertificate
, m_aDescription
, bAdES
))
130 SAL_WARN("xmlsecurity.helper", "failed to sign");
134 uno::Reference
<io::XStream
> xStream(xInputStream
, uno::UNO_QUERY
);
135 std::unique_ptr
<SvStream
> pOutStream(utl::UcbStreamHelper::CreateStream(xStream
, true));
136 if (!aDocument
.Write(*pOutStream
))
138 SAL_WARN("xmlsecurity.helper", "failed to write signed data");
145 bool PDFSignatureHelper::RemoveSignature(const uno::Reference
<io::XInputStream
>& xInputStream
, sal_uInt16 nPosition
)
147 std::unique_ptr
<SvStream
> pStream(utl::UcbStreamHelper::CreateStream(xInputStream
, true));
148 vcl::filter::PDFDocument aDocument
;
149 if (!aDocument
.Read(*pStream
))
151 SAL_WARN("xmlsecurity.helper", "failed to read the document");
155 if (!aDocument
.RemoveSignature(nPosition
))
157 SAL_WARN("xmlsecurity.helper", "failed to remove signature");
161 uno::Reference
<io::XStream
> xStream(xInputStream
, uno::UNO_QUERY
);
162 uno::Reference
<io::XTruncate
> xTruncate(xStream
, uno::UNO_QUERY
);
165 SAL_WARN("xmlsecurity.helper", "failed to truncate");
168 xTruncate
->truncate();
169 std::unique_ptr
<SvStream
> pOutStream(utl::UcbStreamHelper::CreateStream(xStream
, true));
170 if (!aDocument
.Write(*pOutStream
))
172 SAL_WARN("xmlsecurity.helper", "failed to write without signature");
179 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */