1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 "xsecparser.hxx"
22 #include <cppuhelper/exc_hlp.hxx>
26 namespace cssu
= com::sun::star::uno
;
27 namespace cssxc
= com::sun::star::xml::crypto
;
28 namespace cssxs
= com::sun::star::xml::sax
;
30 XSecParser::XSecParser(XSecController
* pXSecController
,
31 const cssu::Reference
< cssxs::XDocumentHandler
>& xNextHandler
)
32 : m_bInX509IssuerName(false)
33 , m_bInX509SerialNumber(false)
34 , m_bInX509Certificate(false)
35 , m_bInCertDigest(false)
36 , m_bInEncapsulatedX509Certificate(false)
37 , m_bInSigningTime(false)
38 , m_bInDigestValue(false)
39 , m_bInSignatureValue(false)
41 , m_bInDescription(false)
42 , m_pXSecController(pXSecController
)
43 , m_xNextHandler(xNextHandler
)
44 , m_bReferenceUnresolved(false)
45 , m_nReferenceDigestID(cssxc::DigestID::SHA1
)
49 OUString
XSecParser::getIdAttr(const cssu::Reference
< cssxs::XAttributeList
>& xAttribs
)
51 OUString ouIdAttr
= xAttribs
->getValueByName("id");
53 if (ouIdAttr
.isEmpty())
55 ouIdAttr
= xAttribs
->getValueByName("Id");
64 void SAL_CALL
XSecParser::startDocument( )
65 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
67 m_bInX509IssuerName
= false;
68 m_bInX509SerialNumber
= false;
69 m_bInX509Certificate
= false;
70 m_bInSignatureValue
= false;
71 m_bInDigestValue
= false;
73 m_bInDescription
= false;
75 if (m_xNextHandler
.is())
77 m_xNextHandler
->startDocument();
81 void SAL_CALL
XSecParser::endDocument( )
82 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
84 if (m_xNextHandler
.is())
86 m_xNextHandler
->endDocument();
90 void SAL_CALL
XSecParser::startElement(
91 const OUString
& aName
,
92 const cssu::Reference
< cssxs::XAttributeList
>& xAttribs
)
93 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
97 OUString ouIdAttr
= getIdAttr(xAttribs
);
98 if (!ouIdAttr
.isEmpty())
100 m_pXSecController
->collectToVerify( ouIdAttr
);
103 if ( aName
== "Signature" )
105 m_pXSecController
->addSignature();
106 if (!ouIdAttr
.isEmpty())
108 m_pXSecController
->setId( ouIdAttr
);
111 else if ( aName
== "Reference" )
113 OUString ouUri
= xAttribs
->getValueByName("URI");
114 SAL_WARN_IF( ouUri
.isEmpty(), "xmlsecurity.helper", "URI is empty" );
115 if (ouUri
.startsWith("#"))
118 * remove the first character '#' from the attribute value
120 m_pXSecController
->addReference( ouUri
.copy(1), m_nReferenceDigestID
);
127 m_currentReferenceURI
= ouUri
;
128 m_bReferenceUnresolved
= true;
131 else if (aName
== "DigestMethod")
133 OUString ouAlgorithm
= xAttribs
->getValueByName("Algorithm");
135 SAL_WARN_IF( ouAlgorithm
.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" );
136 if (!ouAlgorithm
.isEmpty())
138 SAL_WARN_IF( ouAlgorithm
!= ALGO_XMLDSIGSHA1
&& ouAlgorithm
!= ALGO_XMLDSIGSHA256
,
139 "xmlsecurity.helper", "Algorithm neither SHA1 or SHA256");
140 if (ouAlgorithm
== ALGO_XMLDSIGSHA1
)
141 m_nReferenceDigestID
= cssxc::DigestID::SHA1
;
142 else if (ouAlgorithm
== ALGO_XMLDSIGSHA256
)
143 m_nReferenceDigestID
= cssxc::DigestID::SHA256
;
146 else if (aName
== "Transform")
148 if ( m_bReferenceUnresolved
)
150 OUString ouAlgorithm
= xAttribs
->getValueByName("Algorithm");
152 if (ouAlgorithm
== ALGO_C14N
)
157 m_pXSecController
->addStreamReference( m_currentReferenceURI
, false, m_nReferenceDigestID
);
158 m_bReferenceUnresolved
= false;
162 else if (aName
== "X509IssuerName")
164 m_ouX509IssuerName
.clear();
165 m_bInX509IssuerName
= true;
167 else if (aName
== "X509SerialNumber")
169 m_ouX509SerialNumber
.clear();
170 m_bInX509SerialNumber
= true;
172 else if (aName
== "X509Certificate")
174 m_ouX509Certificate
.clear();
175 m_bInX509Certificate
= true;
177 else if (aName
== "SignatureValue")
179 m_ouSignatureValue
.clear();
180 m_bInSignatureValue
= true;
182 else if (aName
== "DigestValue" && !m_bInCertDigest
)
184 m_ouDigestValue
.clear();
185 m_bInDigestValue
= true;
187 else if (aName
== "xd:CertDigest")
189 m_ouCertDigest
.clear();
190 m_bInCertDigest
= true;
192 // FIXME: Existing code here in xmlsecurity uses "xd" as the namespace prefix for XAdES,
193 // while the sample document attached to tdf#76142 uses "xades". So accept either here. Of
194 // course this is idiotic and wrong, the right thing would be to use a proper way to parse
195 // XML that would handle namespaces correctly. I have no idea how substantial re-plumbing of
196 // this code that would require.
197 else if (aName
== "xd:EncapsulatedX509Certificate" || aName
== "xades:EncapsulatedX509Certificate")
199 m_ouEncapsulatedX509Certificate
.clear();
200 m_bInEncapsulatedX509Certificate
= true;
202 else if (aName
== "xd:SigningTime" || aName
== "xades:SigningTime")
205 m_bInSigningTime
= true;
207 else if ( aName
== "SignatureProperty" )
209 if (!ouIdAttr
.isEmpty())
211 m_pXSecController
->setPropertyId( ouIdAttr
);
214 else if (aName
== "dc:date")
216 if (m_ouDate
.isEmpty())
219 else if (aName
== "dc:description")
221 m_ouDescription
.clear();
222 m_bInDescription
= true;
225 if (m_xNextHandler
.is())
227 m_xNextHandler
->startElement(aName
, xAttribs
);
230 catch (cssu::Exception
& )
231 {//getCaughtException MUST be the first line in the catch block
232 cssu::Any exc
= cppu::getCaughtException();
233 throw cssxs::SAXException(
234 "xmlsecurity: Exception in XSecParser::startElement",
239 throw cssxs::SAXException(
240 "xmlsecurity: unexpected exception in XSecParser::startElement", nullptr,
245 void SAL_CALL
XSecParser::endElement( const OUString
& aName
)
246 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
250 if (aName
== "DigestValue" && !m_bInCertDigest
)
252 m_bInDigestValue
= false;
254 else if ( aName
== "Reference" )
256 if ( m_bReferenceUnresolved
)
258 * it must be a octet stream
261 m_pXSecController
->addStreamReference( m_currentReferenceURI
, true, m_nReferenceDigestID
);
262 m_bReferenceUnresolved
= false;
265 m_pXSecController
->setDigestValue( m_nReferenceDigestID
, m_ouDigestValue
);
267 else if ( aName
== "SignedInfo" )
269 m_pXSecController
->setReferenceCount();
271 else if ( aName
== "SignatureValue" )
273 m_pXSecController
->setSignatureValue( m_ouSignatureValue
);
274 m_bInSignatureValue
= false;
276 else if (aName
== "X509IssuerName")
278 m_pXSecController
->setX509IssuerName( m_ouX509IssuerName
);
279 m_bInX509IssuerName
= false;
281 else if (aName
== "X509SerialNumber")
283 m_pXSecController
->setX509SerialNumber( m_ouX509SerialNumber
);
284 m_bInX509SerialNumber
= false;
286 else if (aName
== "X509Certificate")
288 m_pXSecController
->setX509Certificate( m_ouX509Certificate
);
289 m_bInX509Certificate
= false;
291 else if (aName
== "xd:CertDigest")
293 m_pXSecController
->setCertDigest( m_ouCertDigest
);
294 m_bInCertDigest
= false;
296 else if (aName
== "xd:EncapsulatedX509Certificate" || aName
== "xades:EncapsulatedX509Certificate")
298 m_pXSecController
->addEncapsulatedX509Certificate( m_ouEncapsulatedX509Certificate
);
299 m_bInEncapsulatedX509Certificate
= false;
301 else if (aName
== "xd:SigningTime" || aName
== "xades:SigningTime")
303 m_pXSecController
->setDate( m_ouDate
);
304 m_bInSigningTime
= false;
306 else if (aName
== "dc:date")
310 m_pXSecController
->setDate( m_ouDate
);
314 else if (aName
== "dc:description")
316 m_pXSecController
->setDescription( m_ouDescription
);
317 m_bInDescription
= false;
320 if (m_xNextHandler
.is())
322 m_xNextHandler
->endElement(aName
);
325 catch (cssu::Exception
& )
326 {//getCaughtException MUST be the first line in the catch block
327 cssu::Any exc
= cppu::getCaughtException();
328 throw cssxs::SAXException(
329 "xmlsecurity: Exception in XSecParser::endElement",
334 throw cssxs::SAXException(
335 "xmlsecurity: unexpected exception in XSecParser::endElement", nullptr,
340 void SAL_CALL
XSecParser::characters( const OUString
& aChars
)
341 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
343 if (m_bInX509IssuerName
)
345 m_ouX509IssuerName
+= aChars
;
347 else if (m_bInX509SerialNumber
)
349 m_ouX509SerialNumber
+= aChars
;
351 else if (m_bInX509Certificate
)
353 m_ouX509Certificate
+= aChars
;
355 else if (m_bInSignatureValue
)
357 m_ouSignatureValue
+= aChars
;
359 else if (m_bInDigestValue
&& !m_bInCertDigest
)
361 m_ouDigestValue
+= aChars
;
367 else if (m_bInDescription
)
369 m_ouDescription
+= aChars
;
371 else if (m_bInCertDigest
)
373 m_ouCertDigest
+= aChars
;
375 else if (m_bInEncapsulatedX509Certificate
)
377 m_ouEncapsulatedX509Certificate
+= aChars
;
379 else if (m_bInSigningTime
)
384 if (m_xNextHandler
.is())
386 m_xNextHandler
->characters(aChars
);
390 void SAL_CALL
XSecParser::ignorableWhitespace( const OUString
& aWhitespaces
)
391 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
393 if (m_xNextHandler
.is())
395 m_xNextHandler
->ignorableWhitespace( aWhitespaces
);
399 void SAL_CALL
XSecParser::processingInstruction( const OUString
& aTarget
, const OUString
& aData
)
400 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
402 if (m_xNextHandler
.is())
404 m_xNextHandler
->processingInstruction(aTarget
, aData
);
408 void SAL_CALL
XSecParser::setDocumentLocator( const cssu::Reference
< cssxs::XLocator
>& xLocator
)
409 throw (cssxs::SAXException
, cssu::RuntimeException
, std::exception
)
411 if (m_xNextHandler
.is())
413 m_xNextHandler
->setDocumentLocator( xLocator
);
420 void SAL_CALL
XSecParser::initialize(
421 const cssu::Sequence
< cssu::Any
>& aArguments
)
422 throw(cssu::Exception
, cssu::RuntimeException
, std::exception
)
424 aArguments
[0] >>= m_xNextHandler
;
427 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */