Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  xsecverify.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * 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 <config_gpgme.h>

#include <xsecctl.hxx>
#include "xsecparser.hxx"
#include "ooxmlsecparser.hxx"
#include <biginteger.hxx>
#include <framework/signatureverifierimpl.hxx>
#include <framework/saxeventkeeperimpl.hxx>
#include <gpg/xmlsignature_gpgimpl.hxx>
#include <gpg/SEInitializer.hxx>

#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp>
#include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp>
#include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp>
#include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp>
#include <com/sun/star/xml/crypto/XSEInitializer.hpp>
#include <com/sun/star/graphic/GraphicProvider.hpp>
#include <com/sun/star/embed/StorageFormats.hpp>
#include <sal/log.hxx>
#include <unotools/datetime.hxx>
#include <comphelper/base64.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/propertyvalue.hxx>
#include <comphelper/seqstream.hxx>

namespace com::sun::star::graphic { class XGraphic; }

using namespace css;
using namespace css::uno;
using namespace css::beans;

/* protected: for signature verify */
css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > XSecController::prepareSignatureToRead(
    sal_Int32 nSecurityId)
{
    if ( m_eStatusOfSecurityComponents != InitializationState::INITIALIZED )
    {
        return nullptr;
    }

    sal_Int32 nIdOfSignatureElementCollector =
        m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY, false);

    m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId);

    /*
     * create a SignatureVerifier
     */

    rtl::Reference< SignatureVerifierImpl > xReferenceResolvedListener = new SignatureVerifierImpl;

    css::uno::Sequence<css::uno::Any> args
    {
        Any(OUString::number(nSecurityId)),
        Any(uno::Reference<xml::crypto::sax::XSecuritySAXEventKeeper>(m_xSAXEventKeeper)),
        Any(OUString::number(nIdOfSignatureElementCollector)),
        Any(m_xSecurityContext),
        Any(m_xXMLSignature)
    };
    xReferenceResolvedListener->initialize(args);

    xReferenceResolvedListener->addSignatureVerifyResultListener( this );

    m_xSAXEventKeeper->addReferenceResolvedListener(
        nIdOfSignatureElementCollector,
        xReferenceResolvedListener);

    xReferenceResolvedListener->setKeyId(0);

    return xReferenceResolvedListener;
}

void XSecController::addSignature()
{
    css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > xReferenceResolvedListener;
    sal_Int32 nSignatureId = 0;


    if (m_bVerifyCurrentSignature)
    {
        chainOn();
        xReferenceResolvedListener = prepareSignatureToRead( m_nReservedSignatureId );
        m_bVerifyCurrentSignature = false;
        nSignatureId = m_nReservedSignatureId;
    }

    InternalSignatureInformation isi( nSignatureId, xReferenceResolvedListener );
    m_vInternalSignatureInformations.push_back( isi );
}

void XSecController::setSignatureMethod(svl::crypto::SignatureMethodAlgorithm eAlgorithmID)
{
    if (m_vInternalSignatureInformations.empty())
        return;

    m_vInternalSignatureInformations.back().signatureInfor.eAlgorithmID = eAlgorithmID;
}

void XSecController::switchGpgSignature()
{
#if HAVE_FEATURE_GPGME
    // swap signature verifier for the Gpg one
    m_xXMLSignature.set(new XMLSignature_GpgImpl());
    if (m_vInternalSignatureInformations.empty())
        return;

    SignatureVerifierImpl* pImpl=
        dynamic_cast<SignatureVerifierImpl*>(
            m_vInternalSignatureInformations.back().xReferenceResolvedListener.get());
    if (pImpl)
    {
        css::uno::Reference<css::xml::crypto::XSEInitializer> xGpgSEInitializer(
            new SEInitializerGpg());
        pImpl->updateSignature(new XMLSignature_GpgImpl(),
                               xGpgSEInitializer->createSecurityContext(OUString()));
    }
#else
    (voidthis;
#endif
}

bool XSecController::haveReferenceForId(std::u16string_view rId) const
{
    if (m_vInternalSignatureInformations.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::haveReferenceForId: no signature");
        return false;
    }
    InternalSignatureInformation const& rIsi(m_vInternalSignatureInformations.back());
    for (SignatureReferenceInformation const& rSri : rIsi.signatureInfor.vSignatureReferenceInfors)
    {
        if (rSri.nType == SignatureReferenceType::SAMEDOCUMENT
            && rSri.ouURI == rId) // ouUri has # stripped
        {
            return true;
        }
    }
    return false;
}

void XSecController::addReference( const OUString& ouUri, sal_Int32 nDigestID, const OUString& ouType )
{
    if (m_vInternalSignatureInformations.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::addReference: no signature");
        return;
    }
    InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
    isi.addReference(SignatureReferenceType::SAMEDOCUMENT, nDigestID, ouUri, -1, ouType );
}

void XSecController::addStreamReference(
    const OUString& ouUri,
    bool isBinary,
    sal_Int32 nDigestID )
{
    SignatureReferenceType type = (isBinary?SignatureReferenceType::BINARYSTREAM:SignatureReferenceType::XMLSTREAM);

    if (m_vInternalSignatureInformations.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::addStreamReference: no signature");
        return;
    }
    InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();

    if ( isi.xReferenceResolvedListener.is() )
    {
            /*
             * get the input stream
             */

        css::uno::Reference< css::io::XInputStream > xObjectInputStream
                = getObjectInputStream( ouUri );

        if ( xObjectInputStream.is() )
        {
            css::uno::Reference<css::xml::crypto::XUriBinding> xUriBinding
                (isi.xReferenceResolvedListener, css::uno::UNO_QUERY);
            xUriBinding->setUriBinding(ouUri, xObjectInputStream);
        }
    }

    isi.addReference(type, nDigestID, ouUri, -1, OUString());
}

void XSecController::setReferenceCount() const
{
    if (m_vInternalSignatureInformations.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::setReferenceCount: no signature");
        return;
    }
    const InternalSignatureInformation &isi =
        m_vInternalSignatureInformations.back();

    if ( !isi.xReferenceResolvedListener.is() )
        return;

    const SignatureReferenceInformations &refInfors = isi.signatureInfor.vSignatureReferenceInfors;

    int refNum = refInfors.size();
    sal_Int32 referenceCount = 0;

    for(int i=0 ; i<refNum; ++i)
    {
        if (refInfors[i].nType == SignatureReferenceType::SAMEDOCUMENT )
        /*
         * same-document reference
         */

        {
            referenceCount++;
        }
    }

    css::uno::Reference<css::xml::crypto::sax::XReferenceCollector> xReferenceCollector
        (isi.xReferenceResolvedListener, css::uno::UNO_QUERY);
    xReferenceCollector->setReferenceCount( referenceCount );
}

void XSecController::setX509Data(
        std::vector<std::pair<OUString, OUString>> & rX509IssuerSerials,
        std::vector<OUString> const& rX509Certificates)
{
    if (m_vInternalSignatureInformations.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::setX509IssuerName: no signature");
        return;
    }
    InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
    SignatureInformation::X509Data data;
    // due to the excessive flexibility of the spec it's possible that there
    // is both a reference to a cert and the cert itself in one X509Data
    for (OUString const& it : rX509Certificates)
    {
        try
        {
            data.emplace_back();
            data.back().X509Certificate = it;
            uno::Reference<xml::crypto::XSecurityEnvironment> const xSecEnv(m_xSecurityContext->getSecurityEnvironment());
            uno::Reference<security::XCertificate> const xCert(xSecEnv->createCertificateFromAscii(it));
            if (!xCert.is())
            {
                SAL_INFO("xmlsecurity.helper""cannot parse X509Certificate");
                continue// will be handled in CheckX509Data
            }
            OUString const issuerName(xCert->getIssuerName());
            OUString const serialNumber(xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber()));
            auto const iter = std::find_if(rX509IssuerSerials.begin(), rX509IssuerSerials.end(),
                [&](auto const& rX509IssuerSerial) {
                    return xmlsecurity::EqualDistinguishedNames(issuerName, rX509IssuerSerial.first, xmlsecurity::COMPAT_2ND)
                        && serialNumber == rX509IssuerSerial.second;
                });
            if (iter != rX509IssuerSerials.end())
            {
                data.back().X509IssuerName = iter->first;
                data.back().X509SerialNumber = iter->second;
                rX509IssuerSerials.erase(iter);
            }
        }
        catch (uno::Exception const&)
        {
            SAL_INFO("xmlsecurity.helper""cannot parse X509Certificate");
        }
    }
    // now handle any that are left...
    for (auto const& it : rX509IssuerSerials)
    {
        data.emplace_back();
        data.back().X509IssuerName = it.first;
        data.back().X509SerialNumber = it.second;
    }
    if (!data.empty())
    {
        isi.signatureInfor.X509Datas.push_back(data);
    }
}

void XSecController::setSignatureValue( OUString const & ouSignatureValue )
{
    if (m_vInternalSignatureInformations.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::setSignatureValue: no signature");
        return;
    }
    InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
    isi.signatureInfor.ouSignatureValue = ouSignatureValue;
}

void XSecController::setDigestValue( sal_Int32 nDigestID, OUString const & ouDigestValue )
{
    if (m_vInternalSignatureInformations.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::setDigestValue: no signature");
        return;
    }
    InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
    if (isi.signatureInfor.vSignatureReferenceInfors.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::setDigestValue: no signature reference");
        return;
    }
    SignatureReferenceInformation &reference =
        isi.signatureInfor.vSignatureReferenceInfors.back();
    reference.nDigestID = nDigestID;
    reference.ouDigestValue = ouDigestValue;
}

void XSecController::setGpgKeyID( OUString const & ouKeyID )
{
    if (m_vInternalSignatureInformations.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::setGpgKeyID: no signature");
        return;
    }
    InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
    isi.signatureInfor.ouGpgKeyID = ouKeyID;
}

void XSecController::setGpgCertificate( OUString const & ouGpgCert )
{
    if (m_vInternalSignatureInformations.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::setGpgCertificate: no signature");
        return;
    }
    InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
    isi.signatureInfor.ouGpgCertificate = ouGpgCert;
}

void XSecController::setGpgOwner( OUString const & ouGpgOwner )
{
    if (m_vInternalSignatureInformations.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::setGpgOwner: no signature");
        return;
    }
    InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
    isi.signatureInfor.ouGpgOwner = ouGpgOwner;
}

void XSecController::setDate(OUString const& rId, OUString const& ouDate)
{
    if (m_vInternalSignatureInformations.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::setDate: no signature");
        return;
    }
    InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
    // there may be multiple timestamps in a signature - check them for consistency
    if (!isi.signatureInfor.ouDateTime.isEmpty()
        && isi.signatureInfor.ouDateTime != ouDate)
    {
        isi.signatureInfor.hasInconsistentSigningTime = true;
    }
    (void)utl::ISO8601parseDateTime( ouDate, isi.signatureInfor.stDateTime);
    isi.signatureInfor.ouDateTime = ouDate;
    if (!rId.isEmpty())
    {
        isi.signatureInfor.ouDateTimePropertyId = rId;
    }
}

void XSecController::setDescription(OUString const& rId, OUString const& rDescription)
{
    if (m_vInternalSignatureInformations.empty())
        return;

    InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
    rInformation.signatureInfor.ouDescription = rDescription;
    if (!rId.isEmpty())
    {
        rInformation.signatureInfor.ouDescriptionPropertyId = rId;
    }
}

void XSecController::setSignatureBytes(const uno::Sequence<sal_Int8>& rBytes)
{
    if (m_vInternalSignatureInformations.empty())
        return;

    InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
    rInformation.signatureInfor.aSignatureBytes = rBytes;
}

void XSecController::setX509CertDigest(
    OUString const& rCertDigest, sal_Int32 const /*TODO nReferenceDigestID*/,
    std::u16string_view const& rX509IssuerName, std::u16string_view const& rX509SerialNumber)
{
    if (m_vInternalSignatureInformations.empty())
        return;

    InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
    for (auto & rData : rInformation.signatureInfor.X509Datas)
    {
        for (auto & it : rData)
        {
            if (xmlsecurity::EqualDistinguishedNames(it.X509IssuerName, rX509IssuerName, xmlsecurity::COMPAT_BOTH)
                && it.X509SerialNumber == rX509SerialNumber)
            {
                it.CertDigest = rCertDigest;
                return;
            }
        }
    }
    // fall-back: read the actual certificates
    for (auto & rData : rInformation.signatureInfor.X509Datas)
    {
        for (auto & it : rData)
        {
            if (!it.X509Certificate.isEmpty())
            {
                try
                {
                    uno::Reference<xml::crypto::XSecurityEnvironment> const xSecEnv(m_xSecurityContext->getSecurityEnvironment());
                    uno::Reference<security::XCertificate> const xCert(xSecEnv->createCertificateFromAscii(it.X509Certificate));
                    if (!xCert.is())
                    {
                        SAL_INFO("xmlsecurity.helper""cannot parse X509Certificate");
                    }
                    else if (xmlsecurity::EqualDistinguishedNames(xCert->getIssuerName(), rX509IssuerName, xmlsecurity::COMPAT_2ND)
                        && xmlsecurity::bigIntegerToNumericString(xCert->getSerialNumber()) == rX509SerialNumber)
                    {
                        it.CertDigest = rCertDigest;
                        // note: testInsertCertificate_PEM_DOCX requires these!
                        it.X509SerialNumber = rX509SerialNumber;
                        it.X509IssuerName = rX509IssuerName;
                        return;
                    }
                }
                catch (uno::Exception const&)
                {
                    SAL_INFO("xmlsecurity.helper""cannot parse X509Certificate");
                }
            }
        }
    }
    if (!rInformation.signatureInfor.ouGpgCertificate.isEmpty())
    {
        SAL_INFO_IF(rCertDigest != rInformation.signatureInfor.ouGpgKeyID,
            "xmlsecurity.helper""PGPKeyID vs CertDigest mismatch");
    }
    else
    {
        SAL_INFO("xmlsecurity.helper""cannot find X509Data for CertDigest");
    }
}

namespace {
Reference<css::graphic::XGraphic> lcl_getGraphicFromString(std::u16string_view rImage)
{
    Sequence<sal_Int8> seq;
    comphelper::Base64::decode(seq, rImage);

    Reference< graphic::XGraphic > xGraphic;
    if( !seq.hasElements() )
        return Reference<css::graphic::XGraphic>();

    Reference< graphic::XGraphicProvider > xGraphicProvider(
        graphic::GraphicProvider::create(comphelper::getProcessComponentContext()) );
    Reference< io::XInputStream > xInputStream( new ::comphelper::SequenceInputStream( seq ) );

    Sequence< PropertyValue > aArgs{ comphelper::makePropertyValue(u"InputStream"_ustr, xInputStream) };
    xGraphic = xGraphicProvider->queryGraphic(aArgs);

    return xGraphic;
}
}

void XSecController::setValidSignatureImage(std::u16string_view rValidSigImg)
{
    if (m_vInternalSignatureInformations.empty() || rValidSigImg.empty())
        return;

    InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
    rInformation.signatureInfor.aValidSignatureImage = lcl_getGraphicFromString(rValidSigImg);
}

void XSecController::setInvalidSignatureImage(std::u16string_view rInvalidSigImg)
{
    if (m_vInternalSignatureInformations.empty() || rInvalidSigImg.empty())
        return;

    InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
    rInformation.signatureInfor.aInvalidSignatureImage = lcl_getGraphicFromString(rInvalidSigImg);
}

void XSecController::setSignatureLineId(const OUString& rSignatureLineId)
{
    if (m_vInternalSignatureInformations.empty())
        return;

    InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
    rInformation.signatureInfor.ouSignatureLineId = rSignatureLineId;
}

void XSecController::addEncapsulatedX509Certificate(const OUString& rEncapsulatedX509Certificate)
{
    if (m_vInternalSignatureInformations.empty())
        return;

    if (rEncapsulatedX509Certificate.isEmpty())
        return;

    InternalSignatureInformation& rInformation = m_vInternalSignatureInformations.back();
    rInformation.signatureInfor.maEncapsulatedX509Certificates.insert(rEncapsulatedX509Certificate);
}

void XSecController::setId( OUString const & ouId )
{
    if (m_vInternalSignatureInformations.empty())
    {
        SAL_INFO("xmlsecurity.helper","XSecController::setId: no signature");
        return;
    }
    InternalSignatureInformation &isi = m_vInternalSignatureInformations.back();
    isi.signatureInfor.ouSignatureId = ouId;
}

/* public: for signature verify */
void XSecController::collectToVerify( std::u16string_view referenceId )
{
    /* SAL_WARN_IF( !m_xSAXEventKeeper.is(), "xmlsecurity", "the SAXEventKeeper is NULL" ); */

    if ( m_eStatusOfSecurityComponents != InitializationState::INITIALIZED )
    /*
     * if all security components are ready, verify the signature.
     */

        return;

    bool bJustChainingOn = false;
    css::uno::Reference< css::xml::sax::XDocumentHandler > xHandler;

    int i,j;
    int sigNum = m_vInternalSignatureInformations.size();

    for (i=0; i<sigNum; ++i)
    {
        InternalSignatureInformation& isi = m_vInternalSignatureInformations[i];
        SignatureReferenceInformations& vReferenceInfors = isi.signatureInfor.vSignatureReferenceInfors;
        int refNum = vReferenceInfors.size();

        for (j=0; j<refNum; ++j)
        {
            SignatureReferenceInformation &refInfor = vReferenceInfors[j];

            if (refInfor.ouURI == referenceId)
            {
                if (chainOn())
                {
                    bJustChainingOn = true;
                    xHandler = m_xSAXEventKeeper->setNextHandler(nullptr);
                }

                sal_Int32 nKeeperId = m_xSAXEventKeeper->addSecurityElementCollector(
                    css::xml::crypto::sax::ElementMarkPriority_BEFOREMODIFY, false );

                css::uno::Reference<css::xml::crypto::sax::XReferenceCollector> xReferenceCollector
                    ( isi.xReferenceResolvedListener, css::uno::UNO_QUERY );

                m_xSAXEventKeeper->setSecurityId(nKeeperId, isi.signatureInfor.nSecurityId);
                m_xSAXEventKeeper->addReferenceResolvedListener( nKeeperId, isi.xReferenceResolvedListener);
                xReferenceCollector->setReferenceId( nKeeperId );

                isi.vKeeperIds[j] = nKeeperId;
                break;
            }
        }
    }

    if ( bJustChainingOn )
    {
        m_xSAXEventKeeper->setNextHandler(xHandler);
    }
}

void XSecController::addSignature( sal_Int32 nSignatureId )
{
    SAL_WARN_IF( !m_xSecParser.is(), "xmlsecurity.helper""No XSecParser initialized" );

    m_nReservedSignatureId = nSignatureId;
    m_bVerifyCurrentSignature = true;
}

css::uno::Reference< css::xml::sax::XDocumentHandler > const & XSecController::createSignatureReader(XMLSignatureHelper& rXMLSignatureHelper, sal_Int32 nType)
{
    if (nType == embed::StorageFormats::OFOPXML)
        m_xSecParser = new OOXMLSecParser(rXMLSignatureHelper, this);
    else
        m_xSecParser = new XSecParser(rXMLSignatureHelper, this);
    css::uno::Reference< css::lang::XInitialization > xInitialization(m_xSecParser, uno::UNO_QUERY);

    setSAXChainConnector(xInitialization);

    return m_xSecParser;
}

void XSecController::releaseSignatureReader()
{
    clearSAXChainConnector( );
    m_xSecParser.clear();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=83 H=95 G=88

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge