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 .
23 #include <xmlsecurity/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/XSecurityController.hpp>
33 #include <com/sun/star/xml/crypto/sax/XElementStackKeeper.hpp>
34 #include <com/sun/star/xml/crypto/sax/XSecuritySAXEventKeeper.hpp>
35 #include <com/sun/star/xml/crypto/sax/XReferenceResolvedListener.hpp>
36 #include <com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeListener.hpp>
37 #include <com/sun/star/xml/crypto/sax/XSignatureCreationResultListener.hpp>
38 #include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultListener.hpp>
39 #include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp>
40 #include <com/sun/star/beans/XFastPropertySet.hpp>
41 #include <com/sun/star/io/XOutputStream.hpp>
42 #include <com/sun/star/io/XInputStream.hpp>
44 #include <rtl/ustrbuf.hxx>
46 #include <cppuhelper/implbase4.hxx>
51 * all error information
53 #define ERROR_CANNOTCREATEXMLSECURITYCOMPONENT "Can't create XML security components."
54 #define ERROR_SAXEXCEPTIONDURINGCREATION "A SAX exception is throwed during signature creation."
55 #define ERROR_IOEXCEPTIONDURINGCREATION "An IO exception is throwed during signature creation."
56 #define ERROR_EXCEPTIONDURINGCREATION "An exception is throwed during signature creation."
59 * all stringS in signature element
61 #define TAG_SIGNATURE "Signature"
62 #define TAG_SIGNEDINFO "SignedInfo"
63 #define TAG_CANONICALIZATIONMETHOD "CanonicalizationMethod"
64 #define TAG_SIGNATUREMETHOD "SignatureMethod"
65 #define TAG_REFERENCE "Reference"
66 #define TAG_TRANSFORMS "Transforms"
67 #define TAG_TRANSFORM "Transform"
68 #define TAG_DIGESTMETHOD "DigestMethod"
69 #define TAG_DIGESTVALUE "DigestValue"
70 #define TAG_SIGNATUREVALUE "SignatureValue"
71 #define TAG_KEYINFO "KeyInfo"
72 #define TAG_X509DATA "X509Data"
73 #define TAG_X509ISSUERSERIAL "X509IssuerSerial"
74 #define TAG_X509ISSUERNAME "X509IssuerName"
75 #define TAG_X509SERIALNUMBER "X509SerialNumber"
76 #define TAG_X509CERTIFICATE "X509Certificate"
77 #define TAG_OBJECT "Object"
78 #define TAG_SIGNATUREPROPERTIES "SignatureProperties"
79 #define TAG_SIGNATUREPROPERTY "SignatureProperty"
80 #define TAG_TIMESTAMP "timestamp"
81 #define TAG_DATE "date"
82 //#define TAG_TIME "time"
84 #define ATTR_XMLNS "xmlns"
85 #define ATTR_ALGORITHM "Algorithm"
86 #define ATTR_URI "URI"
88 #define ATTR_TARGET "Target"
92 #define NS_XMLDSIG "http://www.w3.org/2000/09/xmldsig#"
93 //#define NS_DATETIME "http://www.ietf.org/rfcXXXX.txt"
94 #define NS_DC "http://purl.org/dc/elements/1.1/"
96 #define ALGO_C14N "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
97 #define ALGO_RSASHA1 "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
98 #define ALGO_XMLDSIGSHA1 "http://www.w3.org/2000/09/xmldsig#sha1"
100 #define CHAR_FRAGMENT "#"
101 #define CHAR_BLANK " "
105 * status of security related components
107 #define UNINITIALIZED 0
108 #define INITIALIZED 1
109 #define FAILTOINITIALIZED 2
111 // forward declaration
114 class InternalSignatureInformation
117 SignatureInformation signatureInfor
;
119 com::sun::star::uno::Reference
<
120 com::sun::star::xml::crypto::sax::XReferenceResolvedListener
>
121 xReferenceResolvedListener
;
123 ::std::vector
< sal_Int32
> vKeeperIds
;
125 InternalSignatureInformation(
127 com::sun::star::uno::Reference
< com::sun::star::xml::crypto::sax::XReferenceResolvedListener
>
131 xReferenceResolvedListener
= xListener
;
134 void addReference( sal_Int32 type
, OUString uri
, sal_Int32 keeperId
)
136 signatureInfor
.vSignatureReferenceInfors
.push_back(
137 SignatureReferenceInformation(type
, uri
));
138 vKeeperIds
.push_back( keeperId
);
142 typedef ::std::vector
< InternalSignatureInformation
> InternalSignatureInformations
;
144 class XSecController
: public cppu::WeakImplHelper4
146 com::sun::star::xml::crypto::sax::XSecurityController
,
147 //com::sun::star::beans::XFastPropertySet,
148 com::sun::star::xml::crypto::sax::XSAXEventKeeperStatusChangeListener
,
149 com::sun::star::xml::crypto::sax::XSignatureCreationResultListener
,
150 com::sun::star::xml::crypto::sax::XSignatureVerifyResultListener
152 /****** XSecController.hxx/CLASS XSecController *******************************
155 * XSecController -- the xml security framework controller
158 * Controlls the whole xml security framework to create signatures or to
162 * The XFastPropertySet interface is used to transfer common values to
163 * classes in other module, for instance, the signature id for all
164 * sessions is transferred to xmloff module through this interface.
168 * Email: michael.mi@sun.com
169 ******************************************************************************/
171 friend class XSecParser
;
174 com::sun::star::uno::Reference
< com::sun::star::uno::XComponentContext
> mxCtx
;
177 * used to buffer SAX events
179 com::sun::star::uno::Reference
<
180 com::sun::star::xml::wrapper::XXMLDocumentWrapper
> m_xXMLDocumentWrapper
;
183 * the SAX events keeper
185 com::sun::star::uno::Reference
<
186 com::sun::star::xml::crypto::sax::XSecuritySAXEventKeeper
> m_xSAXEventKeeper
;
189 * the bridge component which creates/verifies signature
191 com::sun::star::uno::Reference
<
192 com::sun::star::xml::crypto::XXMLSignature
> m_xXMLSignature
;
195 * the Security Context
197 com::sun::star::uno::Reference
<
198 com::sun::star::xml::crypto::XXMLSecurityContext
> m_xSecurityContext
;
201 * the security id incrementer, in order to make any security id unique
202 * to the SAXEventKeeper.
203 * Because each XSecController has its own SAXEventKeeper, so this variable
204 * is not necessary to be static.
206 sal_Int32 m_nNextSecurityId
;
209 * Signature information
211 InternalSignatureInformations m_vInternalSignatureInformations
;
214 * the previous node on the SAX chain.
215 * The reason that use a Reference<XInterface> type variable
216 * is that the previous components are different when exporting
217 * and importing, and there is no other common interface they
220 com::sun::star::uno::Reference
<
221 com::sun::star::uno::XInterface
> m_xPreviousNodeOnSAXChain
;
223 * whether the preivous node can provide an XInitiazlize interface,
224 * use this variable in order to typecast the XInterface to the
225 * correct interface type.
227 bool m_bIsPreviousNodeInitializable
;
230 * the next node on the SAX chain.
231 * it can always provide an XDocumentHandler interface.
233 com::sun::star::uno::Reference
<
234 com::sun::star::xml::sax::XDocumentHandler
> m_xNextNodeOnSAXChain
;
237 * the ElementStackKeeper is used to reserve the key SAX events.
238 * when the SAXEventKeeper is chained on the SAX chain, it need
239 * first get all missed key SAX events in order to make sure the
240 * DOM tree it buffering has the same structure with the original
243 * For a given section of a SAX event stream, the key SAX events
244 * are the minimal SAX event subset of that section, which,
245 * combining with SAX events outside of this section, has the same
246 * structure with the original document.
248 * For example, sees the following dom fragment:
258 * If we consider the SAX event section from startElement(<A>) to
259 * startElement(<D>), then the key SAX events are:
261 * startElement(<A>), startElement(<C>), startElement(<D>)
263 * The startElement(<B>) and endElement(<B>) is ignored, because
264 * they are unimportant for the tree structure in this section.
266 * If we consider the SAX event section from startElement(<D>) to
267 * endElement(<A>), the key SAX events are:
269 * startElement(<D>), endElement(<D>), endElement(<C>),
272 com::sun::star::uno::Reference
<
273 com::sun::star::xml::crypto::sax::XElementStackKeeper
> m_xElementStackKeeper
;
276 * a flag representing whether the SAXEventKeeper is now on the
279 bool m_bIsSAXEventKeeperConnected
;
282 * a flag representing whether it is collecting some element,
283 * which means that the SAXEventKeeper can't be chained off the
286 bool m_bIsCollectingElement
;
289 * a flag representing whether the SAX event stream is blocking,
290 * which also means that the SAXEventKeeper can't be chained off
296 * a flag representing the current status of security related
299 sal_Int32 m_nStatusOfSecurityComponents
;
302 * a flag representing whether the SAXEventKeeper need to be
303 * on the SAX chain all the time.
304 * This flag is used to the situation when creating signature.
306 bool m_bIsSAXEventKeeperSticky
;
309 * fast property vector
311 std::vector
< sal_Int32
> m_vFastPropertyIndexs
;
312 std::vector
< com::sun::star::uno::Any
> m_vFastPropertyValues
;
315 * error message pointer
317 const char *m_pErrorMessage
;
320 * the XSecParser which is used to parse the signature stream
322 XSecParser
*m_pXSecParser
;
325 * the caller assigned signature id for the next signature in the
328 sal_Int32 m_nReservedSignatureId
;
331 * representing whether to verify the current signature
333 bool m_bVerifyCurrentSignature
;
336 * An xUriBinding is provided to map Uris to XInputStream interfaces.
338 com::sun::star::uno::Reference
<
339 com::sun::star::xml::crypto::XUriBinding
> m_xUriBinding
;
346 void createXSecComponent( );
347 int findSignatureInfor( sal_Int32 nSecurityId
) const;
348 bool chainOn( bool bRetrievingLastEvent
);
350 void checkChainingStatus();
351 void initializeSAXChain();
353 com::sun::star::uno::Reference
<
354 com::sun::star::io::XInputStream
> getObjectInputStream( const OUString
& objectURL
);
356 //sal_Int32 getFastPropertyIndex(sal_Int32 nHandle) const;
359 * For signature generation
362 com::sun::star::uno::Reference
<
363 com::sun::star::xml::crypto::sax::XReferenceResolvedListener
> prepareSignatureToWrite(
364 InternalSignatureInformation
& signatureInfo
);
367 * For signature verification
370 void addReference( const OUString
& ouUri
);
371 void addStreamReference(
372 const OUString
& ouUri
,
374 void setReferenceCount() const;
376 void setX509IssuerName( OUString
& ouX509IssuerName
);
377 void setX509SerialNumber( OUString
& ouX509SerialNumber
);
378 void setX509Certificate( OUString
& ouX509Certificate
);
379 void setSignatureValue( OUString
& ouSignatureValue
);
380 void setDigestValue( OUString
& ouDigestValue
);
382 void setDate( OUString
& ouDate
);
384 void setId( OUString
& ouId
);
385 void setPropertyId( OUString
& ouPropertyId
);
387 com::sun::star::uno::Reference
<
388 com::sun::star::xml::crypto::sax::XReferenceResolvedListener
> prepareSignatureToRead(
389 sal_Int32 nSecurityId
);
392 XSecController(const com::sun::star::uno::Reference
<com::sun::star::uno::XComponentContext
>& rxCtx
);
395 sal_Int32
getNewSecurityId( );
397 void startMission( const com::sun::star::uno::Reference
<
398 com::sun::star::xml::crypto::XUriBinding
>& xUriBinding
,
399 const com::sun::star::uno::Reference
<
400 com::sun::star::xml::crypto::XXMLSecurityContext
>& xSecurityContext
);
402 void setSAXChainConnector(
403 const com::sun::star::uno::Reference
<
404 com::sun::star::lang::XInitialization
>& xInitialization
,
405 const com::sun::star::uno::Reference
<
406 com::sun::star::xml::sax::XDocumentHandler
>& xDocumentHandler
,
407 const com::sun::star::uno::Reference
<
408 com::sun::star::xml::crypto::sax::XElementStackKeeper
>& xElementStackKeeper
);
410 void clearSAXChainConnector();
413 SignatureInformation
getSignatureInformation( sal_Int32 nSecurityId
) const;
414 SignatureInformations
getSignatureInformations() const;
416 void exportSignature(
417 const com::sun::star::uno::Reference
<
418 com::sun::star::xml::sax::XDocumentHandler
>& xDocumentHandler
,
419 const SignatureInformation
& signatureInfo
);
423 * For signature generation
425 void signAStream( sal_Int32 securityId
, const OUString
& uri
, const OUString
& objectURL
, sal_Bool isBinary
);
428 /** sets data that describes the certificate.
430 It is absolutely necessary that the parameter ouX509IssuerName is set. It contains
431 the base64 encoded certificate, which is DER encoded. The XMLSec needs it to find
432 the private key. Although issuer name and certificate should be sufficient to identify
433 the certificate the implementation in XMLSec is broken, both for Windows and mozilla.
434 The reason is that they use functions to find the certificate which take as parameter
435 the DER encoded ASN.1 issuer name. The issuer name is a DName, where most attributes
436 are of type DirectoryName, which is a choice of 5 string types. This information is
437 not contained in the issuer string and while it is converted to the ASN.1 name the
438 conversion function must assume a particular type, which is often wrong. For example,
439 the Windows function CertStrToName will use a T.61 string if the string does not contain
440 special characters. So if the certificate uses simple characters but encodes the
441 issuer attributes in Utf8, then CertStrToName will use T.61. The resulting DER encoded
442 ASN.1 name now contains different bytes which indicate the string type. The functions
443 for finding the certificate apparently use memcmp - hence they fail to find the
446 void setX509Certificate(
447 sal_Int32 nSecurityId
,
448 const OUString
& ouX509IssuerName
,
449 const OUString
& ouX509SerialNumber
,
450 const OUString
& ouX509Cert
);
451 // see the other setX509Certifcate function
452 void setX509Certificate(
453 sal_Int32 nSecurityId
,
454 const sal_Int32 nSecurityEnvironmentIndex
,
455 const OUString
& ouX509IssuerName
,
456 const OUString
& ouX509SerialNumber
,
457 const OUString
& ouX509Cert
);
460 sal_Int32 nSecurityId
,
461 const ::com::sun::star::util::DateTime
& rDateTime
);
465 const com::sun::star::uno::Reference
<
466 com::sun::star::xml::sax::XDocumentHandler
>& xDocumentHandler
);
469 * For signature verification
471 void collectToVerify( const OUString
& referenceId
);
472 void addSignature( sal_Int32 nSignatureId
);
473 com::sun::star::uno::Reference
< com::sun::star::xml::sax::XDocumentHandler
> createSignatureReader();
474 void releaseSignatureReader();
477 /* Interface methods */
480 * XSecurityController
482 * no method in XSecurityController interface
490 * XSAXEventKeeperStatusChangeListener
492 virtual void SAL_CALL
blockingStatusChanged( sal_Bool isBlocking
)
493 throw (com::sun::star::uno::RuntimeException
);
494 virtual void SAL_CALL
collectionStatusChanged(
495 sal_Bool isInsideCollectedElement
)
496 throw (com::sun::star::uno::RuntimeException
);
497 virtual void SAL_CALL
bufferStatusChanged( sal_Bool isBufferEmpty
)
498 throw (com::sun::star::uno::RuntimeException
);
501 * XSignatureCreationResultListener
503 virtual void SAL_CALL
signatureCreated( sal_Int32 securityId
, com::sun::star::xml::crypto::SecurityOperationStatus nResult
)
504 throw (com::sun::star::uno::RuntimeException
);
507 * XSignatureVerifyResultListener
509 virtual void SAL_CALL
signatureVerified( sal_Int32 securityId
, com::sun::star::xml::crypto::SecurityOperationStatus nResult
)
510 throw (com::sun::star::uno::RuntimeException
);
516 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */