1632 lines
55 KiB
C++
1632 lines
55 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
|
|
#include "xsecparser.hxx"
|
|
#include <xsecctl.hxx>
|
|
#include <xmlsignaturehelper.hxx>
|
|
|
|
#include <xmloff/xmlnamespace.hxx>
|
|
#include <xmloff/xmltoken.hxx>
|
|
#include <xmloff/xmlimp.hxx>
|
|
|
|
#include <com/sun/star/xml/sax/SAXException.hpp>
|
|
#include <cppuhelper/exc_hlp.hxx>
|
|
#include <sal/log.hxx>
|
|
|
|
class XSecParser::Context
|
|
{
|
|
protected:
|
|
friend class XSecParser;
|
|
XSecParser & m_rParser;
|
|
private:
|
|
std::optional<SvXMLNamespaceMap> m_pOldNamespaceMap;
|
|
|
|
public:
|
|
Context(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: m_rParser(rParser)
|
|
, m_pOldNamespaceMap(std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual ~Context() = default;
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/)
|
|
{
|
|
}
|
|
|
|
virtual void EndElement()
|
|
{
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/);
|
|
|
|
virtual void Characters(OUString const& /*rChars*/)
|
|
{
|
|
}
|
|
};
|
|
|
|
// it's possible that an unsupported element has an Id attribute and a
|
|
// ds:Reference digesting it - probably this means XSecController needs to know
|
|
// about it. (For known elements, the Id attribute is only processed according
|
|
// to the schema.)
|
|
class XSecParser::UnknownContext
|
|
: public XSecParser::Context
|
|
{
|
|
public:
|
|
UnknownContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
m_rParser.HandleIdAttr(xAttrs);
|
|
}
|
|
};
|
|
|
|
auto XSecParser::Context::CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const /*nNamespace*/, OUString const& /*rName*/)
|
|
-> std::unique_ptr<Context>
|
|
{
|
|
// default: create new base context
|
|
return std::make_unique<UnknownContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
|
|
/**
|
|
note: anything in ds:Object should be trusted *only* if there is a ds:Reference
|
|
to it so it is signed (exception: the xades:EncapsulatedX509Certificate).
|
|
ds:SignedInfo precedes all ds:Object.
|
|
|
|
There may be multiple ds:Signature for purpose of counter-signatures
|
|
but the way XAdES describes these, only the ds:SignatureValue element
|
|
would be referenced, so requiring a ds:Reference for anything in
|
|
ds:Object shouldn't cause issues.
|
|
*/
|
|
class XSecParser::ReferencedContextImpl
|
|
: public XSecParser::Context
|
|
{
|
|
protected:
|
|
bool m_isReferenced;
|
|
|
|
public:
|
|
ReferencedContextImpl(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
, m_isReferenced(isReferenced)
|
|
{
|
|
}
|
|
|
|
OUString CheckIdAttrReferenced(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs)
|
|
{
|
|
OUString const id(m_rParser.HandleIdAttr(xAttrs));
|
|
if (!id.isEmpty() && m_rParser.m_pXSecController->haveReferenceForId(id))
|
|
{
|
|
m_isReferenced = true;
|
|
}
|
|
return id;
|
|
}
|
|
};
|
|
|
|
class XSecParser::LoPGPOwnerContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString m_Value;
|
|
|
|
public:
|
|
LoPGPOwnerContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
m_rParser.m_pXSecController->setGpgOwner(m_Value);
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_Value += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsPGPKeyPacketContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString m_Value;
|
|
|
|
public:
|
|
DsPGPKeyPacketContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
m_rParser.m_pXSecController->setGpgCertificate(m_Value);
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_Value += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsPGPKeyIDContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString m_Value;
|
|
|
|
public:
|
|
DsPGPKeyIDContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
m_rParser.m_pXSecController->setGpgKeyID(m_Value);
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_Value += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsPGPDataContext
|
|
: public XSecParser::Context
|
|
{
|
|
public:
|
|
DsPGPDataContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) override
|
|
{
|
|
m_rParser.m_pXSecController->switchGpgSignature();
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "PGPKeyID")
|
|
{
|
|
return std::make_unique<DsPGPKeyIDContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "PGPKeyPacket")
|
|
{
|
|
return std::make_unique<DsPGPKeyPacketContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "PGPOwner")
|
|
{
|
|
return std::make_unique<LoPGPOwnerContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsX509CertificateContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString & m_rValue;
|
|
|
|
public:
|
|
DsX509CertificateContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
OUString& rValue)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
, m_rValue(rValue)
|
|
{
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_rValue += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsX509SerialNumberContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString & m_rValue;
|
|
|
|
public:
|
|
DsX509SerialNumberContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
OUString& rValue)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
, m_rValue(rValue)
|
|
{
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_rValue += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsX509IssuerNameContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString & m_rValue;
|
|
|
|
public:
|
|
DsX509IssuerNameContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
OUString& rValue)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
, m_rValue(rValue)
|
|
{
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_rValue += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsX509IssuerSerialContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString & m_rX509IssuerName;
|
|
OUString & m_rX509SerialNumber;
|
|
|
|
public:
|
|
DsX509IssuerSerialContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
OUString& rIssuerName, OUString& rSerialNumber)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
, m_rX509IssuerName(rIssuerName)
|
|
, m_rX509SerialNumber(rSerialNumber)
|
|
{
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerName")
|
|
{
|
|
return std::make_unique<DsX509IssuerNameContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509IssuerName);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "X509SerialNumber")
|
|
{
|
|
return std::make_unique<DsX509SerialNumberContext>(m_rParser, std::move(pOldNamespaceMap), m_rX509SerialNumber);
|
|
}
|
|
// missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
/// can't be sure what is supposed to happen here because the spec is clear as mud
|
|
class XSecParser::DsX509DataContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
// sigh... "No ordering is implied by the above constraints."
|
|
// so store the ball of mud in vectors and try to figure it out later.
|
|
std::vector<std::pair<OUString, OUString>> m_X509IssuerSerials;
|
|
std::vector<OUString> m_X509Certificates;
|
|
|
|
public:
|
|
DsX509DataContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
m_rParser.m_pXSecController->setX509Data(m_X509IssuerSerials, m_X509Certificates);
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "X509IssuerSerial")
|
|
{
|
|
m_X509IssuerSerials.emplace_back();
|
|
return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerSerials.back().first, m_X509IssuerSerials.back().second);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "X509Certificate")
|
|
{
|
|
m_X509Certificates.emplace_back();
|
|
return std::make_unique<DsX509CertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_X509Certificates.back());
|
|
}
|
|
// missing: ds:X509SKI, ds:X509SubjectName, ds:X509CRL
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsKeyInfoContext
|
|
: public XSecParser::Context
|
|
{
|
|
public:
|
|
DsKeyInfoContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
m_rParser.HandleIdAttr(xAttrs);
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "X509Data")
|
|
{
|
|
return std::make_unique<DsX509DataContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "PGPData")
|
|
{
|
|
return std::make_unique<DsPGPDataContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
// missing: ds:KeyName, ds:KeyValue, ds:RetrievalMethod, ds:SPKIData, ds:MgmtData
|
|
// (old code would read ds:Transform inside ds:RetrievalMethod but
|
|
// presumably that was a bug)
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
|
|
};
|
|
|
|
class XSecParser::DsSignatureValueContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString m_Value;
|
|
|
|
public:
|
|
DsSignatureValueContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
m_rParser.HandleIdAttr(xAttrs);
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
m_rParser.m_pXSecController->setSignatureValue(m_Value);
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_Value += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsDigestValueContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString & m_rValue;
|
|
|
|
public:
|
|
DsDigestValueContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
OUString& rValue)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
, m_rValue(rValue)
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& /*xAttrs*/) override
|
|
{
|
|
m_rValue.clear();
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_rValue += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsDigestMethodContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
sal_Int32 & m_rReferenceDigestID;
|
|
|
|
public:
|
|
DsDigestMethodContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_Int32& rReferenceDigestID)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
, m_rReferenceDigestID(rReferenceDigestID)
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
OUString ouAlgorithm = xAttrs->getValueByName(u"Algorithm"_ustr);
|
|
|
|
SAL_WARN_IF( ouAlgorithm.isEmpty(), "xmlsecurity.helper", "no Algorithm in Reference" );
|
|
if (ouAlgorithm.isEmpty())
|
|
return;
|
|
|
|
SAL_WARN_IF( ouAlgorithm != ALGO_XMLDSIGSHA1
|
|
&& ouAlgorithm != ALGO_XMLDSIGSHA256
|
|
&& ouAlgorithm != ALGO_XMLDSIGSHA512,
|
|
"xmlsecurity.helper", "Algorithm neither SHA1, SHA256 nor SHA512");
|
|
if (ouAlgorithm == ALGO_XMLDSIGSHA1)
|
|
m_rReferenceDigestID = css::xml::crypto::DigestID::SHA1;
|
|
else if (ouAlgorithm == ALGO_XMLDSIGSHA256)
|
|
m_rReferenceDigestID = css::xml::crypto::DigestID::SHA256;
|
|
else if (ouAlgorithm == ALGO_XMLDSIGSHA512)
|
|
m_rReferenceDigestID = css::xml::crypto::DigestID::SHA512;
|
|
else
|
|
m_rReferenceDigestID = 0;
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsTransformContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
bool & m_rIsC14N;
|
|
|
|
public:
|
|
DsTransformContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool& rIsC14N)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
, m_rIsC14N(rIsC14N)
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
OUString ouAlgorithm = xAttrs->getValueByName(u"Algorithm"_ustr);
|
|
|
|
if (ouAlgorithm == ALGO_C14N)
|
|
/*
|
|
* a xml stream
|
|
*/
|
|
{
|
|
m_rIsC14N = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsTransformsContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
bool & m_rIsC14N;
|
|
|
|
public:
|
|
DsTransformsContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool& rIsC14N)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
, m_rIsC14N(rIsC14N)
|
|
{
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "Transform")
|
|
{
|
|
return std::make_unique<DsTransformContext>(m_rParser, std::move(pOldNamespaceMap), m_rIsC14N);
|
|
}
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsReferenceContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString m_URI;
|
|
OUString m_Type;
|
|
OUString m_DigestValue;
|
|
bool m_IsC14N = false;
|
|
// Relevant for ODF. The digest algorithm selected by the DigestMethod
|
|
// element's Algorithm attribute. @see css::xml::crypto::DigestID.
|
|
sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1;
|
|
|
|
public:
|
|
DsReferenceContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
m_rParser.HandleIdAttr(xAttrs);
|
|
|
|
m_URI = xAttrs->getValueByName(u"URI"_ustr);
|
|
SAL_WARN_IF(m_URI.isEmpty(), "xmlsecurity.helper", "URI is empty");
|
|
// Remember the type of this reference.
|
|
m_Type = xAttrs->getValueByName(u"Type"_ustr);
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
if (m_URI.startsWith("#"))
|
|
{
|
|
/*
|
|
* remove the first character '#' from the attribute value
|
|
*/
|
|
m_rParser.m_pXSecController->addReference(m_URI.copy(1), m_nReferenceDigestID, m_Type);
|
|
}
|
|
else
|
|
{
|
|
if (m_IsC14N) // this is determined by nested ds:Transform
|
|
{
|
|
m_rParser.m_pXSecController->addStreamReference(m_URI, false, m_nReferenceDigestID);
|
|
}
|
|
else
|
|
/*
|
|
* it must be an octet stream
|
|
*/
|
|
{
|
|
m_rParser.m_pXSecController->addStreamReference(m_URI, true, m_nReferenceDigestID);
|
|
}
|
|
}
|
|
|
|
m_rParser.m_pXSecController->setDigestValue(m_nReferenceDigestID, m_DigestValue);
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "Transforms")
|
|
{
|
|
return std::make_unique<DsTransformsContext>(m_rParser, std::move(pOldNamespaceMap), m_IsC14N);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod")
|
|
{
|
|
return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_nReferenceDigestID);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue")
|
|
{
|
|
return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_DigestValue);
|
|
}
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsSignatureMethodContext
|
|
: public XSecParser::Context
|
|
{
|
|
public:
|
|
DsSignatureMethodContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
OUString ouAlgorithm = xAttrs->getValueByName(u"Algorithm"_ustr);
|
|
if (ouAlgorithm == ALGO_ECDSASHA1 || ouAlgorithm == ALGO_ECDSASHA256
|
|
|| ouAlgorithm == ALGO_ECDSASHA512)
|
|
{
|
|
m_rParser.m_pXSecController->setSignatureMethod(svl::crypto::SignatureMethodAlgorithm::ECDSA);
|
|
}
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsSignedInfoContext
|
|
: public XSecParser::Context
|
|
{
|
|
public:
|
|
DsSignedInfoContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
m_rParser.HandleIdAttr(xAttrs);
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
m_rParser.m_pXSecController->setReferenceCount();
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureMethod")
|
|
{
|
|
return std::make_unique<DsSignatureMethodContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "Reference")
|
|
{
|
|
return std::make_unique<DsReferenceContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
// missing: ds:CanonicalizationMethod
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::XadesEncapsulatedX509CertificateContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString m_Value;
|
|
|
|
public:
|
|
XadesEncapsulatedX509CertificateContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
m_rParser.HandleIdAttr(xAttrs);
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
m_rParser.m_pXSecController->addEncapsulatedX509Certificate(m_Value);
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_Value += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::XadesCertificateValuesContext
|
|
: public XSecParser::Context
|
|
{
|
|
public:
|
|
XadesCertificateValuesContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
m_rParser.HandleIdAttr(xAttrs);
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_XADES132 && rName == "EncapsulatedX509Certificate")
|
|
{
|
|
return std::make_unique<XadesEncapsulatedX509CertificateContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
// missing: xades:OtherCertificate
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::XadesUnsignedSignaturePropertiesContext
|
|
: public XSecParser::Context
|
|
{
|
|
public:
|
|
XadesUnsignedSignaturePropertiesContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
m_rParser.HandleIdAttr(xAttrs);
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertificateValues")
|
|
{
|
|
return std::make_unique<XadesCertificateValuesContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
// missing:
|
|
// xades:CounterSignature
|
|
// ^ old code would read a ds:Signature inside it?
|
|
// xades:SignatureTimeStamp
|
|
// xades:CompleteCertificateRefs
|
|
// xades:CompleteRevocationRefs
|
|
// xades:AttributeCertificateRefs
|
|
// xades:AttributeRevocationRefs
|
|
// xades:SigAndRefsTimeStamp
|
|
// xades:RefsOnlyTimeStamp
|
|
// xades:RevocationValues
|
|
// xades:AttrAuthoritiesCertValues
|
|
// ^ old code: was equivalent to CertificateValues ???
|
|
// xades:AttributeRevocationValues
|
|
// xades:ArchiveTimeStamp
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::XadesUnsignedPropertiesContext
|
|
: public XSecParser::Context
|
|
{
|
|
public:
|
|
XadesUnsignedPropertiesContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
m_rParser.HandleIdAttr(xAttrs);
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedSignatureProperties")
|
|
{
|
|
return std::make_unique<XadesUnsignedSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
// missing: xades:UnsignedDataObjectProperties
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::LoSignatureLineIdContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
private:
|
|
OUString m_Value;
|
|
|
|
public:
|
|
LoSignatureLineIdContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
|
|
{
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
if (m_isReferenced)
|
|
{
|
|
m_rParser.m_pXSecController->setSignatureLineId(m_Value);
|
|
}
|
|
else
|
|
{
|
|
SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineId");
|
|
}
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_Value += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::LoSignatureLineValidImageContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
private:
|
|
OUString m_Value;
|
|
|
|
public:
|
|
LoSignatureLineValidImageContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
|
|
{
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
if (m_isReferenced)
|
|
{
|
|
m_rParser.m_pXSecController->setValidSignatureImage(m_Value);
|
|
}
|
|
else
|
|
{
|
|
SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineValidImage");
|
|
}
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_Value += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::LoSignatureLineInvalidImageContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
private:
|
|
OUString m_Value;
|
|
|
|
public:
|
|
LoSignatureLineInvalidImageContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
|
|
{
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
if (m_isReferenced)
|
|
{
|
|
m_rParser.m_pXSecController->setInvalidSignatureImage(m_Value);
|
|
}
|
|
else
|
|
{
|
|
SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureLineInvalidImage");
|
|
}
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_Value += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::LoSignatureLineContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
public:
|
|
LoSignatureLineContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
|
|
{
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineId")
|
|
{
|
|
return std::make_unique<LoSignatureLineIdContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineValidImage")
|
|
{
|
|
return std::make_unique<LoSignatureLineValidImageContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLineInvalidImage")
|
|
{
|
|
return std::make_unique<LoSignatureLineInvalidImageContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
|
|
}
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::XadesCertDigestContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString & m_rDigestValue;
|
|
sal_Int32 & m_rReferenceDigestID;
|
|
|
|
public:
|
|
XadesCertDigestContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
OUString& rDigestValue, sal_Int32& rReferenceDigestID)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
, m_rDigestValue(rDigestValue)
|
|
, m_rReferenceDigestID(rReferenceDigestID)
|
|
{
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "DigestMethod")
|
|
{
|
|
return std::make_unique<DsDigestMethodContext>(m_rParser, std::move(pOldNamespaceMap), m_rReferenceDigestID);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "DigestValue")
|
|
{
|
|
return std::make_unique<DsDigestValueContext>(m_rParser, std::move(pOldNamespaceMap), m_rDigestValue);
|
|
}
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::XadesCertContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
private:
|
|
sal_Int32 m_nReferenceDigestID = css::xml::crypto::DigestID::SHA1;
|
|
OUString m_CertDigest;
|
|
OUString m_X509IssuerName;
|
|
OUString m_X509SerialNumber;
|
|
|
|
public:
|
|
XadesCertContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
|
|
{
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
if (m_isReferenced)
|
|
{
|
|
m_rParser.m_pXSecController->setX509CertDigest(m_CertDigest, m_nReferenceDigestID, m_X509IssuerName, m_X509SerialNumber);
|
|
}
|
|
else
|
|
{
|
|
SAL_INFO("xmlsecurity.helper", "ignoring unsigned xades:Cert");
|
|
}
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_XADES132 && rName == "CertDigest")
|
|
{
|
|
return std::make_unique<XadesCertDigestContext>(m_rParser, std::move(pOldNamespaceMap), m_CertDigest, m_nReferenceDigestID);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_XADES132 && rName == "IssuerSerial")
|
|
{
|
|
return std::make_unique<DsX509IssuerSerialContext>(m_rParser, std::move(pOldNamespaceMap), m_X509IssuerName, m_X509SerialNumber);
|
|
}
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::XadesSigningCertificateContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
public:
|
|
XadesSigningCertificateContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
|
|
{
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_XADES132 && rName == "Cert")
|
|
{
|
|
return std::make_unique<XadesCertContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
|
|
}
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::XadesSigningTimeContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
private:
|
|
OUString m_Value;
|
|
|
|
public:
|
|
XadesSigningTimeContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
|
|
{
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
if (m_isReferenced)
|
|
{
|
|
m_rParser.m_pXSecController->setDate(u""_ustr, m_Value);
|
|
}
|
|
else
|
|
{
|
|
SAL_INFO("xmlsecurity.helper", "ignoring unsigned SigningTime");
|
|
}
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_Value += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::XadesSignedSignaturePropertiesContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
public:
|
|
XadesSignedSignaturePropertiesContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
CheckIdAttrReferenced(xAttrs);
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningTime")
|
|
{
|
|
return std::make_unique<XadesSigningTimeContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SigningCertificate")
|
|
{
|
|
return std::make_unique<XadesSigningCertificateContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_LO_EXT && rName == "SignatureLine")
|
|
{
|
|
return std::make_unique<LoSignatureLineContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
|
|
}
|
|
// missing: xades:SignaturePolicyIdentifier, xades:SignatureProductionPlace, xades:SignerRole
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::XadesSignedPropertiesContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
public:
|
|
XadesSignedPropertiesContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
CheckIdAttrReferenced(xAttrs);
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedSignatureProperties")
|
|
{
|
|
return std::make_unique<XadesSignedSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
|
|
}
|
|
// missing: xades:SignedDataObjectProperties
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::XadesQualifyingPropertiesContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
public:
|
|
XadesQualifyingPropertiesContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
CheckIdAttrReferenced(xAttrs);
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_XADES132 && rName == "SignedProperties")
|
|
{
|
|
return std::make_unique<XadesSignedPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_XADES132 && rName == "UnsignedProperties")
|
|
{
|
|
return std::make_unique<XadesUnsignedPropertiesContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::DcDateContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString & m_rValue;
|
|
|
|
public:
|
|
DcDateContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
OUString& rValue)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
, m_rValue(rValue)
|
|
{
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_rValue += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::DcDescriptionContext
|
|
: public XSecParser::Context
|
|
{
|
|
private:
|
|
OUString & m_rValue;
|
|
|
|
public:
|
|
DcDescriptionContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
OUString& rValue)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
, m_rValue(rValue)
|
|
{
|
|
}
|
|
|
|
virtual void Characters(OUString const& rChars) override
|
|
{
|
|
m_rValue += rChars;
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsSignaturePropertyContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
private:
|
|
enum class SignatureProperty { Unknown, Date, Description };
|
|
SignatureProperty m_Property = SignatureProperty::Unknown;
|
|
OUString m_Id;
|
|
OUString m_Value;
|
|
|
|
public:
|
|
DsSignaturePropertyContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
m_Id = CheckIdAttrReferenced(xAttrs);
|
|
}
|
|
|
|
virtual void EndElement() override
|
|
{
|
|
if (m_isReferenced)
|
|
{
|
|
switch (m_Property)
|
|
{
|
|
case SignatureProperty::Unknown:
|
|
SAL_INFO("xmlsecurity.helper", "Unknown property in ds:Object ignored");
|
|
break;
|
|
case SignatureProperty::Date:
|
|
m_rParser.m_pXSecController->setDate(m_Id, m_Value);
|
|
break;
|
|
case SignatureProperty::Description:
|
|
m_rParser.m_pXSecController->setDescription(m_Id, m_Value);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SAL_INFO("xmlsecurity.helper", "ignoring unsigned SignatureProperty");
|
|
}
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DC && rName == "date")
|
|
{
|
|
m_Property = SignatureProperty::Date;
|
|
return std::make_unique<DcDateContext>(m_rParser, std::move(pOldNamespaceMap), m_Value);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_DC && rName == "description")
|
|
{
|
|
m_Property = SignatureProperty::Description;
|
|
return std::make_unique<DcDescriptionContext>(m_rParser, std::move(pOldNamespaceMap), m_Value);
|
|
}
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsSignaturePropertiesContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
public:
|
|
DsSignaturePropertiesContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
bool const isReferenced)
|
|
: ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), isReferenced)
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
CheckIdAttrReferenced(xAttrs);
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperty")
|
|
{
|
|
return std::make_unique<DsSignaturePropertyContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
|
|
}
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsObjectContext
|
|
: public XSecParser::ReferencedContextImpl
|
|
{
|
|
public:
|
|
DsObjectContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
// init with "false" here - the Signature element can't be referenced by its child
|
|
: XSecParser::ReferencedContextImpl(rParser, std::move(pOldNamespaceMap), false)
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
CheckIdAttrReferenced(xAttrs);
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureProperties")
|
|
{
|
|
return std::make_unique<DsSignaturePropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_XADES132 && rName == "QualifyingProperties")
|
|
{
|
|
return std::make_unique<XadesQualifyingPropertiesContext>(m_rParser, std::move(pOldNamespaceMap), m_isReferenced);
|
|
}
|
|
// missing: ds:Manifest
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsSignatureContext
|
|
: public XSecParser::Context
|
|
{
|
|
public:
|
|
DsSignatureContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual void StartElement(
|
|
css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs) override
|
|
{
|
|
OUString const ouIdAttr(m_rParser.HandleIdAttr(xAttrs));
|
|
m_rParser.m_rXMLSignatureHelper.StartVerifySignatureElement();
|
|
m_rParser.m_pXSecController->addSignature();
|
|
if (!ouIdAttr.isEmpty())
|
|
{
|
|
m_rParser.m_pXSecController->setId( ouIdAttr );
|
|
}
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "SignedInfo")
|
|
{
|
|
return std::make_unique<DsSignedInfoContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "SignatureValue")
|
|
{
|
|
return std::make_unique<DsSignatureValueContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "KeyInfo")
|
|
{
|
|
return std::make_unique<DsKeyInfoContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "Object")
|
|
{
|
|
return std::make_unique<DsObjectContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
class XSecParser::DsigSignaturesContext
|
|
: public XSecParser::Context
|
|
{
|
|
public:
|
|
DsigSignaturesContext(XSecParser& rParser,
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap)
|
|
: XSecParser::Context(rParser, std::move(pOldNamespaceMap))
|
|
{
|
|
}
|
|
|
|
virtual std::unique_ptr<Context> CreateChildContext(
|
|
std::optional<SvXMLNamespaceMap>&& pOldNamespaceMap,
|
|
sal_uInt16 const nNamespace, OUString const& rName) override
|
|
{
|
|
if (nNamespace == XML_NAMESPACE_DS && rName == "Signature")
|
|
{
|
|
return std::make_unique<DsSignatureContext>(m_rParser, std::move(pOldNamespaceMap));
|
|
}
|
|
return XSecParser::Context::CreateChildContext(std::move(pOldNamespaceMap), nNamespace, rName);
|
|
}
|
|
};
|
|
|
|
|
|
XSecParser::XSecParser(XMLSignatureHelper& rXMLSignatureHelper,
|
|
XSecController* pXSecController)
|
|
: m_pNamespaceMap(SvXMLNamespaceMap())
|
|
, m_pXSecController(pXSecController)
|
|
, m_rXMLSignatureHelper(rXMLSignatureHelper)
|
|
{
|
|
using namespace xmloff::token;
|
|
m_pNamespaceMap->Add( GetXMLToken(XML_XML), GetXMLToken(XML_N_XML), XML_NAMESPACE_XML );
|
|
m_pNamespaceMap->Add( u"_dsig_ooo"_ustr, GetXMLToken(XML_N_DSIG_OOO), XML_NAMESPACE_DSIG_OOO );
|
|
m_pNamespaceMap->Add( u"_dsig"_ustr, GetXMLToken(XML_N_DSIG), XML_NAMESPACE_DSIG );
|
|
m_pNamespaceMap->Add( u"_ds"_ustr, GetXMLToken(XML_N_DS), XML_NAMESPACE_DS );
|
|
m_pNamespaceMap->Add( u"_xades132"_ustr, GetXMLToken(XML_N_XADES132), XML_NAMESPACE_XADES132);
|
|
m_pNamespaceMap->Add( u"_xades141"_ustr, GetXMLToken(XML_N_XADES141), XML_NAMESPACE_XADES141);
|
|
m_pNamespaceMap->Add( u"_dc"_ustr, GetXMLToken(XML_N_DC), XML_NAMESPACE_DC );
|
|
m_pNamespaceMap->Add( u"_office_libo"_ustr,
|
|
GetXMLToken(XML_N_LO_EXT), XML_NAMESPACE_LO_EXT);
|
|
}
|
|
|
|
OUString XSecParser::HandleIdAttr(css::uno::Reference<css::xml::sax::XAttributeList> const& xAttrs)
|
|
{
|
|
OUString ouIdAttr = getIdAttr(xAttrs);
|
|
if (!ouIdAttr.isEmpty())
|
|
{
|
|
m_pXSecController->collectToVerify( ouIdAttr );
|
|
}
|
|
return ouIdAttr;
|
|
}
|
|
|
|
OUString XSecParser::getIdAttr(const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs )
|
|
{
|
|
OUString ouIdAttr = xAttribs->getValueByName(u"id"_ustr);
|
|
|
|
if (ouIdAttr.isEmpty())
|
|
{
|
|
ouIdAttr = xAttribs->getValueByName(u"Id"_ustr);
|
|
}
|
|
|
|
return ouIdAttr;
|
|
}
|
|
|
|
/*
|
|
* XDocumentHandler
|
|
*/
|
|
void SAL_CALL XSecParser::startDocument( )
|
|
{
|
|
if (m_xNextHandler.is())
|
|
{
|
|
m_xNextHandler->startDocument();
|
|
}
|
|
}
|
|
|
|
void SAL_CALL XSecParser::endDocument( )
|
|
{
|
|
if (m_xNextHandler.is())
|
|
{
|
|
m_xNextHandler->endDocument();
|
|
}
|
|
}
|
|
|
|
void SAL_CALL XSecParser::startElement(
|
|
const OUString& rName,
|
|
const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs )
|
|
{
|
|
assert(m_pNamespaceMap);
|
|
std::optional<SvXMLNamespaceMap> pRewindMap(
|
|
SvXMLImport::processNSAttributes(m_pNamespaceMap, nullptr, xAttribs));
|
|
|
|
OUString localName;
|
|
sal_uInt16 const nPrefix(m_pNamespaceMap->GetKeyByAttrName(rName, &localName));
|
|
|
|
std::unique_ptr<Context> pContext;
|
|
|
|
if (m_ContextStack.empty())
|
|
{
|
|
if ((nPrefix != XML_NAMESPACE_DSIG && nPrefix != XML_NAMESPACE_DSIG_OOO)
|
|
|| localName != "document-signatures")
|
|
{
|
|
throw css::xml::sax::SAXException(
|
|
u"xmlsecurity: unexpected root element"_ustr, nullptr,
|
|
css::uno::Any());
|
|
}
|
|
|
|
pContext.reset(new DsigSignaturesContext(*this, std::move(pRewindMap)));
|
|
|
|
}
|
|
else
|
|
{
|
|
pContext = m_ContextStack.top()->CreateChildContext(
|
|
std::move(pRewindMap), nPrefix, localName);
|
|
}
|
|
|
|
m_ContextStack.push(std::move(pContext));
|
|
|
|
try
|
|
{
|
|
m_ContextStack.top()->StartElement(xAttribs);
|
|
|
|
if (m_xNextHandler.is())
|
|
{
|
|
m_xNextHandler->startElement(rName, xAttribs);
|
|
}
|
|
}
|
|
catch (css::uno::Exception& )
|
|
{//getCaughtException MUST be the first line in the catch block
|
|
css::uno::Any exc = cppu::getCaughtException();
|
|
throw css::xml::sax::SAXException(
|
|
u"xmlsecurity: Exception in XSecParser::startElement"_ustr,
|
|
nullptr, exc);
|
|
}
|
|
catch (...)
|
|
{
|
|
throw css::xml::sax::SAXException(
|
|
u"xmlsecurity: unexpected exception in XSecParser::startElement"_ustr, nullptr,
|
|
css::uno::Any());
|
|
}
|
|
}
|
|
|
|
void SAL_CALL XSecParser::endElement(const OUString& rName)
|
|
{
|
|
assert(!m_ContextStack.empty()); // this should be checked by sax parser?
|
|
|
|
try
|
|
{
|
|
m_ContextStack.top()->EndElement();
|
|
|
|
if (m_xNextHandler.is())
|
|
{
|
|
m_xNextHandler->endElement(rName);
|
|
}
|
|
}
|
|
catch (css::uno::Exception& )
|
|
{//getCaughtException MUST be the first line in the catch block
|
|
css::uno::Any exc = cppu::getCaughtException();
|
|
throw css::xml::sax::SAXException(
|
|
u"xmlsecurity: Exception in XSecParser::endElement"_ustr,
|
|
nullptr, exc);
|
|
}
|
|
catch (...)
|
|
{
|
|
throw css::xml::sax::SAXException(
|
|
u"xmlsecurity: unexpected exception in XSecParser::endElement"_ustr, nullptr,
|
|
css::uno::Any());
|
|
}
|
|
|
|
if (m_ContextStack.top()->m_pOldNamespaceMap)
|
|
{
|
|
m_pNamespaceMap = std::move(m_ContextStack.top()->m_pOldNamespaceMap);
|
|
}
|
|
m_ContextStack.pop();
|
|
}
|
|
|
|
void SAL_CALL XSecParser::characters(const OUString& rChars)
|
|
{
|
|
assert(!m_ContextStack.empty()); // this should be checked by sax parser?
|
|
m_ContextStack.top()->Characters(rChars);
|
|
|
|
if (m_xNextHandler.is())
|
|
{
|
|
m_xNextHandler->characters(rChars);
|
|
}
|
|
}
|
|
|
|
void SAL_CALL XSecParser::ignorableWhitespace( const OUString& aWhitespaces )
|
|
{
|
|
if (m_xNextHandler.is())
|
|
{
|
|
m_xNextHandler->ignorableWhitespace( aWhitespaces );
|
|
}
|
|
}
|
|
|
|
void SAL_CALL XSecParser::processingInstruction( const OUString& aTarget, const OUString& aData )
|
|
{
|
|
if (m_xNextHandler.is())
|
|
{
|
|
m_xNextHandler->processingInstruction(aTarget, aData);
|
|
}
|
|
}
|
|
|
|
void SAL_CALL XSecParser::setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator )
|
|
{
|
|
if (m_xNextHandler.is())
|
|
{
|
|
m_xNextHandler->setDocumentLocator( xLocator );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* XInitialization
|
|
*/
|
|
void SAL_CALL XSecParser::initialize(
|
|
const css::uno::Sequence< css::uno::Any >& aArguments )
|
|
{
|
|
aArguments[0] >>= m_xNextHandler;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|