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 .
20 #ifndef INCLUDED_XMLSECURITY_SOURCE_HELPER_XSECCTL_HXX
21 #define INCLUDED_XMLSECURITY_SOURCE_HELPER_XSECCTL_HXX
23 #include <sigstruct.hxx>
25 #include <com/sun/star/uno/XComponentContext.hpp>
26 #include <com/sun/star/xml/sax/XParser.hpp>
27 #include <com/sun/star/lang/XInitialization.hpp>
28 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
29 #include <com/sun/star/xml/sax/XAttributeList.hpp>
30 #include <com/sun/star/xml/crypto/XXMLSignature.hpp>
31 #include <com/sun/star/xml/crypto/XSEInitializer.hpp>
32 #include <com/sun/star/xml/crypto/sax/XElementStackKeeper.hpp>
33 #include <com/sun/star/xml/crypto/sax/XSecuritySAXEventKeeper.hpp>
34 #include <com/sun/star/xml/crypto/sax/XReferenceResolvedListener.hpp>
35 #include <com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeListener.hpp>
36 #include <com/sun/star/xml/crypto/sax/XSignatureCreationResultListener.hpp>
37 #include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultListener.hpp>
38 #include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp>
39 #include <com/sun/star/io/XOutputStream.hpp>
40 #include <com/sun/star/io/XInputStream.hpp>
41 #include <com/sun/star/embed/XStorage.hpp>
43 #include <rtl/ustrbuf.hxx>
45 #include <cppuhelper/implbase.hxx>
49 #define NS_XMLDSIG "http://www.w3.org/2000/09/xmldsig#"
50 #define NS_DC "http://purl.org/dc/elements/1.1/"
51 #define NS_XD "http://uri.etsi.org/01903/v1.3.2#"
52 #define NS_MDSSI "http://schemas.openxmlformats.org/package/2006/digital-signature"
54 #define ALGO_C14N "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
55 #define ALGO_RSASHA1 "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
56 #define ALGO_RSASHA256 "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
57 #define ALGO_XMLDSIGSHA1 "http://www.w3.org/2000/09/xmldsig#sha1"
58 #define ALGO_XMLDSIGSHA256 "http://www.w3.org/2001/04/xmlenc#sha256"
59 #define ALGO_RELATIONSHIP "http://schemas.openxmlformats.org/package/2006/RelationshipTransform"
63 class InternalSignatureInformation
66 SignatureInformation signatureInfor
;
68 css::uno::Reference
< css::xml::crypto::sax::XReferenceResolvedListener
> xReferenceResolvedListener
;
70 ::std::vector
< sal_Int32
> vKeeperIds
;
72 InternalSignatureInformation(
74 css::uno::Reference
< css::xml::crypto::sax::XReferenceResolvedListener
> const & xListener
)
77 xReferenceResolvedListener
= xListener
;
80 void addReference( SignatureReferenceType type
, sal_Int32 digestID
, const OUString
& uri
, sal_Int32 keeperId
)
82 signatureInfor
.vSignatureReferenceInfors
.push_back(
83 SignatureReferenceInformation(type
, digestID
, uri
));
84 vKeeperIds
.push_back( keeperId
);
88 class XSecController
: public cppu::WeakImplHelper
90 css::xml::crypto::sax::XSAXEventKeeperStatusChangeListener
,
91 css::xml::crypto::sax::XSignatureCreationResultListener
,
92 css::xml::crypto::sax::XSignatureVerifyResultListener
94 /****** XSecController.hxx/CLASS XSecController *******************************
97 * XSecController -- the xml security framework controller
100 * Controls the whole xml security framework to create signatures or to
103 ******************************************************************************/
105 friend class XSecParser
;
106 friend class OOXMLSecParser
;
109 css::uno::Reference
< css::uno::XComponentContext
> mxCtx
;
112 * used to buffer SAX events
114 css::uno::Reference
< css::xml::wrapper::XXMLDocumentWrapper
> m_xXMLDocumentWrapper
;
117 * the SAX events keeper
119 css::uno::Reference
< css::xml::crypto::sax::XSecuritySAXEventKeeper
> m_xSAXEventKeeper
;
122 * the bridge component which creates/verifies signature
124 css::uno::Reference
< css::xml::crypto::XXMLSignature
> m_xXMLSignature
;
127 * the Security Context
129 css::uno::Reference
< css::xml::crypto::XXMLSecurityContext
> m_xSecurityContext
;
132 * the security id incrementer, in order to make any security id unique
133 * to the SAXEventKeeper.
134 * Because each XSecController has its own SAXEventKeeper, so this variable
135 * is not necessary to be static.
137 sal_Int32 m_nNextSecurityId
;
140 * Signature information
142 std::vector
< InternalSignatureInformation
> m_vInternalSignatureInformations
;
145 * the previous node on the SAX chain.
146 * The reason that use a Reference<XInterface> type variable
147 * is that the previous components are different when exporting
148 * and importing, and there is no other common interface they
151 css::uno::Reference
< css::uno::XInterface
> m_xPreviousNodeOnSAXChain
;
153 * whether the previous node can provide an XInitialize interface,
154 * use this variable in order to typecast the XInterface to the
155 * correct interface type.
157 bool m_bIsPreviousNodeInitializable
;
160 * the next node on the SAX chain.
161 * it can always provide an XDocumentHandler interface.
163 css::uno::Reference
< css::xml::sax::XDocumentHandler
> m_xNextNodeOnSAXChain
;
166 * the ElementStackKeeper is used to reserve the key SAX events.
167 * when the SAXEventKeeper is chained on the SAX chain, it need
168 * first get all missed key SAX events in order to make sure the
169 * DOM tree it buffering has the same structure with the original
172 * For a given section of a SAX event stream, the key SAX events
173 * are the minimal SAX event subset of that section, which,
174 * combining with SAX events outside of this section, has the same
175 * structure with the original document.
177 * For example, sees the following dom fragment:
187 * If we consider the SAX event section from startElement(<A>) to
188 * startElement(<D>), then the key SAX events are:
190 * startElement(<A>), startElement(<C>), startElement(<D>)
192 * The startElement(<B>) and endElement(<B>) is ignored, because
193 * they are unimportant for the tree structure in this section.
195 * If we consider the SAX event section from startElement(<D>) to
196 * endElement(<A>), the key SAX events are:
198 * startElement(<D>), endElement(<D>), endElement(<C>),
201 css::uno::Reference
< css::xml::crypto::sax::XElementStackKeeper
> m_xElementStackKeeper
;
204 * a flag representing whether the SAXEventKeeper is now on the
207 bool m_bIsSAXEventKeeperConnected
;
210 * a flag representing whether it is collecting some element,
211 * which means that the SAXEventKeeper can't be chained off the
214 bool m_bIsCollectingElement
;
217 * a flag representing whether the SAX event stream is blocking,
218 * which also means that the SAXEventKeeper can't be chained off
224 * a flag representing the current status of security related
229 * status of security related components
231 enum class InitializationState
{ UNINITIALIZED
, INITIALIZED
, FAILTOINITIALIZED
} m_eStatusOfSecurityComponents
;
234 * a flag representing whether the SAXEventKeeper need to be
235 * on the SAX chain all the time.
236 * This flag is used to the situation when creating signature.
238 bool m_bIsSAXEventKeeperSticky
;
241 * the XSecParser which is used to parse the signature stream
243 css::uno::Reference
<css::xml::sax::XDocumentHandler
> m_xSecParser
;
246 * the caller assigned signature id for the next signature in the
249 sal_Int32 m_nReservedSignatureId
;
252 * representing whether to verify the current signature
254 bool m_bVerifyCurrentSignature
;
257 * the type of signature to generate (from the css::xml::crypto::DigestID alternatives) when there is a choice,
258 * in practice currently SHA1 or SHA256 for ODF.
260 sal_Int32 m_nDigestID
;
264 * An xUriBinding is provided to map Uris to XInputStream interfaces.
266 css::uno::Reference
< css::xml::crypto::XUriBinding
> m_xUriBinding
;
273 void createXSecComponent( );
274 int findSignatureInfor( sal_Int32 nSecurityId
) const;
275 bool chainOn( bool bRetrievingLastEvent
);
277 void checkChainingStatus();
278 void initializeSAXChain();
280 css::uno::Reference
< css::io::XInputStream
> getObjectInputStream( const OUString
& objectURL
);
282 //sal_Int32 getFastPropertyIndex(sal_Int32 nHandle) const;
285 * For signature generation
287 static OUString
createId();
288 css::uno::Reference
< css::xml::crypto::sax::XReferenceResolvedListener
> prepareSignatureToWrite(
289 InternalSignatureInformation
& signatureInfo
,
290 sal_Int32 nStorageFormat
,
291 bool bXAdESCompliantIfODF
);
294 * For signature verification
298 const OUString
& ouUri
,
299 sal_Int32 nDigestID
);
300 void addStreamReference(
301 const OUString
& ouUri
,
303 sal_Int32 nDigestID
);
304 void setReferenceCount() const;
306 void setX509IssuerName( OUString
& ouX509IssuerName
);
307 void setX509SerialNumber( OUString
& ouX509SerialNumber
);
308 void setX509Certificate( OUString
& ouX509Certificate
);
309 void setSignatureValue( OUString
& ouSignatureValue
);
310 void setDigestValue( sal_Int32 nDigestID
, OUString
& ouDigestValue
);
312 void setDate( OUString
& ouDate
);
313 void setDescription(const OUString
& rDescription
);
314 void setCertDigest(const OUString
& rCertDigest
);
317 void setSignatureBytes(const css::uno::Sequence
<sal_Int8
>& rBytes
);
320 void setId( OUString
& ouId
);
321 void setPropertyId( OUString
& ouPropertyId
);
323 css::uno::Reference
< css::xml::crypto::sax::XReferenceResolvedListener
> prepareSignatureToRead(
324 sal_Int32 nSecurityId
);
327 explicit XSecController(const css::uno::Reference
<css::uno::XComponentContext
>& rxCtx
);
328 virtual ~XSecController() override
;
330 sal_Int32
getNewSecurityId( );
332 void startMission( const css::uno::Reference
<
333 css::xml::crypto::XUriBinding
>& xUriBinding
,
334 const css::uno::Reference
<
335 css::xml::crypto::XXMLSecurityContext
>& xSecurityContext
);
337 void setSAXChainConnector(
338 const css::uno::Reference
< css::lang::XInitialization
>& xInitialization
,
339 const css::uno::Reference
< css::xml::sax::XDocumentHandler
>& xDocumentHandler
,
340 const css::uno::Reference
< css::xml::crypto::sax::XElementStackKeeper
>& xElementStackKeeper
);
342 void clearSAXChainConnector();
345 SignatureInformation
getSignatureInformation( sal_Int32 nSecurityId
) const;
346 SignatureInformations
getSignatureInformations() const;
348 static void exportSignature(
349 const css::uno::Reference
< css::xml::sax::XDocumentHandler
>& xDocumentHandler
,
350 const SignatureInformation
& signatureInfo
,
351 bool bXAdESCompliantIfODF
);
355 * For signature generation
357 void signAStream( sal_Int32 securityId
, const OUString
& uri
, const OUString
& objectURL
, bool isBinary
, bool bXAdESCompliantIfODF
);
360 /** sets data that describes the certificate.
362 It is absolutely necessary that the parameter ouX509IssuerName is set. It contains
363 the base64 encoded certificate, which is DER encoded. The XMLSec needs it to find
364 the private key. Although issuer name and certificate should be sufficient to identify
365 the certificate the implementation in XMLSec is broken, both for Windows and mozilla.
366 The reason is that they use functions to find the certificate which take as parameter
367 the DER encoded ASN.1 issuer name. The issuer name is a DName, where most attributes
368 are of type DirectoryName, which is a choice of 5 string types. This information is
369 not contained in the issuer string and while it is converted to the ASN.1 name the
370 conversion function must assume a particular type, which is often wrong. For example,
371 the Windows function CertStrToName will use a T.61 string if the string does not contain
372 special characters. So if the certificate uses simple characters but encodes the
373 issuer attributes in Utf8, then CertStrToName will use T.61. The resulting DER encoded
374 ASN.1 name now contains different bytes which indicate the string type. The functions
375 for finding the certificate apparently use memcmp - hence they fail to find the
378 void setX509Certificate(
379 sal_Int32 nSecurityId
,
380 const OUString
& ouX509IssuerName
,
381 const OUString
& ouX509SerialNumber
,
382 const OUString
& ouX509Cert
,
383 const OUString
& ouX509CertDigest
);
385 void addEncapsulatedX509Certificate(const OUString
& rEncapsulatedX509Certificate
);
388 sal_Int32 nSecurityId
,
389 const css::util::DateTime
& rDateTime
);
390 void setDescription(sal_Int32 nSecurityId
, const OUString
& rDescription
);
393 const css::uno::Reference
< css::xml::sax::XDocumentHandler
>& xDocumentHandler
,
394 bool bXAdESCompliantIfODF
);
397 * For signature verification
399 void collectToVerify( const OUString
& referenceId
);
400 void addSignature( sal_Int32 nSignatureId
);
401 css::uno::Reference
< css::xml::sax::XDocumentHandler
> const & createSignatureReader(sal_Int32 nType
= 0);
402 void releaseSignatureReader();
405 /* Interface methods */
408 * XSAXEventKeeperStatusChangeListener
410 virtual void SAL_CALL
blockingStatusChanged( sal_Bool isBlocking
)
411 throw (css::uno::RuntimeException
, std::exception
) override
;
412 virtual void SAL_CALL
collectionStatusChanged(
413 sal_Bool isInsideCollectedElement
)
414 throw (css::uno::RuntimeException
, std::exception
) override
;
415 virtual void SAL_CALL
bufferStatusChanged( sal_Bool isBufferEmpty
)
416 throw (css::uno::RuntimeException
, std::exception
) override
;
419 * XSignatureCreationResultListener
421 virtual void SAL_CALL
signatureCreated( sal_Int32 securityId
, css::xml::crypto::SecurityOperationStatus nResult
)
422 throw (css::uno::RuntimeException
, std::exception
) override
;
425 * XSignatureVerifyResultListener
427 virtual void SAL_CALL
signatureVerified( sal_Int32 securityId
, css::xml::crypto::SecurityOperationStatus nResult
)
428 throw (css::uno::RuntimeException
, std::exception
) override
;
430 /// Writes XML elements inside a single OOXML signature's <Signature> element.
431 bool WriteOOXMLSignature(const css::uno::Reference
<css::embed::XStorage
>& xRootStorage
, const css::uno::Reference
<css::xml::sax::XDocumentHandler
>& xDocumentHandler
);
432 /// Exports an OOXML signature, called by WriteOOXMLSignature().
433 void exportOOXMLSignature(const css::uno::Reference
<css::embed::XStorage
>& xRootStorage
, const css::uno::Reference
<css::xml::sax::XDocumentHandler
>& xDocumentHandler
, const SignatureInformation
& rInformation
);
438 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */