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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "xsecctl.hxx"
23 #include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp>
24 #include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
25 #include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp>
26 #include <com/sun/star/xml/crypto/sax/XBlockerMonitor.hpp>
27 #include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp>
28 #include <com/sun/star/xml/crypto/sax/XSignatureCreationResultBroadcaster.hpp>
29 #include <com/sun/star/io/XActiveDataSource.hpp>
30 #include <com/sun/star/embed/StorageFormats.hpp>
35 using namespace com::sun::star
;
36 namespace cssu
= com::sun::star::uno
;
37 namespace cssl
= com::sun::star::lang
;
38 namespace cssxc
= com::sun::star::xml::crypto
;
39 namespace cssxs
= com::sun::star::xml::sax
;
41 /* xml security framework components */
42 #define SIGNATURECREATOR_COMPONENT "com.sun.star.xml.crypto.sax.SignatureCreator"
44 /* protected: for signature generation */
45 OUString
XSecController::createId()
48 rtl_createUuid( aSeq
, nullptr, true );
52 for (sal_uInt8 i
: aSeq
)
54 length
+= sprintf(str
+length
, "%04x", i
);
57 return OUString::createFromAscii(str
);
60 cssu::Reference
< cssxc::sax::XReferenceResolvedListener
> XSecController::prepareSignatureToWrite(
61 InternalSignatureInformation
& internalSignatureInfor
,
62 sal_Int32 nStorageFormat
,
63 bool bXAdESCompliantIfODF
)
65 sal_Int32 nSecurityId
= internalSignatureInfor
.signatureInfor
.nSecurityId
;
66 SignatureReferenceInformations
& vReferenceInfors
= internalSignatureInfor
.signatureInfor
.vSignatureReferenceInfors
;
68 sal_Int32 nIdOfSignatureElementCollector
;
69 cssu::Reference
< cssxc::sax::XReferenceResolvedListener
> xReferenceResolvedListener
;
71 nIdOfSignatureElementCollector
=
72 m_xSAXEventKeeper
->addSecurityElementCollector( cssxc::sax::ElementMarkPriority_AFTERMODIFY
, true );
74 m_xSAXEventKeeper
->setSecurityId(nIdOfSignatureElementCollector
, nSecurityId
);
77 * create a SignatureCreator
79 cssu::Reference
< cssl::XMultiComponentFactory
> xMCF( mxCtx
->getServiceManager() );
80 xReferenceResolvedListener
.set(
81 xMCF
->createInstanceWithContext(SIGNATURECREATOR_COMPONENT
, mxCtx
),
84 cssu::Reference
<cssl::XInitialization
> xInitialization(xReferenceResolvedListener
, cssu::UNO_QUERY
);
86 cssu::Sequence
<cssu::Any
> args(5);
87 args
[0] = cssu::makeAny(OUString::number(nSecurityId
));
88 args
[1] = cssu::makeAny(m_xSAXEventKeeper
);
89 args
[2] = cssu::makeAny(OUString::number(nIdOfSignatureElementCollector
));
91 //for nss, the internal module is used for signing, which needs to be improved later
92 args
[3] = cssu::makeAny(m_xSecurityContext
->getSecurityEnvironment());
94 args
[4] = cssu::makeAny(m_xXMLSignature
);
95 xInitialization
->initialize(args
);
97 sal_Int32 nBlockerId
= m_xSAXEventKeeper
->addBlocker();
98 m_xSAXEventKeeper
->setSecurityId(nBlockerId
, nSecurityId
);
100 cssu::Reference
<cssxc::sax::XBlockerMonitor
> xBlockerMonitor(xReferenceResolvedListener
, cssu::UNO_QUERY
);
101 xBlockerMonitor
->setBlockerId(nBlockerId
);
103 cssu::Reference
< cssxc::sax::XSignatureCreationResultBroadcaster
>
104 xSignatureCreationResultBroadcaster(xReferenceResolvedListener
, cssu::UNO_QUERY
);
106 xSignatureCreationResultBroadcaster
->addSignatureCreationResultListener( this );
108 cssu::Reference
<cssxc::sax::XReferenceResolvedBroadcaster
>
109 xReferenceResolvedBroadcaster
113 xReferenceResolvedBroadcaster
->addReferenceResolvedListener(
114 nIdOfSignatureElementCollector
,
115 xReferenceResolvedListener
);
117 cssu::Reference
<cssxc::sax::XReferenceCollector
> xReferenceCollector
118 (xReferenceResolvedListener
, cssu::UNO_QUERY
);
121 int size
= vReferenceInfors
.size();
122 sal_Int32 nReferenceCount
= 0;
124 for(i
=0; i
<size
; ++i
)
126 sal_Int32 keeperId
= internalSignatureInfor
.vKeeperIds
[i
];
130 m_xSAXEventKeeper
->setSecurityId(keeperId
, nSecurityId
);
131 xReferenceResolvedBroadcaster
->addReferenceResolvedListener( keeperId
, xReferenceResolvedListener
);
132 xReferenceCollector
->setReferenceId( keeperId
);
137 xReferenceCollector
->setReferenceCount( nReferenceCount
);
140 * adds all URI binding
142 cssu::Reference
<cssxc::XUriBinding
> xUriBinding
143 (xReferenceResolvedListener
, cssu::UNO_QUERY
);
145 for(i
=0; i
<size
; ++i
)
147 const SignatureReferenceInformation
& refInfor
= vReferenceInfors
[i
];
149 cssu::Reference
< css::io::XInputStream
> xInputStream
150 = getObjectInputStream( refInfor
.ouURI
);
152 if (xInputStream
.is())
154 xUriBinding
->setUriBinding(refInfor
.ouURI
,xInputStream
);
158 cssu::Reference
<cssxc::sax::XKeyCollector
> keyCollector (xReferenceResolvedListener
, cssu::UNO_QUERY
);
159 keyCollector
->setKeyId(0);
161 const sal_Int32 digestID
= bXAdESCompliantIfODF
? cssxc::DigestID::SHA256
: cssxc::DigestID::SHA1
;
163 if (nStorageFormat
!= embed::StorageFormats::OFOPXML
)
165 internalSignatureInfor
.signatureInfor
.ouSignatureId
= createId();
166 internalSignatureInfor
.signatureInfor
.ouPropertyId
= createId();
167 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, internalSignatureInfor
.signatureInfor
.ouPropertyId
, -1 );
170 if (bXAdESCompliantIfODF
)
172 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idSignedProperties", -1);
176 if (!internalSignatureInfor
.signatureInfor
.ouDescription
.isEmpty())
178 // Only mention the hash of the description in the signature if it's non-empty.
179 internalSignatureInfor
.signatureInfor
.ouDescriptionPropertyId
= createId();
180 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, internalSignatureInfor
.signatureInfor
.ouDescriptionPropertyId
, -1);
186 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idPackageObject", -1);
188 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idOfficeObject", -1);
190 internalSignatureInfor
.addReference(SignatureReferenceType::SAMEDOCUMENT
, digestID
, "idSignedProperties", -1);
195 * replace both digestValues and signatueValue to " "
197 for(i
=0; i
<size
; ++i
)
199 SignatureReferenceInformation
& refInfor
= vReferenceInfors
[i
];
200 refInfor
.ouDigestValue
= " ";
203 internalSignatureInfor
.signatureInfor
.ouSignatureValue
= " ";
205 return xReferenceResolvedListener
;
208 void XSecController::signAStream( sal_Int32 securityId
, const OUString
& uri
, const OUString
& /*objectURL*/, bool isBinary
, bool bXAdESCompliantIfODF
)
210 const SignatureReferenceType type
= isBinary
? SignatureReferenceType::BINARYSTREAM
: SignatureReferenceType::XMLSTREAM
;
211 const sal_Int32 digestID
= bXAdESCompliantIfODF
? cssxc::DigestID::SHA256
: cssxc::DigestID::SHA1
;
213 int index
= findSignatureInfor( securityId
);
217 InternalSignatureInformation
isi(securityId
, nullptr);
218 isi
.addReference(type
, digestID
, uri
, -1);
219 m_vInternalSignatureInformations
.push_back( isi
);
223 m_vInternalSignatureInformations
[index
].addReference(type
, digestID
, uri
, -1);
227 void XSecController::setX509Certificate(
228 sal_Int32 nSecurityId
,
229 const OUString
& ouX509IssuerName
,
230 const OUString
& ouX509SerialNumber
,
231 const OUString
& ouX509Cert
,
232 const OUString
& ouX509CertDigest
)
234 int index
= findSignatureInfor( nSecurityId
);
238 InternalSignatureInformation
isi(nSecurityId
, nullptr);
239 isi
.signatureInfor
.ouX509IssuerName
= ouX509IssuerName
;
240 isi
.signatureInfor
.ouX509SerialNumber
= ouX509SerialNumber
;
241 isi
.signatureInfor
.ouX509Certificate
= ouX509Cert
;
242 isi
.signatureInfor
.ouCertDigest
= ouX509CertDigest
;
243 m_vInternalSignatureInformations
.push_back( isi
);
247 SignatureInformation
&si
248 = m_vInternalSignatureInformations
[index
].signatureInfor
;
249 si
.ouX509IssuerName
= ouX509IssuerName
;
250 si
.ouX509SerialNumber
= ouX509SerialNumber
;
251 si
.ouX509Certificate
= ouX509Cert
;
252 si
.ouCertDigest
= ouX509CertDigest
;
256 void XSecController::setDate(
257 sal_Int32 nSecurityId
,
258 const css::util::DateTime
& rDateTime
)
260 int index
= findSignatureInfor( nSecurityId
);
264 InternalSignatureInformation
isi(nSecurityId
, nullptr);
265 isi
.signatureInfor
.stDateTime
= rDateTime
;
266 m_vInternalSignatureInformations
.push_back( isi
);
270 SignatureInformation
&si
271 = m_vInternalSignatureInformations
[index
].signatureInfor
;
272 si
.stDateTime
= rDateTime
;
276 void XSecController::setDescription(sal_Int32 nSecurityId
, const OUString
& rDescription
)
278 int nIndex
= findSignatureInfor(nSecurityId
);
282 InternalSignatureInformation
aInformation(nSecurityId
, nullptr);
283 aInformation
.signatureInfor
.ouDescription
= rDescription
;
284 m_vInternalSignatureInformations
.push_back(aInformation
);
288 SignatureInformation
& rInformation
= m_vInternalSignatureInformations
[nIndex
].signatureInfor
;
289 rInformation
.ouDescription
= rDescription
;
293 bool XSecController::WriteSignature(
294 const cssu::Reference
<cssxs::XDocumentHandler
>& xDocumentHandler
,
295 bool bXAdESCompliantIfODF
)
299 SAL_WARN_IF( !xDocumentHandler
.is(), "xmlsecurity.helper", "I really need a document handler!" );
302 * chain the SAXEventKeeper to the SAX chain
306 if ( m_eStatusOfSecurityComponents
== InitializationState::INITIALIZED
)
308 * if all security components are ready, add the signature
312 m_bIsSAXEventKeeperSticky
= true;
313 m_xSAXEventKeeper
->setNextHandler(xDocumentHandler
);
318 * export the signature template
320 cssu::Reference
<cssxs::XDocumentHandler
> xSEKHandler( m_xSAXEventKeeper
,cssu::UNO_QUERY
);
323 int sigNum
= m_vInternalSignatureInformations
.size();
325 for (i
=0; i
<sigNum
; ++i
)
327 InternalSignatureInformation
&isi
= m_vInternalSignatureInformations
[i
];
329 // Prepare the signature creator.
330 // 0 is not a documented value of embed::StorageFormats, ugh
331 isi
.xReferenceResolvedListener
= prepareSignatureToWrite( isi
, 0, bXAdESCompliantIfODF
);
333 exportSignature( xSEKHandler
, isi
.signatureInfor
, bXAdESCompliantIfODF
);
336 m_bIsSAXEventKeeperSticky
= false;
341 catch( cssu::Exception
& )
345 m_xSAXEventKeeper
->setNextHandler( nullptr );
346 m_bIsSAXEventKeeperSticky
= false;
352 bool XSecController::WriteOOXMLSignature(const uno::Reference
<embed::XStorage
>& xRootStorage
, const uno::Reference
<xml::sax::XDocumentHandler
>& xDocumentHandler
)
356 SAL_WARN_IF(!xDocumentHandler
.is(), "xmlsecurity.helper", "empty xDocumentHandler reference");
358 // Chain the SAXEventKeeper to the SAX chain.
359 chainOn(/*bRetrievingLastEvent=*/true);
361 if (m_eStatusOfSecurityComponents
== InitializationState::INITIALIZED
)
363 m_bIsSAXEventKeeperSticky
= true;
364 m_xSAXEventKeeper
->setNextHandler(xDocumentHandler
);
368 // Export the signature template.
369 cssu::Reference
<xml::sax::XDocumentHandler
> xSEKHandler(m_xSAXEventKeeper
, uno::UNO_QUERY
);
371 for (InternalSignatureInformation
& rInformation
: m_vInternalSignatureInformations
)
373 // Prepare the signature creator.
374 rInformation
.xReferenceResolvedListener
= prepareSignatureToWrite(rInformation
, embed::StorageFormats::OFOPXML
, false);
376 exportOOXMLSignature(xRootStorage
, xSEKHandler
, rInformation
.signatureInfor
);
379 m_bIsSAXEventKeeperSticky
= false;
384 catch(const uno::Exception
&)
388 m_xSAXEventKeeper
->setNextHandler(nullptr);
389 m_bIsSAXEventKeeperSticky
= false;
395 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */