Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / xmlsecurity / source / helper / pdfsignaturehelper.cxx
bloba54d121d97eb12995dde1630e897cc259b5594f2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <pdfsignaturehelper.hxx>
12 #include <memory>
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/security/DocumentSignatureInformation.hpp>
18 #include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
20 #include <tools/stream.hxx>
21 #include <unotools/ucbstreamhelper.hxx>
22 #include <vcl/filter/pdfdocument.hxx>
24 #include <pdfio/pdfdocument.hxx>
25 #include <tools/diagnose_ex.h>
27 using namespace ::com::sun::star;
29 PDFSignatureHelper::PDFSignatureHelper() = default;
31 bool PDFSignatureHelper::ReadAndVerifySignature(
32 const uno::Reference<io::XInputStream>& xInputStream)
34 if (!xInputStream.is())
36 SAL_WARN("xmlsecurity.helper", "input stream missing");
37 return false;
40 std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
41 vcl::filter::PDFDocument aDocument;
42 if (!aDocument.Read(*pStream))
44 SAL_WARN("xmlsecurity.helper", "failed to read the document");
45 return false;
48 std::vector<vcl::filter::PDFObjectElement*> aSignatures = aDocument.GetSignatureWidgets();
49 if (aSignatures.empty())
50 return true;
52 m_aSignatureInfos.clear();
54 for (size_t i = 0; i < aSignatures.size(); ++i)
56 SignatureInformation aInfo(i);
58 bool bLast = i == aSignatures.size() - 1;
59 if (!xmlsecurity::pdfio::ValidateSignature(*pStream, aSignatures[i], aInfo, bLast))
60 SAL_WARN("xmlsecurity.helper", "failed to determine digest match");
62 m_aSignatureInfos.push_back(aInfo);
65 return true;
68 SignatureInformations const& PDFSignatureHelper::GetSignatureInformations() const
70 return m_aSignatureInfos;
73 uno::Sequence<security::DocumentSignatureInformation>
74 PDFSignatureHelper::GetDocumentSignatureInformations(
75 const uno::Reference<xml::crypto::XSecurityEnvironment>& xSecEnv) const
77 uno::Sequence<security::DocumentSignatureInformation> aRet(m_aSignatureInfos.size());
79 for (size_t i = 0; i < m_aSignatureInfos.size(); ++i)
81 const SignatureInformation& rInternal = m_aSignatureInfos[i];
82 security::DocumentSignatureInformation& rExternal = aRet[i];
83 rExternal.SignatureIsValid
84 = rInternal.nStatus == xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED;
85 if (!rInternal.ouX509Certificate.isEmpty())
86 rExternal.Signer = xSecEnv->createCertificateFromAscii(rInternal.ouX509Certificate);
87 rExternal.PartialDocumentSignature = rInternal.bPartialDocumentSignature;
89 // Verify certificate.
90 if (rExternal.Signer.is())
92 try
94 rExternal.CertificateStatus = xSecEnv->verifyCertificate(rExternal.Signer, {});
96 catch (const uno::SecurityException&)
98 DBG_UNHANDLED_EXCEPTION("xmlsecurity.helper", "failed to verify certificate");
99 rExternal.CertificateStatus = security::CertificateValidity::INVALID;
102 else
103 rExternal.CertificateStatus = security::CertificateValidity::INVALID;
106 return aRet;
109 sal_Int32 PDFSignatureHelper::GetNewSecurityId() const { return m_aSignatureInfos.size(); }
111 void PDFSignatureHelper::SetX509Certificate(
112 const uno::Reference<security::XCertificate>& xCertificate)
114 m_xCertificate = xCertificate;
117 void PDFSignatureHelper::SetDescription(const OUString& rDescription)
119 m_aDescription = rDescription;
122 bool PDFSignatureHelper::Sign(const uno::Reference<io::XInputStream>& xInputStream, bool bAdES)
124 std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
125 vcl::filter::PDFDocument aDocument;
126 if (!aDocument.Read(*pStream))
128 SAL_WARN("xmlsecurity.helper", "failed to read the document");
129 return false;
132 if (!aDocument.Sign(m_xCertificate, m_aDescription, bAdES))
134 SAL_WARN("xmlsecurity.helper", "failed to sign");
135 return false;
138 uno::Reference<io::XStream> xStream(xInputStream, uno::UNO_QUERY);
139 std::unique_ptr<SvStream> pOutStream(utl::UcbStreamHelper::CreateStream(xStream, true));
140 if (!aDocument.Write(*pOutStream))
142 SAL_WARN("xmlsecurity.helper", "failed to write signed data");
143 return false;
146 return true;
149 bool PDFSignatureHelper::RemoveSignature(const uno::Reference<io::XInputStream>& xInputStream,
150 sal_uInt16 nPosition)
152 std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
153 vcl::filter::PDFDocument aDocument;
154 if (!aDocument.Read(*pStream))
156 SAL_WARN("xmlsecurity.helper", "failed to read the document");
157 return false;
160 if (!aDocument.RemoveSignature(nPosition))
162 SAL_WARN("xmlsecurity.helper", "failed to remove signature");
163 return false;
166 uno::Reference<io::XStream> xStream(xInputStream, uno::UNO_QUERY);
167 uno::Reference<io::XTruncate> xTruncate(xStream, uno::UNO_QUERY);
168 if (!xTruncate.is())
170 SAL_WARN("xmlsecurity.helper", "failed to truncate");
171 return false;
173 xTruncate->truncate();
174 std::unique_ptr<SvStream> pOutStream(utl::UcbStreamHelper::CreateStream(xStream, true));
175 if (!aDocument.Write(*pOutStream))
177 SAL_WARN("xmlsecurity.helper", "failed to write without signature");
178 return false;
181 return true;
184 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */