21#include <config_gpgme.h>
25#include <com/sun/star/embed/StorageFormats.hpp>
26#include <com/sun/star/embed/ElementModes.hpp>
27#include <com/sun/star/embed/XStorage.hpp>
28#include <com/sun/star/io/XTempFile.hpp>
29#include <com/sun/star/io/XTruncate.hpp>
30#include <com/sun/star/embed/XTransactedObject.hpp>
31#include <com/sun/star/xml/crypto/SEInitializer.hpp>
32#include <com/sun/star/lang/XServiceInfo.hpp>
33#include <com/sun/star/beans/PropertyValue.hpp>
34#include <com/sun/star/packages/manifest/ManifestReader.hpp>
35#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
36#include <com/sun/star/xml/sax/XWriter.hpp>
37#include <com/sun/star/frame/XModel.hpp>
41#include <rtl/ustrbuf.hxx>
43#include <tools/datetime.hxx>
56using namespace css::graphic;
57using namespace css::uno;
62 , maSignatureHelper(xContext)
63 , meSignatureMode(
eMode)
72 "DocumentSignatureManager::Init - mxSEInitializer already set!");
74 "DocumentSignatureManager::Init - mxSecurityContext already set!");
76 "DocumentSignatureManager::Init - mxGpgSEInitializer already set!");
105 SAL_WARN_IF(!bInit,
"xmlsecurity.comp",
"Error initializing security context!");
114bool DocumentSignatureManager::IsXAdESRelevant()
122 if (aStreamHelper.
nStorageFormat == embed::StorageFormats::OFOPXML)
147 uno::Reference<packages::manifest::XManifestReader> xReader
148 = packages::manifest::ManifestReader::create(
mxContext);
150 if (
mxStore->hasByName(
"META-INF"))
153 uno::Reference<embed::XStorage> xSubStore(
154 mxStore->openStorageElement(
"META-INF", embed::ElementModes::READ), UNO_SET_THROW);
156 uno::Reference<io::XInputStream>
xStream(
157 xSubStore->openStreamElement(
"manifest.xml", css::embed::ElementModes::READ),
175 bool bPropsAvailable =
false;
176 static constexpr OUStringLiteral sPropFullPath(
u"FullPath");
177 static constexpr OUStringLiteral sPropMediaType(
u"MediaType");
178 static constexpr OUStringLiteral sPropDigest(
u"Digest");
182 for (
const uno::Sequence<beans::PropertyValue>& entry : std::as_const(
m_manifest))
186 bool bEncrypted =
false;
187 for (
const beans::PropertyValue& prop : entry)
189 if (prop.Name == sPropFullPath)
190 prop.Value >>= sPath;
191 else if (prop.Name == sPropMediaType)
193 else if (prop.Name == sPropDigest)
198 bIsXML =
sMediaType ==
"text/xml" && !bEncrypted;
199 bPropsAvailable =
true;
204 if (!bPropsAvailable)
211 size_t nSep = rURI.rfind(
'.');
212 if (nSep != std::u16string_view::npos)
214 std::u16string_view aExt = rURI.substr(nSep + 1);
233 aHelper.nStorageFormat = embed::StorageFormats::OFOPXML;
237 if (nStreamOpenMode & embed::ElementModes::TRUNCATE)
241 if (
aHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
255 "empty temp. signature stream reference");
258 if (
aHelper.nStorageFormat == embed::StorageFormats::OFOPXML)
280 if (nStreamOpenMode & embed::ElementModes::TRUNCATE)
282 if (
aHelper.xSignatureStream.is()
283 &&
aHelper.nStorageFormat != embed::StorageFormats::OFOPXML)
285 uno::Reference<io::XTruncate> xTruncate(
aHelper.xSignatureStream, uno::UNO_QUERY_THROW);
286 xTruncate->truncate();
294 uno::Reference<io::XSeekable> xSeek(
aHelper.xSignatureStream, uno::UNO_QUERY_THROW);
302 const uno::Reference<security::XCertificate>& xCert,
303 const uno::Reference<xml::crypto::XXMLSecurityContext>& xSecurityContext,
304 const OUString& rDescription, sal_Int32& nSecurityId,
bool bAdESCompliant,
305 const OUString& rSignatureLineId,
const Reference<XGraphic>& xValidGraphic,
306 const Reference<XGraphic>& xInvalidGraphic)
310 SAL_WARN(
"xmlsecurity.helper",
"no certificate selected");
315 uno::Reference<lang::XServiceInfo> xServiceInfo(xSecurityContext, uno::UNO_QUERY);
316 if (xServiceInfo->getImplementationName()
317 ==
"com.sun.star.xml.security.gpg.XMLSecurityContext_GpgImpl")
322 SAL_WARN(
"xmlsecurity.helper",
"cannot sign pdfs with GPG keys");
330 OUStringBuffer aStrBuffer;
334 if (
auto pCertificate =
dynamic_cast<xmlsecurity::Certificate*
>(xCert.get()))
338 aKeyId =
aBuffer.makeStringAndClear();
342 "XCertificate implementation without an xmlsecurity::Certificate one");
345 xCert->getIssuerName());
350 if (aCertSerial.isEmpty())
352 SAL_WARN(
"xmlsecurity.helper",
"Error in Certificate, problem with serial number!");
362 uno::Reference<io::XInputStream> xInputStream(
mxSignatureStream, uno::UNO_QUERY);
365 SAL_WARN(
"xmlsecurity.helper",
"PDFSignatureHelper::Sign() failed");
375 OUStringBuffer aStrBuffer;
378 OUString aCertDigest;
381 if (
auto pCertificate =
dynamic_cast<xmlsecurity::Certificate*
>(xCert.get()))
385 aCertDigest =
aBuffer.makeStringAndClear();
387 eAlgorithmID = pCertificate->getSignatureMethodAlgorithm();
391 "XCertificate implementation without an xmlsecurity::Certificate one");
394 aStrBuffer.makeStringAndClear(), aCertDigest,
398 const uno::Sequence<uno::Reference<security::XCertificate>> aCertPath
399 = xSecurityContext->getSecurityEnvironment()->buildCertificatePath(xCert);
401 OUStringBuffer aStrBuffer;
402 for (uno::Reference<security::XCertificate>
const& rxCertificate : aCertPath)
405 OUString aString = aStrBuffer.makeStringAndClear();
413 for (OUString
const& rUri : aElements)
415 bool bBinaryMode = !
isXML(rUri);
422 if (!rSignatureLineId.isEmpty())
425 if (xValidGraphic.is())
428 if (xInvalidGraphic.is())
439 if (aStreamHelper.
nStorageFormat != embed::StorageFormats::OFOPXML)
441 uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.
xSignatureStream,
442 uno::UNO_QUERY_THROW);
443 uno::Reference<xml::sax::XWriter> xSaxWriter
447 uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter,
448 uno::UNO_QUERY_THROW);
450 for (std::size_t
n = 0;
n < nInfos;
n++)
481 uno::Reference<embed::XTransactedObject> xTransact(aStreamHelper.
xSignatureStorage,
484 uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.
xSignatureStream,
486 xOutputStream->closeOutput();
488 uno::Reference<io::XTempFile> xTempFile(aStreamHelper.
xSignatureStream, uno::UNO_QUERY);
490 "DocumentSignatureManager::add temporary storage at " << xTempFile->getUri());
502 uno::Reference<io::XInputStream> xInputStream(
mxSignatureStream, uno::UNO_QUERY);
505 SAL_WARN(
"xmlsecurity.helper",
"PDFSignatureHelper::RemoveSignature() failed");
520 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE,
true);
522 if (aStreamHelper.
nStorageFormat != embed::StorageFormats::OFOPXML)
524 uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.
xSignatureStream,
525 uno::UNO_QUERY_THROW);
526 uno::Reference<xml::sax::XWriter> xSaxWriter
529 uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter,
530 uno::UNO_QUERY_THROW);
532 for (std::size_t
n = 0;
n < nInfos; ++
n)
553 uno::Reference<embed::XTransactedObject> xTransact(aStreamHelper.
xSignatureStorage,
556 uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.
xSignatureStream,
558 xOutputStream->closeOutput();
560 uno::Reference<io::XTempFile> xTempFile(aStreamHelper.
xSignatureStream, uno::UNO_QUERY);
561 SAL_INFO(
"xmlsecurity.helper",
"DocumentSignatureManager::remove: temporary storage is at "
562 << xTempFile->getUri());
577 if (aStreamHelper.
nStorageFormat != embed::StorageFormats::OFOPXML
580 uno::Reference<io::XInputStream> xInputStream(aStreamHelper.
xSignatureStream,
584 else if (aStreamHelper.
nStorageFormat == embed::StorageFormats::OFOPXML
587 bCacheLastSignature);
594 if (!it.X509Datas.empty())
596 uno::Reference<xml::crypto::XSecurityEnvironment>
const xSecEnv(
607 uno::Reference<io::XInputStream> xInputStream(
mxSignatureStream, uno::UNO_QUERY);
623 embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE,
false);
626 && aStreamHelper.
nStorageFormat != embed::StorageFormats::OFOPXML)
629 uno::Reference<io::XOutputStream> xOutputStream(aStreamHelper.
xSignatureStream,
631 uno::Reference<xml::sax::XWriter> xSaxWriter
634 uno::Reference<xml::sax::XDocumentHandler> xDocumentHandler(xSaxWriter,
635 uno::UNO_QUERY_THROW);
637 for (std::size_t
n = 0;
n < nInfos; ++
n)
639 bXAdESCompliantIfODF);
644 && aStreamHelper.
nStorageFormat == embed::StorageFormats::OFOPXML)
649 if (nSignatureCount > 0)
658 mxStore->removeElement(
"_xmlsignatures");
661 for (std::size_t
i = 0;
i < nSignatureCount; ++
i)
678 : uno::Reference<xml::crypto::XSecurityEnvironment>();
681uno::Reference<xml::crypto::XSecurityEnvironment>
685 : uno::Reference<xml::crypto::XSecurityEnvironment>();
688uno::Reference<xml::crypto::XXMLSecurityContext>
const&
694uno::Reference<xml::crypto::XXMLSecurityContext>
const&
constexpr OUStringLiteral sMediaType
css::uno::Reference< css::xml::crypto::XXMLSecurityContext > const & getGpgSecurityContext() const
XMLSignatureHelper maSignatureHelper
void setModel(const css::uno::Reference< css::frame::XModel > &xModel)
~DocumentSignatureManager()
bool init()
Attempts to initialize the platform-specific crypto.
css::uno::Reference< css::xml::crypto::XXMLSecurityContext > mxSecurityContext
css::uno::Reference< css::xml::crypto::XSecurityEnvironment > getGpgSecurityEnvironment()
rtl::Reference< utl::TempFileFastService > mxTempSignatureStream
css::uno::Reference< css::xml::crypto::XXMLSecurityContext > mxGpgSecurityContext
void remove(sal_uInt16 nPosition)
Remove signature at nPosition.
std::unique_ptr< PDFSignatureHelper > mpPDFSignatureHelper
css::uno::Reference< css::uno::XComponentContext > mxContext
css::uno::Reference< css::embed::XStorage > mxTempSignatureStorage
Storage containing all OOXML signatures, unused for ODF.
XMLSignatureHelper & getSignatureHelper()
css::uno::Reference< css::io::XStream > mxSignatureStream
PDFSignatureHelper & getPDFSignatureHelper()
Lazy creation of PDF helper.
void write(bool bXAdESCompliantIfODF)
Write signatures back to the persistent storage.
css::uno::Reference< css::xml::crypto::XXMLSecurityContext > const & getSecurityContext() const
SignatureStreamHelper ImplOpenSignatureStream(sal_Int32 nStreamOpenMode, bool bTempStream)
SignatureInformations maCurrentSignatureInformations
css::uno::Reference< css::frame::XModel > mxModel
DocumentSignatureManager(const css::uno::Reference< css::uno::XComponentContext > &xContext, DocumentSignatureMode eMode)
css::uno::Reference< css::xml::crypto::XSEInitializer > mxSEInitializer
bool isXML(std::u16string_view rURI)
Checks if a particular stream is a valid xml stream.
css::uno::Reference< css::embed::XStorage > mxStore
void read(bool bUseTempStream, bool bCacheLastSignature=true)
Read signatures from either a temp stream or the real storage.
DocumentSignatureMode const meSignatureMode
css::uno::Reference< css::xml::crypto::XSecurityEnvironment > getSecurityEnvironment()
Get the security environment.
css::uno::Reference< css::xml::crypto::XSEInitializer > mxGpgSEInitializer
css::uno::Sequence< css::uno::Sequence< css::beans::PropertyValue > > m_manifest
bool add(const css::uno::Reference< css::security::XCertificate > &xCert, const css::uno::Reference< css::xml::crypto::XXMLSecurityContext > &xSecurityContext, const OUString &rDescription, sal_Int32 &nSecurityId, bool bAdESCompliant, const OUString &rSignatureLineId=OUString(), const css::uno::Reference< css::graphic::XGraphic > &xValidGraphic=css::uno::Reference< css::graphic::XGraphic >(), const css::uno::Reference< css::graphic::XGraphic > &xInvalidGraphic=css::uno::Reference< css::graphic::XGraphic >())
Add a new signature, using xCert as a signing certificate, and rDescription as description.
Handles signatures of a PDF file.
static bool RemoveSignature(const css::uno::Reference< css::io::XInputStream > &xInputStream, sal_uInt16 nPosition)
Remove the signature at nPosition (and all dependent signatures) from xInputStream.
void SetDescription(const OUString &rDescription)
Comment / reason to be used next time signing is performed.
SignatureInformations const & GetSignatureInformations() const
sal_Int32 GetNewSecurityId() const
Return the ID of the next created signature.
void SetX509Certificate(const css::uno::Reference< css::security::XCertificate > &xCertificate)
Certificate to be used next time signing is performed.
bool ReadAndVerifySignatureStorage(const css::uno::Reference< css::embed::XStorage > &xStorage, bool bCacheLastSignature=true)
Read and verify OOXML signatures.
void SetGpgCertificate(sal_Int32 nSecurityId, const OUString &ouGpgCertDigest, const OUString &ouGpgCert, const OUString &ouGpgOwner)
void AddEncapsulatedX509Certificate(const OUString &ouEncapsulatedX509Certificate)
SignatureInformations GetSignatureInformations() const
bool ReadAndVerifySignature(const css::uno::Reference< css::io::XInputStream > &xInputStream)
void StartMission(const css::uno::Reference< css::xml::crypto::XXMLSecurityContext > &xSecurityContext)
void SetSignatureLineInvalidGraphic(sal_Int32 nSecurityId, const css::uno::Reference< css::graphic::XGraphic > &xInvalidGraphic)
void SetX509Certificate(sal_Int32 nSecurityId, const OUString &ouX509IssuerName, const OUString &ouX509SerialNumber, const OUString &ouX509Cert, const OUString &ouX509CertDigest, svl::crypto::SignatureMethodAlgorithm eAlgorithmID)
sets data that describes the certificate.
void CreateAndWriteOOXMLSignature(const css::uno::Reference< css::embed::XStorage > &xRootStorage, const css::uno::Reference< css::embed::XStorage > &xSignatureStorage, int nSignatureIndex)
Given that xSignatureStorage is an OOXML _xmlsignatures storage, create and write a new signature.
void ExportSignatureContentTypes(const css::uno::Reference< css::embed::XStorage > &xStorage, int nSignatureCount)
Given that xStorage is an OOXML root storage, advertise signatures in its [Content_Types]....
void SetSignatureLineValidGraphic(sal_Int32 nSecurityId, const css::uno::Reference< css::graphic::XGraphic > &xValidGraphic)
sal_Int32 GetNewSecurityId()
std::vector< css::uno::Reference< css::security::XCertificate > > CheckAndUpdateSignatureInformation(css::uno::Reference< css::xml::crypto::XSecurityEnvironment > const &xSecEnv, SignatureInformation const &rInfo)
ImplVerifySignature calls this to figure out which X509Data is the signing certificate and update the...
void SetDescription(sal_Int32 nSecurityId, const OUString &rDescription)
static void ExportSignature(const css::uno::Reference< css::xml::sax::XDocumentHandler > &xDocumentHandler, const SignatureInformation &signatureInfo, bool bXAdESCompliantIfODF)
void SetSignatureLineId(sal_Int32 nSecurityId, const OUString &rSignatureLineId)
void CreateAndWriteSignature(const css::uno::Reference< css::xml::sax::XDocumentHandler > &xDocumentHandler, bool bXAdESCompliantIfODF)
static void CloseDocumentHandler(const css::uno::Reference< css::xml::sax::XDocumentHandler > &xDocumentHandler)
void ExportOOXMLSignature(const css::uno::Reference< css::embed::XStorage > &xRootStorage, const css::uno::Reference< css::embed::XStorage > &xSignatureStorage, const SignatureInformation &rInformation, int nSignatureIndex)
Similar to CreateAndWriteOOXMLSignature(), but used to write the signature to the persistent storage,...
void AddForSigning(sal_Int32 securityId, const OUString &uri, bool bBinary, bool bXAdESCompliantIfODF)
void ExportSignatureRelations(const css::uno::Reference< css::embed::XStorage > &xStorage, int nSignatureCount)
Given that xStorage is an OOXML _xmlsignatures storage, create origin.sigs and its relations.
css::uno::Reference< css::xml::sax::XWriter > CreateDocumentHandlerWithHeader(const css::uno::Reference< css::io::XOutputStream > &xOutputStream)
void EnsureSignaturesRelation(const css::uno::Reference< css::embed::XStorage > &xStorage, bool bAdd)
Adds or removes an OOXML digital signature relation to _rels/.rels if there wasn't any before.
void SetDateTime(sal_Int32 nSecurityId, const DateTime &rDateTime)
static void encode(OUStringBuffer &aStrBuffer, const css::uno::Sequence< sal_Int8 > &aPass)
static css::uno::Reference< css::embed::XStorage > GetStorageOfFormatFromStream(const OUString &aFormat, const css::uno::Reference< css::io::XStream > &xStream, sal_Int32 nStorageMode=css::embed::ElementModes::READWRITE, const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >(), bool bRepairStorage=false)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
void AppendContentTypes(const css::uno::Reference< css::embed::XStorage > &xStorage, std::vector< OUString > &rElements)
In case the storage is OOXML, prepend a leading '/' and append content type to the element URIs.
SignatureStreamHelper OpenSignatureStream(const css::uno::Reference< css::embed::XStorage > &rxStore, sal_Int32 nOpenMode, DocumentSignatureMode eDocSigMode)
bool equalsReferenceUriManifestPath(std::u16string_view rUri, std::u16string_view rPath)
std::vector< OUString > CreateElementList(const css::uno::Reference< css::embed::XStorage > &rxStore, DocumentSignatureMode eMode, const DocumentSignatureAlgorithm mode)
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
OUString bigIntegerToNumericString(const Sequence< sal_Int8 > &integer)
constexpr OUStringLiteral ZIP_STORAGE_FORMAT_STRING
css::uno::Reference< css::io::XStream > xSignatureStream
css::uno::Reference< css::embed::XStorage > xSignatureStorage
sal_Int32 nStorageFormat
If this is embed::StorageFormats::OFOPXML, then it's expected that xSignatureStream is an empty refer...
Reference< XModel > xModel
std::unique_ptr< char[]> aBuffer
XSECXMLSEC_DLLPUBLIC void deInitXmlSec()
XSECXMLSEC_DLLPUBLIC void initXmlSec()