Bump version to 6.0-36
[LibreOffice.git] / xmlsecurity / source / helper / xsecparser.cxx
blobb33a11f5cf3656401c2e89bef7002d0371b5c8f2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
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 <xmlsignaturehelper.hxx>
23 #include <com/sun/star/xml/sax/SAXException.hpp>
24 #include <cppuhelper/exc_hlp.hxx>
26 #include <string.h>
28 namespace cssu = com::sun::star::uno;
29 namespace cssxc = com::sun::star::xml::crypto;
30 namespace cssxs = com::sun::star::xml::sax;
32 XSecParser::XSecParser(XMLSignatureHelper& rXMLSignatureHelper,
33 XSecController* pXSecController)
34 : m_bInX509IssuerName(false)
35 , m_bInX509SerialNumber(false)
36 , m_bInX509Certificate(false)
37 , m_bInGpgCertificate(false)
38 , m_bInGpgKeyID(false)
39 , m_bInGpgOwner(false)
40 , m_bInCertDigest(false)
41 , m_bInEncapsulatedX509Certificate(false)
42 , m_bInSigningTime(false)
43 , m_bInDigestValue(false)
44 , m_bInSignatureValue(false)
45 , m_bInDate(false)
46 , m_bInDescription(false)
47 , m_bInSignatureLineId(false)
48 , m_pXSecController(pXSecController)
49 , m_bReferenceUnresolved(false)
50 , m_nReferenceDigestID(cssxc::DigestID::SHA1)
51 , m_rXMLSignatureHelper(rXMLSignatureHelper)
55 OUString XSecParser::getIdAttr(const cssu::Reference< cssxs::XAttributeList >& xAttribs )
57 OUString ouIdAttr = xAttribs->getValueByName("id");
59 if (ouIdAttr.isEmpty())
61 ouIdAttr = xAttribs->getValueByName("Id");
64 return ouIdAttr;
68 * XDocumentHandler
70 void SAL_CALL XSecParser::startDocument( )
72 m_bInX509IssuerName = false;
73 m_bInX509SerialNumber = false;
74 m_bInX509Certificate = false;
75 m_bInGpgCertificate = false;
76 m_bInGpgKeyID = false;
77 m_bInGpgOwner = false;
78 m_bInSignatureValue = false;
79 m_bInDigestValue = false;
80 m_bInDate = false;
81 m_bInDescription = false;
83 if (m_xNextHandler.is())
85 m_xNextHandler->startDocument();
89 void SAL_CALL XSecParser::endDocument( )
91 if (m_xNextHandler.is())
93 m_xNextHandler->endDocument();
97 void SAL_CALL XSecParser::startElement(
98 const OUString& aName,
99 const cssu::Reference< cssxs::XAttributeList >& xAttribs )
103 OUString ouIdAttr = getIdAttr(xAttribs);
104 if (!ouIdAttr.isEmpty())
106 m_pXSecController->collectToVerify( ouIdAttr );
109 if ( aName == "Signature" )
111 m_rXMLSignatureHelper.StartVerifySignatureElement();
112 m_pXSecController->addSignature();
113 if (!ouIdAttr.isEmpty())
115 m_pXSecController->setId( ouIdAttr );
118 else if ( aName == "Reference" )
120 OUString ouUri = xAttribs->getValueByName("URI");
121 SAL_WARN_IF( ouUri.isEmpty(), "xmlsecurity.helper", "URI is empty" );
122 if (ouUri.startsWith("#"))
125 * remove the first character '#' from the attribute value
127 m_pXSecController->addReference( ouUri.copy(1), m_nReferenceDigestID );
129 else
132 * remember the uri
134 m_currentReferenceURI = ouUri;
135 m_bReferenceUnresolved = true;
138 else if (aName == "DigestMethod")
140 OUString ouAlgorithm = xAttribs->getValueByName("Algorithm");
142 SAL_WARN_IF( ouAlgorithm.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" );
143 if (!ouAlgorithm.isEmpty())
145 SAL_WARN_IF( ouAlgorithm != ALGO_XMLDSIGSHA1
146 && ouAlgorithm != ALGO_XMLDSIGSHA256
147 && ouAlgorithm != ALGO_XMLDSIGSHA512,
148 "xmlsecurity.helper", "Algorithm neither SHA1, SHA256 nor SHA512");
149 if (ouAlgorithm == ALGO_XMLDSIGSHA1)
150 m_nReferenceDigestID = cssxc::DigestID::SHA1;
151 else if (ouAlgorithm == ALGO_XMLDSIGSHA256)
152 m_nReferenceDigestID = cssxc::DigestID::SHA256;
153 else if (ouAlgorithm == ALGO_XMLDSIGSHA512)
154 m_nReferenceDigestID = cssxc::DigestID::SHA512;
155 else
156 m_nReferenceDigestID = 0;
159 else if (aName == "Transform")
161 if ( m_bReferenceUnresolved )
163 OUString ouAlgorithm = xAttribs->getValueByName("Algorithm");
165 if (ouAlgorithm == ALGO_C14N)
167 * a xml stream
170 m_pXSecController->addStreamReference( m_currentReferenceURI, false, m_nReferenceDigestID );
171 m_bReferenceUnresolved = false;
175 else if (aName == "X509IssuerName")
177 m_ouX509IssuerName.clear();
178 m_bInX509IssuerName = true;
180 else if (aName == "X509SerialNumber")
182 m_ouX509SerialNumber.clear();
183 m_bInX509SerialNumber = true;
185 else if (aName == "X509Certificate")
187 m_ouX509Certificate.clear();
188 m_bInX509Certificate = true;
190 else if (aName == "PGPData")
192 m_pXSecController->switchGpgSignature();
194 else if (aName == "PGPKeyID")
196 m_ouGpgKeyID.clear();
197 m_bInGpgKeyID = true;
199 else if (aName == "PGPKeyPacket")
201 m_ouGpgCertificate.clear();
202 m_bInGpgCertificate = true;
204 else if (aName == "loext:PGPOwner")
206 m_ouGpgOwner.clear();
207 m_bInGpgOwner = true;
209 else if (aName == "SignatureValue")
211 m_ouSignatureValue.clear();
212 m_bInSignatureValue = true;
214 else if (aName == "DigestValue" && !m_bInCertDigest)
216 m_ouDigestValue.clear();
217 m_bInDigestValue = true;
219 else if (aName == "xd:CertDigest")
221 m_ouCertDigest.clear();
222 m_bInCertDigest = true;
224 // FIXME: Existing code here in xmlsecurity uses "xd" as the namespace prefix for XAdES,
225 // while the sample document attached to tdf#76142 uses "xades". So accept either here. Of
226 // course this is idiotic and wrong, the right thing would be to use a proper way to parse
227 // XML that would handle namespaces correctly. I have no idea how substantial re-plumbing of
228 // this code that would require.
229 else if (aName == "xd:EncapsulatedX509Certificate" || aName == "xades:EncapsulatedX509Certificate")
231 m_ouEncapsulatedX509Certificate.clear();
232 m_bInEncapsulatedX509Certificate = true;
234 else if (aName == "xd:SigningTime" || aName == "xades:SigningTime")
236 m_ouDate.clear();
237 m_bInSigningTime = true;
239 else if ( aName == "SignatureProperty" )
241 if (!ouIdAttr.isEmpty())
243 m_pXSecController->setPropertyId( ouIdAttr );
246 else if (aName == "dc:date")
248 if (m_ouDate.isEmpty())
249 m_bInDate = true;
251 else if (aName == "dc:description")
253 m_ouDescription.clear();
254 m_bInDescription = true;
256 else if (aName == "loext:SignatureLineId")
258 m_ouSignatureLineId.clear();
259 m_bInSignatureLineId = true;
262 if (m_xNextHandler.is())
264 m_xNextHandler->startElement(aName, xAttribs);
267 catch (cssu::Exception& )
268 {//getCaughtException MUST be the first line in the catch block
269 cssu::Any exc = cppu::getCaughtException();
270 throw cssxs::SAXException(
271 "xmlsecurity: Exception in XSecParser::startElement",
272 nullptr, exc);
274 catch (...)
276 throw cssxs::SAXException(
277 "xmlsecurity: unexpected exception in XSecParser::startElement", nullptr,
278 cssu::Any());
282 void SAL_CALL XSecParser::endElement( const OUString& aName )
286 if (aName == "DigestValue" && !m_bInCertDigest)
288 m_bInDigestValue = false;
290 else if ( aName == "Reference" )
292 if ( m_bReferenceUnresolved )
294 * it must be a octet stream
297 m_pXSecController->addStreamReference( m_currentReferenceURI, true, m_nReferenceDigestID );
298 m_bReferenceUnresolved = false;
301 m_pXSecController->setDigestValue( m_nReferenceDigestID, m_ouDigestValue );
303 else if ( aName == "SignedInfo" )
305 m_pXSecController->setReferenceCount();
307 else if ( aName == "SignatureValue" )
309 m_pXSecController->setSignatureValue( m_ouSignatureValue );
310 m_bInSignatureValue = false;
312 else if (aName == "X509IssuerName")
314 m_pXSecController->setX509IssuerName( m_ouX509IssuerName );
315 m_bInX509IssuerName = false;
317 else if (aName == "X509SerialNumber")
319 m_pXSecController->setX509SerialNumber( m_ouX509SerialNumber );
320 m_bInX509SerialNumber = false;
322 else if (aName == "X509Certificate")
324 m_pXSecController->setX509Certificate( m_ouX509Certificate );
325 m_bInX509Certificate = false;
327 else if (aName == "PGPKeyID")
329 m_pXSecController->setGpgKeyID( m_ouGpgKeyID );
330 m_bInGpgKeyID = false;
332 else if (aName == "PGPKeyPacket")
334 m_pXSecController->setGpgCertificate( m_ouGpgCertificate );
335 m_bInGpgCertificate = false;
337 else if (aName == "loext:PGPOwner")
339 m_pXSecController->setGpgOwner( m_ouGpgOwner );
340 m_bInGpgOwner = false;
342 else if (aName == "xd:CertDigest")
344 m_pXSecController->setCertDigest( m_ouCertDigest );
345 m_bInCertDigest = false;
347 else if (aName == "xd:EncapsulatedX509Certificate" || aName == "xades:EncapsulatedX509Certificate")
349 m_pXSecController->addEncapsulatedX509Certificate( m_ouEncapsulatedX509Certificate );
350 m_bInEncapsulatedX509Certificate = false;
352 else if (aName == "xd:SigningTime" || aName == "xades:SigningTime")
354 m_pXSecController->setDate( m_ouDate );
355 m_bInSigningTime = false;
357 else if (aName == "dc:date")
359 if (m_bInDate)
361 m_pXSecController->setDate( m_ouDate );
362 m_bInDate = false;
365 else if (aName == "dc:description")
367 m_pXSecController->setDescription( m_ouDescription );
368 m_bInDescription = false;
370 else if (aName == "loext:SignatureLineId")
372 m_pXSecController->setSignatureLineId( m_ouSignatureLineId );
373 m_bInSignatureLineId = false;
376 if (m_xNextHandler.is())
378 m_xNextHandler->endElement(aName);
381 catch (cssu::Exception& )
382 {//getCaughtException MUST be the first line in the catch block
383 cssu::Any exc = cppu::getCaughtException();
384 throw cssxs::SAXException(
385 "xmlsecurity: Exception in XSecParser::endElement",
386 nullptr, exc);
388 catch (...)
390 throw cssxs::SAXException(
391 "xmlsecurity: unexpected exception in XSecParser::endElement", nullptr,
392 cssu::Any());
396 void SAL_CALL XSecParser::characters( const OUString& aChars )
398 if (m_bInX509IssuerName)
400 m_ouX509IssuerName += aChars;
402 else if (m_bInX509SerialNumber)
404 m_ouX509SerialNumber += aChars;
406 else if (m_bInX509Certificate)
408 m_ouX509Certificate += aChars;
410 else if (m_bInGpgCertificate)
412 m_ouGpgCertificate += aChars;
414 else if (m_bInGpgKeyID)
416 m_ouGpgKeyID += aChars;
418 else if (m_bInGpgOwner)
420 m_ouGpgOwner += aChars;
422 else if (m_bInSignatureValue)
424 m_ouSignatureValue += aChars;
426 else if (m_bInDigestValue && !m_bInCertDigest)
428 m_ouDigestValue += aChars;
430 else if (m_bInDate)
432 m_ouDate += aChars;
434 else if (m_bInDescription)
436 m_ouDescription += aChars;
438 else if (m_bInCertDigest)
440 m_ouCertDigest += aChars;
442 else if (m_bInEncapsulatedX509Certificate)
444 m_ouEncapsulatedX509Certificate += aChars;
446 else if (m_bInSigningTime)
448 m_ouDate += aChars;
450 else if (m_bInSignatureLineId)
452 m_ouSignatureLineId += aChars;
455 if (m_xNextHandler.is())
457 m_xNextHandler->characters(aChars);
461 void SAL_CALL XSecParser::ignorableWhitespace( const OUString& aWhitespaces )
463 if (m_xNextHandler.is())
465 m_xNextHandler->ignorableWhitespace( aWhitespaces );
469 void SAL_CALL XSecParser::processingInstruction( const OUString& aTarget, const OUString& aData )
471 if (m_xNextHandler.is())
473 m_xNextHandler->processingInstruction(aTarget, aData);
477 void SAL_CALL XSecParser::setDocumentLocator( const cssu::Reference< cssxs::XLocator >& xLocator )
479 if (m_xNextHandler.is())
481 m_xNextHandler->setDocumentLocator( xLocator );
486 * XInitialization
488 void SAL_CALL XSecParser::initialize(
489 const cssu::Sequence< cssu::Any >& aArguments )
491 aArguments[0] >>= m_xNextHandler;
494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */