diff options
Diffstat (limited to 'xmlsecurity/source/helper')
-rw-r--r-- | xmlsecurity/source/helper/documentsignaturehelper.cxx | 462 | ||||
-rw-r--r-- | xmlsecurity/source/helper/makefile.mk | 54 | ||||
-rw-r--r-- | xmlsecurity/source/helper/xmlsignaturehelper.cxx | 467 | ||||
-rw-r--r-- | xmlsecurity/source/helper/xmlsignaturehelper2.cxx | 232 | ||||
-rw-r--r-- | xmlsecurity/source/helper/xmlsignaturehelper2.hxx | 134 | ||||
-rw-r--r-- | xmlsecurity/source/helper/xsecctl.cxx | 1498 | ||||
-rw-r--r-- | xmlsecurity/source/helper/xsecctl.hxx | 577 | ||||
-rw-r--r-- | xmlsecurity/source/helper/xsecparser.cxx | 377 | ||||
-rw-r--r-- | xmlsecurity/source/helper/xsecparser.hxx | 165 | ||||
-rw-r--r-- | xmlsecurity/source/helper/xsecsign.cxx | 374 | ||||
-rw-r--r-- | xmlsecurity/source/helper/xsecverify.cxx | 331 |
11 files changed, 4671 insertions, 0 deletions
diff --git a/xmlsecurity/source/helper/documentsignaturehelper.cxx b/xmlsecurity/source/helper/documentsignaturehelper.cxx new file mode 100644 index 000000000000..d0fba345588c --- /dev/null +++ b/xmlsecurity/source/helper/documentsignaturehelper.cxx @@ -0,0 +1,462 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmlsecurity.hxx" + +#include <xmlsecurity/documentsignaturehelper.hxx> + +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include "com/sun/star/beans/XPropertySet.hpp" + +#include "comphelper/documentconstants.hxx" +#include <tools/debug.hxx> +#include "rtl/uri.hxx" + +using namespace ::com::sun::star::uno; +//using namespace ::com::sun::star; +namespace css = ::com::sun::star; +using rtl::OUString; + + +namespace +{ +::rtl::OUString getElement(::rtl::OUString const & version, ::sal_Int32 * index) +{ + while (*index < version.getLength() && version[*index] == '0') { + ++*index; + } + return version.getToken(0, '.', *index); +} + + + +// Return 1 if version1 is greater then version 2, 0 if they are equal +//and -1 if version1 is less version 2 +int compareVersions( + ::rtl::OUString const & version1, ::rtl::OUString const & version2) +{ + for (::sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0;) { + ::rtl::OUString e1(getElement(version1, &i1)); + ::rtl::OUString e2(getElement(version2, &i2)); + if (e1.getLength() < e2.getLength()) { + return -1; + } else if (e1.getLength() > e2.getLength()) { + return 1; + } else if (e1 < e2) { + return -1; + } else if (e1 > e2) { + return 1; + } + } + return 0; +} +} +//If the OOo 3.0 mode is used then we exclude +//'mimetype' and all content of 'META-INF'. +//If the argument 'bSigning' is true then the element list is created for a signing +//operation in which case we use the latest signing algorithm. That is all elements +//we find in the zip storage are added to the list. We do not support the old signatures +//which did not contain all files. +//If 'bSigning' is false, then we validate. If the user enabled validating according to OOo 3.0 +//then mimetype and all content of META-INF must be excluded. +void ImplFillElementList( + std::vector< rtl::OUString >& rList, const Reference < css::embed::XStorage >& rxStore, + const ::rtl::OUString rRootStorageName, const bool bRecursive, + const DocumentSignatureAlgorithm mode) +{ + ::rtl::OUString aMetaInfName( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ); + ::rtl::OUString sMimeTypeName (RTL_CONSTASCII_USTRINGPARAM("mimetype")); + ::rtl::OUString aSep( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + + Reference < css::container::XNameAccess > xElements( rxStore, UNO_QUERY ); + Sequence< ::rtl::OUString > aElements = xElements->getElementNames(); + sal_Int32 nElements = aElements.getLength(); + const ::rtl::OUString* pNames = aElements.getConstArray(); + + for ( sal_Int32 n = 0; n < nElements; n++ ) + { + if (mode != OOo3_2Document + && (pNames[n] == aMetaInfName + || pNames[n] == sMimeTypeName)) + { + continue; + } + else + { + ::rtl::OUString sEncName = ::rtl::Uri::encode( + pNames[n], rtl_UriCharClassRelSegment, + rtl_UriEncodeStrict, RTL_TEXTENCODING_UTF8); + if (sEncName.getLength() == 0 && pNames[n].getLength() != 0) + throw css::uno::Exception(::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("Failed to encode element name of XStorage")), 0); + + if ( rxStore->isStreamElement( pNames[n] ) ) + { + //Exclude documentsignatures.xml! + if (pNames[n].equals( + DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName())) + continue; + ::rtl::OUString aFullName( rRootStorageName + sEncName ); + rList.push_back(aFullName); + } + else if ( bRecursive && rxStore->isStorageElement( pNames[n] ) ) + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( pNames[n], css::embed::ElementModes::READ ); + rtl::OUString aFullRootName( rRootStorageName + sEncName + aSep ); + ImplFillElementList(rList, xSubStore, aFullRootName, bRecursive, mode); + } + } + } +} + + +bool DocumentSignatureHelper::isODFPre_1_2(const ::rtl::OUString & sVersion) +{ + //The property version exists only if the document is at least version 1.2 + //That is, if the document has version 1.1 and sVersion is empty. + //The constant is defined in comphelper/documentconstants.hxx + if (compareVersions(sVersion, ODFVER_012_TEXT) == -1) + return true; + return false; +} + +bool DocumentSignatureHelper::isOOo3_2_Signature(const SignatureInformation & sigInfo) +{ + ::rtl::OUString sManifestURI(RTL_CONSTASCII_USTRINGPARAM("META-INF/manifest.xml")); + bool bOOo3_2 = false; + typedef ::std::vector< SignatureReferenceInformation >::const_iterator CIT; + for (CIT i = sigInfo.vSignatureReferenceInfors.begin(); + i < sigInfo.vSignatureReferenceInfors.end(); i++) + { + if (i->ouURI.equals(sManifestURI)) + { + bOOo3_2 = true; + break; + } + } + return bOOo3_2; +} + +DocumentSignatureAlgorithm +DocumentSignatureHelper::getDocumentAlgorithm( + const ::rtl::OUString & sODFVersion, const SignatureInformation & sigInfo) +{ + OSL_ASSERT(sODFVersion.getLength()); + DocumentSignatureAlgorithm mode = OOo3_2Document; + if (!isOOo3_2_Signature(sigInfo)) + { + if (isODFPre_1_2(sODFVersion)) + mode = OOo2Document; + else + mode = OOo3_0Document; + } + return mode; +} + +//The function creates a list of files which are to be signed or for which +//the signature is to be validated. The strings are UTF8 encoded URIs which +//contain '/' as path separators. +// +//The algorithm how document signatures are created and validated has +//changed over time. The change affects only which files within the document +//are changed. Document signatures created by OOo 2.x only used particular files. Since +//OOo 3.0 everything except "mimetype" and "META-INF" are signed. As of OOo 3.2 everything +//except META-INF/documentsignatures.xml is signed. +//Signatures are validated according to the algorithm which was then used for validation. +//That is, when validating a signature which was created by OOo 3.0, then mimetype and +//META-INF are not used. +// +//When a signature is created then we always use the latest algorithm. That is, we use +//that of OOo 3.2 +std::vector< rtl::OUString > +DocumentSignatureHelper::CreateElementList( + const Reference < css::embed::XStorage >& rxStore, + const ::rtl::OUString /*rRootStorageName*/, DocumentSignatureMode eMode, + const DocumentSignatureAlgorithm mode) +{ + std::vector< rtl::OUString > aElements; + ::rtl::OUString aSep( RTL_CONSTASCII_USTRINGPARAM( "/" ) ); + + switch ( eMode ) + { + case SignatureModeDocumentContent: + { + if (mode == OOo2Document) //that is, ODF 1.0, 1.1 + { + // 1) Main content + ImplFillElementList(aElements, rxStore, ::rtl::OUString(), false, mode); + + // 2) Pictures... + rtl::OUString aSubStorageName( rtl::OUString::createFromAscii( "Pictures" ) ); + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode); + } + catch(css::io::IOException& ) + { + ; // Doesn't have to exist... + } + // 3) OLE.... + aSubStorageName = rtl::OUString::createFromAscii( "ObjectReplacements" ); + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode); + xSubStore.clear(); + + // Object folders... + rtl::OUString aMatchStr( rtl::OUString::createFromAscii( "Object " ) ); + Reference < css::container::XNameAccess > xElements( rxStore, UNO_QUERY ); + Sequence< ::rtl::OUString > aElementNames = xElements->getElementNames(); + sal_Int32 nElements = aElementNames.getLength(); + const ::rtl::OUString* pNames = aElementNames.getConstArray(); + for ( sal_Int32 n = 0; n < nElements; n++ ) + { + if ( ( pNames[n].match( aMatchStr ) ) && rxStore->isStorageElement( pNames[n] ) ) + { + Reference < css::embed::XStorage > xTmpSubStore = rxStore->openStorageElement( pNames[n], css::embed::ElementModes::READ ); + ImplFillElementList(aElements, xTmpSubStore, pNames[n]+aSep, true, mode); + } + } + } + catch( com::sun::star::io::IOException& ) + { + ; // Doesn't have to exist... + } + } + else + { + // Everything except META-INF + ImplFillElementList(aElements, rxStore, ::rtl::OUString(), true, mode); + } + } + break; + case SignatureModeMacros: + { + // 1) Macros + rtl::OUString aSubStorageName( rtl::OUString::createFromAscii( "Basic" ) ); + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode); + } + catch( com::sun::star::io::IOException& ) + { + ; // Doesn't have to exist... + } + + // 2) Dialogs + aSubStorageName = rtl::OUString::createFromAscii( "Dialogs") ; + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode); + } + catch( com::sun::star::io::IOException& ) + { + ; // Doesn't have to exist... + } + // 3) Scripts + aSubStorageName = rtl::OUString::createFromAscii( "Scripts") ; + try + { + Reference < css::embed::XStorage > xSubStore = rxStore->openStorageElement( aSubStorageName, css::embed::ElementModes::READ ); + ImplFillElementList(aElements, xSubStore, aSubStorageName+aSep, true, mode); + } + catch( css::io::IOException& ) + { + ; // Doesn't have to exist... + } + } + break; + case SignatureModePackage: + { + // Everything except META-INF + ImplFillElementList(aElements, rxStore, ::rtl::OUString(), true, mode); + } + break; + } + + return aElements; +} + +SignatureStreamHelper DocumentSignatureHelper::OpenSignatureStream( + const Reference < css::embed::XStorage >& rxStore, sal_Int32 nOpenMode, DocumentSignatureMode eDocSigMode ) +{ + sal_Int32 nSubStorageOpenMode = css::embed::ElementModes::READ; + if ( nOpenMode & css::embed::ElementModes::WRITE ) + nSubStorageOpenMode = css::embed::ElementModes::WRITE; + + SignatureStreamHelper aHelper; + + try + { + ::rtl::OUString aSIGStoreName( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ); + aHelper.xSignatureStorage = rxStore->openStorageElement( aSIGStoreName, nSubStorageOpenMode ); + if ( aHelper.xSignatureStorage.is() ) + { + ::rtl::OUString aSIGStreamName; + if ( eDocSigMode == SignatureModeDocumentContent ) + aSIGStreamName = DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName(); + else if ( eDocSigMode == SignatureModeMacros ) + aSIGStreamName = DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName(); + else + aSIGStreamName = DocumentSignatureHelper::GetPackageSignatureDefaultStreamName(); + + aHelper.xSignatureStream = aHelper.xSignatureStorage->openStreamElement( aSIGStreamName, nOpenMode ); + } + } + catch(css::io::IOException& ) + { + // Doesn't have to exist... + DBG_ASSERT( nOpenMode == css::embed::ElementModes::READ, "Error creating signature stream..." ); + } + + return aHelper; +} + +//sElementList contains all files which are expected to be signed. Only those files must me signed, +//no more, no less. +//The DocumentSignatureAlgorithm indicates if the document was created with OOo 2.x. Then +//the uri s in the Reference elements in the signature, were not properly encoded. +// For example: <Reference URI="ObjectReplacements/Object 1"> +bool DocumentSignatureHelper::checkIfAllFilesAreSigned( + const ::std::vector< ::rtl::OUString > & sElementList, + const SignatureInformation & sigInfo, + const DocumentSignatureAlgorithm alg) +{ + // Can only be valid if ALL streams are signed, which means real stream count == signed stream count + unsigned int nRealCount = 0; + for ( int i = sigInfo.vSignatureReferenceInfors.size(); i; ) + { + const SignatureReferenceInformation& rInf = sigInfo.vSignatureReferenceInfors[--i]; + // There is also an extra entry of type TYPE_SAMEDOCUMENT_REFERENCE because of signature date. + if ( ( rInf.nType == TYPE_BINARYSTREAM_REFERENCE ) || ( rInf.nType == TYPE_XMLSTREAM_REFERENCE ) ) + { + ::rtl::OUString sReferenceURI = rInf.ouURI; + if (alg == OOo2Document) + { + //Comparing URIs is a difficult. Therefore we kind of normalize + //it before comparing. We assume that our URI do not have a leading "./" + //and fragments at the end (...#...) + sReferenceURI = ::rtl::Uri::encode( + sReferenceURI, rtl_UriCharClassPchar, + rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8); + } + + //find the file in the element list + typedef ::std::vector< ::rtl::OUString >::const_iterator CIT; + for (CIT aIter = sElementList.begin(); aIter < sElementList.end(); aIter++) + { + ::rtl::OUString sElementListURI = *aIter; + if (alg == OOo2Document) + { + sElementListURI = + ::rtl::Uri::encode( + sElementListURI, rtl_UriCharClassPchar, + rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8); + } + if (sElementListURI.equals(sReferenceURI)) + { + nRealCount++; + break; + } + } + } + } + return sElementList.size() == nRealCount; +} + +/*Compares the Uri which are obtained from CreateElementList with + the path obtained from the manifest.xml. + Returns true if both strings are equal. +*/ +bool DocumentSignatureHelper::equalsReferenceUriManifestPath( + const OUString & rUri, const OUString & rPath) +{ + bool retVal = false; + //split up the uri and path into segments. Both are separated by '/' + std::vector<OUString> vUriSegments; + sal_Int32 nIndex = 0; + do + { + OUString aToken = rUri.getToken( 0, '/', nIndex ); + vUriSegments.push_back(aToken); + } + while (nIndex >= 0); + + std::vector<OUString> vPathSegments; + nIndex = 0; + do + { + OUString aToken = rPath.getToken( 0, '/', nIndex ); + vPathSegments.push_back(aToken); + } + while (nIndex >= 0); + + //Now compare each segment of the uri with its counterpart from the path + if (vUriSegments.size() == vPathSegments.size()) + { + retVal = true; + typedef std::vector<OUString>::const_iterator CIT; + for (CIT i = vUriSegments.begin(), j = vPathSegments.begin(); + i != vUriSegments.end(); i++, j++) + { + //Decode the uri segment, so that %20 becomes ' ', etc. + OUString sDecUri = ::rtl::Uri::decode( + *i, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); + if (!sDecUri.equals(*j)) + { + retVal = false; + break; + } + } + } + + return retVal; +} + +::rtl::OUString DocumentSignatureHelper::GetDocumentContentSignatureDefaultStreamName() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "documentsignatures.xml" ) ); +} + +::rtl::OUString DocumentSignatureHelper::GetScriptingContentSignatureDefaultStreamName() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "macrosignatures.xml" ) ); +} + +::rtl::OUString DocumentSignatureHelper::GetPackageSignatureDefaultStreamName() +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "packagesignatures.xml" ) ); +} diff --git a/xmlsecurity/source/helper/makefile.mk b/xmlsecurity/source/helper/makefile.mk new file mode 100644 index 000000000000..6b5a6a525e48 --- /dev/null +++ b/xmlsecurity/source/helper/makefile.mk @@ -0,0 +1,54 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=xmlsecurity +TARGET=helper + +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/target.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES= \ + $(SLO)$/documentsignaturehelper.obj \ + $(SLO)$/xmlsignaturehelper.obj \ + $(SLO)$/xmlsignaturehelper2.obj \ + $(SLO)$/xsecctl.obj \ + $(SLO)$/xsecparser.obj \ + $(SLO)$/xsecsign.obj \ + $(SLO)$/xsecverify.obj + + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx new file mode 100644 index 000000000000..dd3ae00f69c1 --- /dev/null +++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx @@ -0,0 +1,467 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmlsecurity.hxx" + +#include <xmlsecurity/xmlsignaturehelper.hxx> +#include <xmlsecurity/documentsignaturehelper.hxx> +#include <xsecctl.hxx> + +#include <xmlsignaturehelper2.hxx> + +#include <tools/stream.hxx> +#include <tools/debug.hxx> + +#include <xmloff/attrlist.hxx> + +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/security/SerialNumberAdapter.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +#include <tools/date.hxx> +#include <tools/time.hxx> + +//MM : search for the default profile +//#include <unotools/streamhelper.hxx> +//MM : end + +/* SEInitializer component */ +#define SEINITIALIZER_COMPONENT "com.sun.star.xml.crypto.SEInitializer" + +#define TAG_DOCUMENTSIGNATURES "document-signatures" +#define NS_DOCUMENTSIGNATURES "http://openoffice.org/2004/documentsignatures" +#define NS_DOCUMENTSIGNATURES_ODF_1_2 "urn:oasis:names:tc:opendocument:xmlns:digitalsignature:1.0" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +XMLSignatureHelper::XMLSignatureHelper( const uno::Reference< uno::XComponentContext >& rxCtx) + : mxCtx(rxCtx), mbODFPre1_2(false) +{ + mpXSecController = new XSecController(rxCtx); + mxSecurityController = mpXSecController; + mbError = false; +} + +XMLSignatureHelper::~XMLSignatureHelper() +{ + if ( mxSEInitializer.is() && mxSecurityContext.is() ) + mxSEInitializer->freeSecurityContext( mxSecurityContext ); +} + +bool XMLSignatureHelper::Init( const rtl::OUString& rTokenPath ) +{ + DBG_ASSERT( !mxSEInitializer.is(), "XMLSignatureHelper::Init - mxSEInitializer already set!" ); + DBG_ASSERT( !mxSecurityContext.is(), "XMLSignatureHelper::Init - mxSecurityContext already set!" ); + + ImplCreateSEInitializer(); + + if ( mxSEInitializer.is() ) + mxSecurityContext = mxSEInitializer->createSecurityContext( rTokenPath ); + + return mxSecurityContext.is(); +} + +void XMLSignatureHelper::ImplCreateSEInitializer() +{ + rtl::OUString sSEInitializer(rtl::OUString::createFromAscii( SEINITIALIZER_COMPONENT )); + uno::Reference< lang::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() ); + mxSEInitializer = uno::Reference< com::sun::star::xml::crypto::XSEInitializer > ( + xMCF->createInstanceWithContext( sSEInitializer, mxCtx ), uno::UNO_QUERY ); +} + +void XMLSignatureHelper::SetUriBinding( com::sun::star::uno::Reference< com::sun::star::xml::crypto::XUriBinding >& rxUriBinding ) +{ + mxUriBinding = rxUriBinding; +} + +com::sun::star::uno::Reference< com::sun::star::xml::crypto::XUriBinding > XMLSignatureHelper::GetUriBinding() const +{ + return mxUriBinding; +} + +void XMLSignatureHelper::SetStorage( + const Reference < css::embed::XStorage >& rxStorage, + ::rtl::OUString sODFVersion) +{ + DBG_ASSERT( !mxUriBinding.is(), "SetStorage - UriBinding already set!" ); + mxUriBinding = new UriBindingHelper( rxStorage ); + DBG_ASSERT(rxStorage.is(), "SetStorage - empty storage!"); + mbODFPre1_2 = DocumentSignatureHelper::isODFPre_1_2(sODFVersion); +} + + +void XMLSignatureHelper::SetStartVerifySignatureHdl( const Link& rLink ) +{ + maStartVerifySignatureHdl = rLink; +} + + +void XMLSignatureHelper::StartMission() +{ + if ( !mxUriBinding.is() ) + mxUriBinding = new UriBindingHelper(); + + mpXSecController->startMission( mxUriBinding, mxSecurityContext ); +} + +void XMLSignatureHelper::EndMission() +{ + mpXSecController->endMission(); +} + +sal_Int32 XMLSignatureHelper::GetNewSecurityId() +{ + return mpXSecController->getNewSecurityId(); +} + +void XMLSignatureHelper::SetX509Certificate( + sal_Int32 nSecurityId, + const rtl::OUString& ouX509IssuerName, + const rtl::OUString& ouX509SerialNumber, + const rtl::OUString& ouX509Cert) +{ + mpXSecController->setX509Certificate( + nSecurityId, + ouX509IssuerName, + ouX509SerialNumber, + ouX509Cert); +} + +void XMLSignatureHelper::SetX509Certificate( + sal_Int32 nSecurityId, + sal_Int32 nSecurityEnvironmentIndex, + const rtl::OUString& ouX509IssuerName, + const rtl::OUString& ouX509SerialNumber, + const rtl::OUString& ouX509Cert) +{ + mpXSecController->setX509Certificate( + nSecurityId, + nSecurityEnvironmentIndex, + ouX509IssuerName, + ouX509SerialNumber, + ouX509Cert); +} + +void XMLSignatureHelper::SetDateTime( sal_Int32 nSecurityId, const Date& rDate, const Time& rTime ) +{ + /* + rtl::OUString aDate = String::CreateFromInt32( rDate.GetDate() ); + rtl::OUString aTime = String::CreateFromInt32( rTime.GetTime() ); + mpXSecController->setDateTime( nSecurityId, aDate, aTime ); + */ + ::com::sun::star::util::DateTime stDateTime; + stDateTime.HundredthSeconds = (::sal_uInt16)rTime.Get100Sec(); + stDateTime.Seconds = (::sal_uInt16)rTime.GetSec(); + stDateTime.Minutes = (::sal_uInt16)rTime.GetMin(); + stDateTime.Hours = (::sal_uInt16)rTime.GetHour(); + stDateTime.Day = (::sal_uInt16)rDate.GetDay(); + stDateTime.Month = (::sal_uInt16)rDate.GetMonth(); + stDateTime.Year = (::sal_uInt16)rDate.GetYear(); + mpXSecController->setDate( nSecurityId, stDateTime ); +} + +void XMLSignatureHelper::AddForSigning( sal_Int32 nSecurityId, const rtl::OUString& uri, const rtl::OUString& objectURL, sal_Bool bBinary ) +{ + mpXSecController->signAStream( nSecurityId, uri, objectURL, bBinary ); +} + + +uno::Reference<xml::sax::XDocumentHandler> XMLSignatureHelper::CreateDocumentHandlerWithHeader( + const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xOutputStream ) +{ + /* + * get SAX writer component + */ + uno::Reference< lang::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() ); + uno::Reference< io::XActiveDataSource > xSaxWriter( + xMCF->createInstanceWithContext(rtl::OUString::createFromAscii( + "com.sun.star.xml.sax.Writer"), mxCtx ), uno::UNO_QUERY ); + + DBG_ASSERT( xSaxWriter.is(), "can't instantiate XML writer" ); + + /* + * connect XML writer to output stream + */ + xSaxWriter->setOutputStream( xOutputStream ); + + /* + * prepare document handler + */ + uno::Reference<xml::sax::XDocumentHandler> + xDocHandler( xSaxWriter,uno::UNO_QUERY); + + /* + * write the xml context for signatures + */ + rtl::OUString tag_AllSignatures(RTL_CONSTASCII_USTRINGPARAM(TAG_DOCUMENTSIGNATURES)); + + SvXMLAttributeList *pAttributeList = new SvXMLAttributeList(); + rtl::OUString sNamespace; + if (mbODFPre1_2) + sNamespace = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NS_DOCUMENTSIGNATURES)); + else + sNamespace = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NS_DOCUMENTSIGNATURES_ODF_1_2)); + + pAttributeList->AddAttribute( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_XMLNS)), + sNamespace); + + xDocHandler->startDocument(); + xDocHandler->startElement( + tag_AllSignatures, + uno::Reference< com::sun::star::xml::sax::XAttributeList > (pAttributeList)); + + return xDocHandler; +} + +void XMLSignatureHelper::CloseDocumentHandler( const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler ) +{ + rtl::OUString tag_AllSignatures(RTL_CONSTASCII_USTRINGPARAM(TAG_DOCUMENTSIGNATURES)); + xDocumentHandler->endElement( tag_AllSignatures ); + xDocumentHandler->endDocument(); +} + +void XMLSignatureHelper::ExportSignature( + const uno::Reference< xml::sax::XDocumentHandler >& xDocumentHandler, + const SignatureInformation& signatureInfo ) +{ + mpXSecController->exportSignature(xDocumentHandler, signatureInfo); +} + +bool XMLSignatureHelper::CreateAndWriteSignature( const uno::Reference< xml::sax::XDocumentHandler >& xDocumentHandler ) +{ + mbError = false; + + /* + * create a signature listener + */ +/* + ImplXMLSignatureListener* pSignatureListener = new ImplXMLSignatureListener( + LINK( this, XMLSignatureHelper, SignatureCreationResultListener ), + LINK( this, XMLSignatureHelper, SignatureVerifyResultListener ), + LINK( this, XMLSignatureHelper, StartVerifySignatureElement ) ); +*/ + /* + * configure the signature creation listener + */ + //mpXSecController->setSignatureCreationResultListener( pSignatureListener ); + + /* + * write signatures + */ + if ( !mpXSecController->WriteSignature( xDocumentHandler ) ) + { + mbError = true; + } + + /* + * clear up the signature creation listener + */ + //mpXSecController->setSignatureCreationResultListener( NULL ); + + return !mbError; +} + +bool XMLSignatureHelper::CreateAndWriteSignature( const com::sun::star::uno::Reference< com::sun::star::io::XOutputStream >& xOutputStream ) +{ + uno::Reference<xml::sax::XDocumentHandler> xDocHandler + = CreateDocumentHandlerWithHeader(xOutputStream); + + bool rc = CreateAndWriteSignature( xDocHandler ); + + CloseDocumentHandler(xDocHandler); + + return rc; +} + +bool XMLSignatureHelper::ReadAndVerifySignature( const com::sun::star::uno::Reference< com::sun::star::io::XInputStream >& xInputStream ) +{ + mbError = false; + + DBG_ASSERT(xInputStream.is(), "input stream missing"); + + /* + * prepare ParserInputSrouce + */ + xml::sax::InputSource aParserInput; + // aParserInput.sSystemId = ouName; + aParserInput.aInputStream = xInputStream; + + /* + * get SAX parser component + */ + uno::Reference< lang::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() ); + uno::Reference< xml::sax::XParser > xParser( + xMCF->createInstanceWithContext( + rtl::OUString::createFromAscii("com.sun.star.xml.sax.Parser"), mxCtx ), + uno::UNO_QUERY ); + + DBG_ASSERT( xParser.is(), "Can't create parser" ); + + /* + * create a signature reader + */ + uno::Reference< xml::sax::XDocumentHandler > xHandler + = mpXSecController->createSignatureReader( ); + + /* + * create a signature listener + */ + ImplXMLSignatureListener* pSignatureListener = new ImplXMLSignatureListener( + LINK( this, XMLSignatureHelper, SignatureCreationResultListener ), + LINK( this, XMLSignatureHelper, SignatureVerifyResultListener ), + LINK( this, XMLSignatureHelper, StartVerifySignatureElement ) ); + + /* + * configure the signature verify listener + */ + //mpXSecController->setSignatureVerifyResultListener( pSignatureListener ); + + /* + * setup the connection: + * Parser -> SignatureListener -> SignatureReader + */ + pSignatureListener->setNextHandler(xHandler); + xParser->setDocumentHandler( pSignatureListener ); + + /* + * parser the stream + */ + try + { + xParser->parseStream( aParserInput ); + } + catch( xml::sax::SAXParseException& ) + { + mbError = true; + } + catch( xml::sax::SAXException& ) + { + mbError = true; + } + catch( com::sun::star::io::IOException& ) + { + mbError = true; + } + catch( uno::Exception& ) + { + mbError = true; + } + + /* + * clear up the connection + */ + pSignatureListener->setNextHandler( NULL ); + + /* + * clear up the signature verify listener + */ + //mpXSecController->setSignatureVerifyResultListener( NULL ); + + /* + * release the signature reader + */ + mpXSecController->releaseSignatureReader( ); + + return !mbError; +} + +SignatureInformation XMLSignatureHelper::GetSignatureInformation( sal_Int32 nSecurityId ) const +{ + return mpXSecController->getSignatureInformation( nSecurityId ); +} + +SignatureInformations XMLSignatureHelper::GetSignatureInformations() const +{ + return mpXSecController->getSignatureInformations(); +} + +uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > XMLSignatureHelper::GetSecurityEnvironment() +{ + return (mxSecurityContext.is()?(mxSecurityContext->getSecurityEnvironment()): uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment >()); +} + +uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment > XMLSignatureHelper::GetSecurityEnvironmentByIndex(sal_Int32 nId) +{ + return (mxSecurityContext.is()?(mxSecurityContext->getSecurityEnvironmentByIndex(nId)): uno::Reference< ::com::sun::star::xml::crypto::XSecurityEnvironment >()); +} + +sal_Int32 XMLSignatureHelper::GetSecurityEnvironmentNumber() +{ + return (mxSecurityContext.is()?(mxSecurityContext->getSecurityEnvironmentNumber()): 0); +} + + +/* +void XMLSignatureHelper::createSecurityContext( rtl::OUString tokenPath ) +{ + if ( !mxSEInitializer.is() ) + ImplCreateSEInitializer(); + + mxSecurityContext = mxSEInitializer->createSecurityContext(tokenPath); +} + +void XMLSignatureHelper::freeSecurityContext() +{ + if ( !mxSEInitializer.is() ) + ImplCreateSEInitializer(); + + mxSEInitializer->freeSecurityContext( mxSecurityContext ); +} +*/ + +IMPL_LINK( XMLSignatureHelper, SignatureCreationResultListener, XMLSignatureCreationResult*, pResult ) +{ + maCreationResults.insert( maCreationResults.begin() + maCreationResults.size(), *pResult ); + if ( pResult->nSignatureCreationResult != com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED ) + mbError = true; + return 0; +} + +IMPL_LINK( XMLSignatureHelper, SignatureVerifyResultListener, XMLSignatureVerifyResult*, pResult ) +{ + maVerifyResults.insert( maVerifyResults.begin() + maVerifyResults.size(), *pResult ); + if ( pResult->nSignatureVerifyResult != com::sun::star::xml::crypto::SecurityOperationStatus_OPERATION_SUCCEEDED ) + mbError = true; + return 0; +} + +IMPL_LINK( XMLSignatureHelper, StartVerifySignatureElement, const uno::Reference< com::sun::star::xml::sax::XAttributeList >*, pAttrs ) +{ + if ( !maStartVerifySignatureHdl.IsSet() || maStartVerifySignatureHdl.Call( (void*)pAttrs ) ) + { + sal_Int32 nSignatureId = mpXSecController->getNewSecurityId(); + mpXSecController->addSignature( nSignatureId ); + } + + return 0; +} diff --git a/xmlsecurity/source/helper/xmlsignaturehelper2.cxx b/xmlsecurity/source/helper/xmlsignaturehelper2.cxx new file mode 100644 index 000000000000..4c0c847b8d54 --- /dev/null +++ b/xmlsecurity/source/helper/xmlsignaturehelper2.cxx @@ -0,0 +1,232 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmlsecurity.hxx" + +#include <xmlsecurity/xmlsignaturehelper.hxx> +#include <xmlsignaturehelper2.hxx> + +#include <unotools/streamhelper.hxx> + +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/XStorageRawAccess.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include "rtl/uri.hxx" + +using namespace com::sun::star; + +ImplXMLSignatureListener::ImplXMLSignatureListener( const Link& rCreationResultListenerListener, const Link rVerifyResultListenerListener, const Link rStartSignatureElement ) +{ + maCreationResultListenerListener = rCreationResultListenerListener; + maVerifyResultListenerListener = rVerifyResultListenerListener; + maStartVerifySignatureElementListener = rStartSignatureElement; + +} +ImplXMLSignatureListener::~ImplXMLSignatureListener() +{ +} + +void ImplXMLSignatureListener::setNextHandler( + uno::Reference< xml::sax::XDocumentHandler > xNextHandler) +{ + m_xNextHandler = xNextHandler; +} + +void SAL_CALL ImplXMLSignatureListener::signatureCreated( sal_Int32 securityId, com::sun::star::xml::crypto::SecurityOperationStatus nResult ) + throw (com::sun::star::uno::RuntimeException) +{ + XMLSignatureCreationResult aResult( securityId, nResult ); + maCreationResultListenerListener.Call( &aResult ); +} + +void SAL_CALL ImplXMLSignatureListener::signatureVerified( sal_Int32 securityId, com::sun::star::xml::crypto::SecurityOperationStatus nResult ) + throw (com::sun::star::uno::RuntimeException) +{ + XMLSignatureVerifyResult aResult( securityId, nResult ); + maVerifyResultListenerListener.Call( &aResult ); +} + +// --------------------------------------------------------------------------------- +// XDocumentHandler +// --------------------------------------------------------------------------------- +void SAL_CALL ImplXMLSignatureListener::startDocument( ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->startDocument(); + } +} + +void SAL_CALL ImplXMLSignatureListener::endDocument( ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->endDocument(); + } +} + +void SAL_CALL ImplXMLSignatureListener::startElement( const rtl::OUString& aName, const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException) +{ + if ( aName == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Signature")) ) + { + maStartVerifySignatureElementListener.Call( (void*)&xAttribs ); + } + + if (m_xNextHandler.is()) + { + m_xNextHandler->startElement( aName, xAttribs ); + } +} + +void SAL_CALL ImplXMLSignatureListener::endElement( const rtl::OUString& aName ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->endElement( aName ); + } +} + +void SAL_CALL ImplXMLSignatureListener::characters( const rtl::OUString& aChars ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->characters( aChars ); + } +} + +void SAL_CALL ImplXMLSignatureListener::ignorableWhitespace( const rtl::OUString& aWhitespaces ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->ignorableWhitespace( aWhitespaces ); + } +} + +void SAL_CALL ImplXMLSignatureListener::processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->processingInstruction( aTarget, aData ); + } +} + +void SAL_CALL ImplXMLSignatureListener::setDocumentLocator( const com::sun::star::uno::Reference< com::sun::star::xml::sax::XLocator >& xLocator ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->setDocumentLocator( xLocator ); + } +} + +// --------------------------------------------------------------------------------- +// XUriBinding +// --------------------------------------------------------------------------------- + +UriBindingHelper::UriBindingHelper() +{ +} + +UriBindingHelper::UriBindingHelper( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rxStorage ) +{ + mxStorage = rxStorage; +} + + +void SAL_CALL UriBindingHelper::setUriBinding( const rtl::OUString& /*uri*/, const uno::Reference< io::XInputStream >&) + throw (uno::Exception, uno::RuntimeException) +{ +} + +uno::Reference< io::XInputStream > SAL_CALL UriBindingHelper::getUriBinding( const rtl::OUString& uri ) + throw (uno::Exception, uno::RuntimeException) +{ + uno::Reference< io::XInputStream > xInputStream; + if ( mxStorage.is() ) + { + xInputStream = OpenInputStream( mxStorage, uri ); + } + else + { + SvFileStream* pStream = new SvFileStream( uri, STREAM_READ ); + pStream->Seek( STREAM_SEEK_TO_END ); + ULONG nBytes = pStream->Tell(); + pStream->Seek( STREAM_SEEK_TO_BEGIN ); + SvLockBytesRef xLockBytes = new SvLockBytes( pStream, TRUE ); + xInputStream = new utl::OInputStreamHelper( xLockBytes, nBytes ); + } + return xInputStream; +} + +uno::Reference < io::XInputStream > UriBindingHelper::OpenInputStream( const uno::Reference < embed::XStorage >& rxStore, const rtl::OUString& rURI ) +{ + OSL_ASSERT(rURI.getLength()); + uno::Reference < io::XInputStream > xInStream; + + sal_Int32 nSepPos = rURI.indexOf( '/' ); + if ( nSepPos == -1 ) + { + // Cloning because of I can't keep all storage references open + // MBA with think about a better API... + const ::rtl::OUString sName = ::rtl::Uri::decode( + rURI, rtl_UriDecodeStrict, rtl_UriCharClassRelSegment); + if (sName.getLength() == 0 && rURI.getLength() != 0) + throw uno::Exception(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Could not decode URI for stream element.")), 0); + + uno::Reference< io::XStream > xStream; + xStream = rxStore->cloneStreamElement( sName ); + if ( !xStream.is() ) + throw uno::RuntimeException(); + xInStream = xStream->getInputStream(); + } + else + { + const rtl::OUString aStoreName = ::rtl::Uri::decode( + rURI.copy( 0, nSepPos ), rtl_UriDecodeStrict, rtl_UriCharClassRelSegment); + if (aStoreName.getLength() == 0 && rURI.getLength() != 0) + throw uno::Exception( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "Could not decode URI for stream element.")), 0); + + rtl::OUString aElement = rURI.copy( nSepPos+1 ); + uno::Reference < embed::XStorage > xSubStore = rxStore->openStorageElement( aStoreName, embed::ElementModes::READ ); + xInStream = OpenInputStream( xSubStore, aElement ); + } + return xInStream; +} + + diff --git a/xmlsecurity/source/helper/xmlsignaturehelper2.hxx b/xmlsecurity/source/helper/xmlsignaturehelper2.hxx new file mode 100644 index 000000000000..84b45d02ba41 --- /dev/null +++ b/xmlsecurity/source/helper/xmlsignaturehelper2.hxx @@ -0,0 +1,134 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <tools/link.hxx> +#include <rtl/ustring.hxx> + +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase3.hxx> + +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/crypto/sax/XSignatureCreationResultListener.hpp> +#include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultListener.hpp> + +namespace com { +namespace sun { +namespace star { +namespace io { + class XStream; + class XOutputStream; + class XInputStream; } +namespace embed { + class XStorage; } +}}} + + +// MT: Not needed any more, remove later... + +class ImplXMLSignatureListener : public cppu::WeakImplHelper3 +< + com::sun::star::xml::crypto::sax::XSignatureCreationResultListener, + com::sun::star::xml::crypto::sax::XSignatureVerifyResultListener, + com::sun::star::xml::sax::XDocumentHandler +> +{ +private: + Link maCreationResultListenerListener; + Link maVerifyResultListenerListener; + Link maStartVerifySignatureElementListener; + + com::sun::star::uno::Reference< + com::sun::star::xml::sax::XDocumentHandler > m_xNextHandler; + +public: + ImplXMLSignatureListener( const Link& rCreationResultListenerListener, const Link rVerifyResultListenerListener, const Link rStartVerifySignatureElement ); + ~ImplXMLSignatureListener(); + + void setNextHandler(com::sun::star::uno::Reference< + com::sun::star::xml::sax::XDocumentHandler > xNextHandler); + + // com::sun::star::xml::crypto::sax::XSignatureCreationResultListener + virtual void SAL_CALL signatureCreated( sal_Int32 securityId, com::sun::star::xml::crypto::SecurityOperationStatus creationResult ) + throw (com::sun::star::uno::RuntimeException); + + // com::sun::star::xml::crypto::sax::XSignatureVerifyResultListener + virtual void SAL_CALL signatureVerified( sal_Int32 securityId, com::sun::star::xml::crypto::SecurityOperationStatus verifyResult ) + throw (com::sun::star::uno::RuntimeException); + + // com::sun::star::xml::sax::XDocumentHandler + virtual void SAL_CALL startElement( const rtl::OUString& aName, const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttribs ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL startDocument( ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL endDocument( ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL endElement( const rtl::OUString& aName ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL characters( const rtl::OUString& aChars ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL ignorableWhitespace( const rtl::OUString& aWhitespaces ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setDocumentLocator( const com::sun::star::uno::Reference< com::sun::star::xml::sax::XLocator >& xLocator ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); +}; + + +// --------------------------------------------------------------------------------- +// XUriBinding +// --------------------------------------------------------------------------------- + +class UriBindingHelper : public cppu::WeakImplHelper1 +< + com::sun::star::xml::crypto::XUriBinding +> +{ +private: + com::sun::star::uno::Reference < com::sun::star::embed::XStorage > mxStorage; + + +public: + UriBindingHelper(); + UriBindingHelper( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rxStorage ); + + void SAL_CALL setUriBinding( const rtl::OUString& uri, const com::sun::star::uno::Reference< com::sun::star::io::XInputStream >& aInputStream ) + throw (com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + com::sun::star::uno::Reference< com::sun::star::io::XInputStream > SAL_CALL getUriBinding( const rtl::OUString& uri ) + throw (com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + static com::sun::star::uno::Reference < com::sun::star::io::XInputStream > OpenInputStream( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rxStore, const rtl::OUString& rURI ); +}; + diff --git a/xmlsecurity/source/helper/xsecctl.cxx b/xmlsecurity/source/helper/xsecctl.cxx new file mode 100644 index 000000000000..bdcb0658af1e --- /dev/null +++ b/xmlsecurity/source/helper/xsecctl.cxx @@ -0,0 +1,1498 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmlsecurity.hxx" + +#include <xsecctl.hxx> +#include <tools/debug.hxx> + +#include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp> +#include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp> +#include <com/sun/star/xml/crypto/sax/XMissionTaker.hpp> +#include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp> +#include <com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeBroadcaster.hpp> +#include <com/sun/star/xml/crypto/SecurityOperationStatus.hpp> + +#include <xmloff/attrlist.hxx> +#include <rtl/math.hxx> +#include <tools/string.hxx> + +namespace cssu = com::sun::star::uno; +namespace cssl = com::sun::star::lang; +namespace cssxc = com::sun::star::xml::crypto; +namespace cssxs = com::sun::star::xml::sax; +namespace cssxw = com::sun::star::xml::wrapper; +namespace cssb = com::sun::star::beans; + +const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 11; +const sal_Int8 XML_MAXDIGITSCOUNT_DATETIME = 6; + +/* bridge component names */ +#define XMLSIGNATURE_COMPONENT "com.sun.star.xml.crypto.XMLSignature" +#define XMLDOCUMENTWRAPPER_COMPONENT "com.sun.star.xml.wrapper.XMLDocumentWrapper" + +/* xml security framework components */ +#define SAXEVENTKEEPER_COMPONENT "com.sun.star.xml.crypto.sax.SAXEventKeeper" + +/* string for package protocol */ +#define PACKAGEPROTOCOL "vnd.sun.star.Package:" + +XSecController::XSecController( const cssu::Reference<cssu::XComponentContext>& rxCtx ) + :mxCtx(rxCtx), + m_nNextSecurityId(1), + m_bIsSAXEventKeeperConnected(false), + m_nStatusOfSecurityComponents(UNINITIALIZED), + m_bIsSAXEventKeeperSticky(false), + m_pErrorMessage(NULL), + m_pXSecParser(NULL) +{ +} + +XSecController::~XSecController() +{ +} + + +/* + * private methods + */ +/** convert string to number with optional min and max values */ +sal_Bool XSecController::convertNumber( sal_Int32& rValue, + const rtl::OUString& rString, + sal_Int32 /*nMin*/, sal_Int32 /*nMax*/ ) +{ + sal_Bool bNeg = sal_False; + rValue = 0; + + sal_Int32 nPos = 0L; + sal_Int32 nLen = rString.getLength(); + + // skip white space + while( nPos < nLen && sal_Unicode(' ') == rString[nPos] ) + nPos++; + + if( nPos < nLen && sal_Unicode('-') == rString[nPos] ) + { + bNeg = sal_True; + nPos++; + } + + // get number + while( nPos < nLen && + sal_Unicode('0') <= rString[nPos] && + sal_Unicode('9') >= rString[nPos] ) + { + // TODO: check overflow! + rValue *= 10; + rValue += (rString[nPos] - sal_Unicode('0')); + nPos++; + } + + if( bNeg ) + rValue *= -1; + + return nPos == nLen; +} + +/** convert util::DateTime to ISO Date String */ +void XSecController::convertDateTime( ::rtl::OUStringBuffer& rBuffer, + const com::sun::star::util::DateTime& rDateTime ) +{ + String aString( String::CreateFromInt32( rDateTime.Year ) ); + aString += '-'; + if( rDateTime.Month < 10 ) + aString += '0'; + aString += String::CreateFromInt32( rDateTime.Month ); + aString += '-'; + if( rDateTime.Day < 10 ) + aString += '0'; + aString += String::CreateFromInt32( rDateTime.Day ); + + if( rDateTime.Seconds != 0 || + rDateTime.Minutes != 0 || + rDateTime.Hours != 0 ) + { + aString += 'T'; + if( rDateTime.Hours < 10 ) + aString += '0'; + aString += String::CreateFromInt32( rDateTime.Hours ); + aString += ':'; + if( rDateTime.Minutes < 10 ) + aString += '0'; + aString += String::CreateFromInt32( rDateTime.Minutes ); + aString += ':'; + if( rDateTime.Seconds < 10 ) + aString += '0'; + aString += String::CreateFromInt32( rDateTime.Seconds ); + if ( rDateTime.HundredthSeconds > 0) + { + aString += ','; + if (rDateTime.HundredthSeconds < 10) + aString += '0'; + aString += String::CreateFromInt32( rDateTime.HundredthSeconds ); + } + } + + rBuffer.append( aString ); +} + +/** convert ISO Date String to util::DateTime */ +sal_Bool XSecController::convertDateTime( com::sun::star::util::DateTime& rDateTime, + const ::rtl::OUString& rString ) +{ + sal_Bool bSuccess = sal_True; + + rtl::OUString aDateStr, aTimeStr, sHundredth; + sal_Int32 nPos = rString.indexOf( (sal_Unicode) 'T' ); + sal_Int32 nPos2 = rString.indexOf( (sal_Unicode) ',' ); + if ( nPos >= 0 ) + { + aDateStr = rString.copy( 0, nPos ); + if ( nPos2 >= 0 ) + { + aTimeStr = rString.copy( nPos + 1, nPos2 - nPos - 1 ); + + //Get the fraction of a second with the accuracy of one hundreds second. + //The fraction part of the date could have different accuracies. To calculate + //the count of a hundredth units one could form a fractional number by appending + //the value of the time string to 0. Then multiply it by 100 and use only the whole number. + //For example: 5:27:46,1 -> 0,1 * 100 = 10 + //5:27:46,01 -> 0,01 * 100 = 1 + //5:27:46,001 -> 0,001 * 100 = 0 + //Due to the inaccuracy of floating point numbers the result may not be the same on different + //platforms. We had the case where we had a value of 24 hundredth of second, which converted to + //23 on Linux and 24 on Solaris and Windows. + + //we only support a hundredth second + //make ,1 -> 10 ,01 -> 1 ,001 -> only use first two diggits + sHundredth = rString.copy(nPos2 + 1); + sal_Int32 len = sHundredth.getLength(); + if (len == 1) + sHundredth += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0")); + if (len > 2) + sHundredth = sHundredth.copy(0, 2); + } + else + { + aTimeStr = rString.copy(nPos + 1); + sHundredth = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0")); + } + } + else + aDateStr = rString; // no separator: only date part + + sal_Int32 nYear = 1899; + sal_Int32 nMonth = 12; + sal_Int32 nDay = 30; + sal_Int32 nHour = 0; + sal_Int32 nMin = 0; + sal_Int32 nSec = 0; + + const sal_Unicode* pStr = aDateStr.getStr(); + sal_Int32 nDateTokens = 1; + while ( *pStr ) + { + if ( *pStr == '-' ) + nDateTokens++; + pStr++; + } + if ( nDateTokens > 3 || aDateStr.getLength() == 0 ) + bSuccess = sal_False; + else + { + sal_Int32 n = 0; + if ( !convertNumber( nYear, aDateStr.getToken( 0, '-', n ), 0, 9999 ) ) + bSuccess = sal_False; + if ( nDateTokens >= 2 ) + if ( !convertNumber( nMonth, aDateStr.getToken( 0, '-', n ), 0, 12 ) ) + bSuccess = sal_False; + if ( nDateTokens >= 3 ) + if ( !convertNumber( nDay, aDateStr.getToken( 0, '-', n ), 0, 31 ) ) + bSuccess = sal_False; + } + + if ( aTimeStr.getLength() > 0 ) // time is optional + { + pStr = aTimeStr.getStr(); + sal_Int32 nTimeTokens = 1; + while ( *pStr ) + { + if ( *pStr == ':' ) + nTimeTokens++; + pStr++; + } + if ( nTimeTokens > 3 ) + bSuccess = sal_False; + else + { + sal_Int32 n = 0; + if ( !convertNumber( nHour, aTimeStr.getToken( 0, ':', n ), 0, 23 ) ) + bSuccess = sal_False; + if ( nTimeTokens >= 2 ) + if ( !convertNumber( nMin, aTimeStr.getToken( 0, ':', n ), 0, 59 ) ) + bSuccess = sal_False; + if ( nTimeTokens >= 3 ) + if ( !convertNumber( nSec, aTimeStr.getToken( 0, ':', n ), 0, 59 ) ) + bSuccess = sal_False; + } + } + + if (bSuccess) + { + rDateTime.Year = (sal_uInt16)nYear; + rDateTime.Month = (sal_uInt16)nMonth; + rDateTime.Day = (sal_uInt16)nDay; + rDateTime.Hours = (sal_uInt16)nHour; + rDateTime.Minutes = (sal_uInt16)nMin; + rDateTime.Seconds = (sal_uInt16)nSec; + // rDateTime.HundredthSeconds = sDoubleStr.toDouble() * 100; + rDateTime.HundredthSeconds = static_cast<sal_uInt16>(sHundredth.toInt32()); + } + return bSuccess; +} + +int XSecController::findSignatureInfor( sal_Int32 nSecurityId) const +/****** XSecController/findSignatureInfor ************************************* + * + * NAME + * findSignatureInfor -- find SignatureInformation struct for a particular + * signature + * + * SYNOPSIS + * index = findSignatureInfor( nSecurityId ); + * + * FUNCTION + * see NAME. + * + * INPUTS + * nSecurityId - the signature's id + * + * RESULT + * index - the index of the signature, or -1 when no such signature + * existing + * + * HISTORY + * 08.05.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + int i; + int size = m_vInternalSignatureInformations.size(); + + for (i=0; i<size; ++i) + { + if (m_vInternalSignatureInformations[i].signatureInfor.nSecurityId == nSecurityId) + { + return i; + } + } + + return -1; +} + +void XSecController::createXSecComponent( ) +/****** XSecController/createXSecComponent ************************************ + * + * NAME + * bResult = createXSecComponent -- creates xml security components + * + * SYNOPSIS + * createXSecComponent( ); + * + * FUNCTION + * Creates xml security components, including: + * 1. an xml signature bridge component ( Java based or C based) + * 2. an XMLDocumentWrapper component ( Java based or C based) + * 3. a SAXEventKeeper component + * + * INPUTS + * empty + * + * RESULT + * empty + * + * HISTORY + * 05.01.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + rtl::OUString sSAXEventKeeper(rtl::OUString::createFromAscii( SAXEVENTKEEPER_COMPONENT )); + rtl::OUString sXMLSignature(rtl::OUString::createFromAscii( XMLSIGNATURE_COMPONENT )); + rtl::OUString sXMLDocument(rtl::OUString::createFromAscii( XMLDOCUMENTWRAPPER_COMPONENT )); + + /* + * marks all security components are not available. + */ + m_nStatusOfSecurityComponents = FAILTOINITIALIZED; + m_xXMLSignature = NULL; + m_xXMLDocumentWrapper = NULL; + m_xSAXEventKeeper = NULL; + + cssu::Reference< cssl::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() ); + + m_xXMLSignature = cssu::Reference< cssxc::XXMLSignature >( + xMCF->createInstanceWithContext( sXMLSignature, mxCtx ), + cssu::UNO_QUERY ); + + bool bSuccess = (0!=m_xXMLSignature.is()); + if ( bSuccess ) + /* + * XMLSignature created successfully. + */ + { + m_xXMLDocumentWrapper = cssu::Reference< cssxw::XXMLDocumentWrapper >( + xMCF->createInstanceWithContext( sXMLDocument, mxCtx ), + cssu::UNO_QUERY ); + } + + bSuccess &= (0!=m_xXMLDocumentWrapper.is()); + if ( bSuccess ) + /* + * XMLDocumentWrapper created successfully. + */ + { + m_xSAXEventKeeper = cssu::Reference< cssxc::sax::XSecuritySAXEventKeeper >( + xMCF->createInstanceWithContext( sSAXEventKeeper, mxCtx ), + cssu::UNO_QUERY ); + } + + bSuccess &= (0!=m_xSAXEventKeeper.is()); + + if (bSuccess) + /* + * SAXEventKeeper created successfully. + */ + { + cssu::Reference< cssl::XInitialization > xInitialization(m_xSAXEventKeeper, cssu::UNO_QUERY); + + cssu::Sequence <cssu::Any> arg(1); + arg[0] = cssu::makeAny(m_xXMLDocumentWrapper); + xInitialization->initialize(arg); + + cssu::Reference<cssxc::sax::XSAXEventKeeperStatusChangeBroadcaster> + xSAXEventKeeperStatusChangeBroadcaster(m_xSAXEventKeeper, cssu::UNO_QUERY); + cssu::Reference< cssxc::sax::XSAXEventKeeperStatusChangeListener > + xStatusChangeListener = this; + + xSAXEventKeeperStatusChangeBroadcaster + ->addSAXEventKeeperStatusChangeListener( xStatusChangeListener ); + + m_nStatusOfSecurityComponents = INITIALIZED; + } +} + +bool XSecController::chainOn( bool bRetrievingLastEvent ) +/****** XSecController/chainOn ************************************************ + * + * NAME + * chainOn -- tyies to connect the SAXEventKeeper with the SAX chain. + * + * SYNOPSIS + * bJustChainingOn = chainOn( bRetrievingLastEvent ); + * + * FUNCTION + * First, checks whether the SAXEventKeeper is on the SAX chain. If not, + * creates xml security components, and chains the SAXEventKeeper into + * the SAX chain. + * Before being chained in, the SAXEventKeeper needs to receive all + * missed key SAX events, which can promise the DOM tree bufferred by the + * SAXEventKeeper has the same structure with the original document. + * + * INPUTS + * bRetrievingLastEvent - whether to retrieve the last key SAX event from + * the ElementStackKeeper. + * + * RESULT + * bJustChainingOn - whether the SAXEventKeeper is just chained into the + * SAX chain. + * + * NOTES + * Sometimes, the last key SAX event can't be transferred to the + * SAXEventKeeper together. + * For instance, at the time an referenced element is detected, the + * startElement event has already been reserved by the ElementStackKeeper. + * Meanwhile, an ElementCollector needs to be created before the + * SAXEventKeeper receives that startElement event. + * So for the SAXEventKeeper, it needs to receive all missed key SAX + * events except that startElement event, then adds a new + * ElementCollector, then receives that startElement event. + * + * HISTORY + * 05.01.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + bool rc = false; + + if (!m_bIsSAXEventKeeperSticky && !m_bIsSAXEventKeeperConnected) + { + if ( m_nStatusOfSecurityComponents == UNINITIALIZED ) + { + createXSecComponent(); + } + + if ( m_nStatusOfSecurityComponents == INITIALIZED ) + /* + * if all security components are ready, chains on the SAXEventKeeper + */ + { + /* + * disconnect the SAXEventKeeper with its current output handler, + * to make sure no SAX event is forwarded during the connecting + * phase. + */ + m_xSAXEventKeeper->setNextHandler( NULL ); + + cssu::Reference< cssxs::XDocumentHandler > xSEKHandler(m_xSAXEventKeeper, cssu::UNO_QUERY); + + /* + * connects the previous document handler on the SAX chain + */ + if ( m_xPreviousNodeOnSAXChain.is() ) + { + if ( m_bIsPreviousNodeInitializable ) + { + cssu::Reference< cssl::XInitialization > xInitialization + (m_xPreviousNodeOnSAXChain, cssu::UNO_QUERY); + + cssu::Sequence<cssu::Any> aArgs( 1 ); + aArgs[0] <<= xSEKHandler; + xInitialization->initialize(aArgs); + } + else + { + cssu::Reference< cssxs::XParser > xParser + (m_xPreviousNodeOnSAXChain, cssu::UNO_QUERY); + xParser->setDocumentHandler( xSEKHandler ); + } + } + + /* + * get missed key SAX events + */ + if (m_xElementStackKeeper.is()) + { + m_xElementStackKeeper->retrieve(xSEKHandler, bRetrievingLastEvent); + + /* + * now the ElementStackKeeper can stop its work, because the + * SAXEventKeeper is on the SAX chain, no SAX events will be + * missed. + */ + m_xElementStackKeeper->stop(); + } + + /* + * connects the next document handler on the SAX chain + */ + m_xSAXEventKeeper->setNextHandler( m_xNextNodeOnSAXChain ); + + m_bIsSAXEventKeeperConnected = true; + + rc = true; + } + } + + return rc; +} + +void XSecController::chainOff() +/****** XSecController/chainOff *********************************************** + * + * NAME + * chainOff -- disconnects the SAXEventKeeper from the SAX chain. + * + * SYNOPSIS + * chainOff( ); + * + * FUNCTION + * See NAME. + * + * INPUTS + * empty + * + * RESULT + * empty + * + * HISTORY + * 05.01.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + if (!m_bIsSAXEventKeeperSticky ) + { + if (m_bIsSAXEventKeeperConnected) + { + m_xSAXEventKeeper->setNextHandler( NULL ); + + if ( m_xPreviousNodeOnSAXChain.is() ) + { + if ( m_bIsPreviousNodeInitializable ) + { + cssu::Reference< cssl::XInitialization > xInitialization + (m_xPreviousNodeOnSAXChain, cssu::UNO_QUERY); + + cssu::Sequence<cssu::Any> aArgs( 1 ); + aArgs[0] <<= m_xNextNodeOnSAXChain; + xInitialization->initialize(aArgs); + } + else + { + cssu::Reference< cssxs::XParser > xParser(m_xPreviousNodeOnSAXChain, cssu::UNO_QUERY); + xParser->setDocumentHandler( m_xNextNodeOnSAXChain ); + } + } + + if (m_xElementStackKeeper.is()) + { + /* + * start the ElementStackKeeper to reserve any possible + * missed key SAX events + */ + m_xElementStackKeeper->start(); + } + + m_bIsSAXEventKeeperConnected = false; + } + } +} + +void XSecController::checkChainingStatus() +/****** XSecController/checkChainingStatus ************************************ + * + * NAME + * checkChainingStatus -- connects or disconnects the SAXEventKeeper + * according to the current situation. + * + * SYNOPSIS + * checkChainingStatus( ); + * + * FUNCTION + * The SAXEventKeeper is chained into the SAX chain, when: + * 1. some element is being collected, or + * 2. the SAX event stream is blocking. + * Otherwise, chain off the SAXEventKeeper. + * + * INPUTS + * empty + * + * RESULT + * empty + * + * HISTORY + * 05.01.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + if ( m_bIsCollectingElement || m_bIsBlocking ) + { + chainOn(true); + } + else + { + chainOff(); + } +} + +void XSecController::initializeSAXChain() +/****** XSecController/initializeSAXChain ************************************* + * + * NAME + * initializeSAXChain -- initializes the SAX chain according to the + * current setting. + * + * SYNOPSIS + * initializeSAXChain( ); + * + * FUNCTION + * Initializes the SAX chain, if the SAXEventKeeper is asked to be always + * on the SAX chain, chains it on. Otherwise, starts the + * ElementStackKeeper to reserve key SAX events. + * + * INPUTS + * empty + * + * RESULT + * empty + * + * HISTORY + * 05.01.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + m_bIsSAXEventKeeperConnected = false; + m_bIsCollectingElement = false; + m_bIsBlocking = false; + + if (m_xElementStackKeeper.is()) + { + /* + * starts the ElementStackKeeper + */ + m_xElementStackKeeper->start(); + } + + chainOff(); +} + +cssu::Reference< com::sun::star::io::XInputStream > + XSecController::getObjectInputStream( const rtl::OUString& objectURL ) +/****** XSecController/getObjectInputStream ************************************ + * + * NAME + * getObjectInputStream -- get a XInputStream interface from a SvStorage + * + * SYNOPSIS + * xInputStream = getObjectInputStream( objectURL ); + * + * FUNCTION + * See NAME. + * + * INPUTS + * objectURL - the object uri + * + * RESULT + * xInputStream - the XInputStream interface + * + * HISTORY + * 15.04.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + cssu::Reference< com::sun::star::io::XInputStream > xObjectInputStream; + + DBG_ASSERT( m_xUriBinding.is(), "Need XUriBinding!" ); + + xObjectInputStream = m_xUriBinding->getUriBinding(objectURL); + + return xObjectInputStream; +} + +#if 0 +sal_Int32 XSecController::getFastPropertyIndex(sal_Int32 nHandle) const +/****** XSecController/getFastPropertyIndex *********************************** + * + * NAME + * getFastPropertyIndex -- gets the index of a particular fast property + * + * SYNOPSIS + * nIndex = getFastPropertyIndex( nHandle ); + * + * FUNCTION + * See NAME. + * + * INPUTS + * nHandle - the key for the fast property + * + * RESULT + * nIndex - the index of the fast property, or -1 + * if the key is not found. + * + * HISTORY + * 05.01.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + std::vector< sal_Int32 >::const_iterator ii = m_vFastPropertyIndexs.begin(); + sal_Int32 nIndex = 0; + + bool bFound = false; + + for( ; ii != m_vFastPropertyIndexs.end(); ++ii,++nIndex ) + { + if ( nHandle == (*ii)) + { + bFound = true; + break; + } + } + + if (!bFound) + { + nIndex = -1; + } + + return nIndex; +} +#endif + +/* + * public methods + */ + +sal_Int32 XSecController::getNewSecurityId( ) +{ + sal_Int32 nId = m_nNextSecurityId; + m_nNextSecurityId++; + return nId; +} + +void XSecController::startMission( + const cssu::Reference< cssxc::XUriBinding >& xUriBinding, + const cssu::Reference< cssxc::XXMLSecurityContext >& xSecurityContext ) +/****** XSecController/startMission ******************************************* + * + * NAME + * startMission -- starts a new security mission. + * + * SYNOPSIS + * startMission( xUriBinding, xSecurityContect ); + * + * FUNCTION + * get ready for a new mission. + * + * INPUTS + * xUriBinding - the Uri binding that provide maps between uris and + * XInputStreams + * xSecurityContext - the security context component which can provide + * cryptoken + * + * RESULT + * empty + * + * HISTORY + * 05.01.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + m_xUriBinding = xUriBinding; + + m_nStatusOfSecurityComponents = UNINITIALIZED; + m_xSecurityContext = xSecurityContext; + m_pErrorMessage = NULL; + + m_vInternalSignatureInformations.clear(); + + m_bVerifyCurrentSignature = false; +} + +void XSecController::setSAXChainConnector( + const cssu::Reference< cssl::XInitialization >& xInitialization, + const cssu::Reference< cssxs::XDocumentHandler >& xDocumentHandler, + const cssu::Reference< cssxc::sax::XElementStackKeeper >& xElementStackKeeper) +/****** XSecController/setSAXChainConnector *********************************** + * + * NAME + * setSAXChainConnector -- configures the components which will + * collaborate with the SAXEventKeeper on the SAX chain. + * + * SYNOPSIS + * setSAXChainConnector( xInitialization, + * xDocumentHandler, + * xElementStackKeeper ); + * + * FUNCTION + * See NAME. + * + * INPUTS + * xInitialization - the previous node on the SAX chain + * xDocumentHandler - the next node on the SAX chain + * xElementStackKeeper - the ElementStackKeeper component which reserves + * missed key SAX events for the SAXEventKeeper + * + * RESULT + * empty + * + * HISTORY + * 05.01.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + m_bIsPreviousNodeInitializable = true; + m_xPreviousNodeOnSAXChain = xInitialization; + m_xNextNodeOnSAXChain = xDocumentHandler; + m_xElementStackKeeper = xElementStackKeeper; + + initializeSAXChain( ); +} + +void XSecController::setSAXChainConnector( + const cssu::Reference< cssxs::XParser >& xParser, + const cssu::Reference< cssxs::XDocumentHandler >& xDocumentHandler, + const cssu::Reference< cssxc::sax::XElementStackKeeper >& xElementStackKeeper) +/****** XSecController/setSAXChainConnector *********************************** + * + * NAME + * setSAXChainConnector -- configures the components which will + * collaborate with the SAXEventKeeper on the SAX chain. + * + * SYNOPSIS + * setSAXChainConnector( xParser, xDocumentHandler, xElementStackKeeper ); + * + * FUNCTION + * See NAME. + * + * INPUTS + * xParser - the previous node on the SAX chain + * xDocumentHandler - the next node on the SAX chain + * xElementStackKeeper -the ElementStackKeeper component which reserves + * missed key SAX events for the SAXEventKeeper + * + * RESULT + * empty + * + * HISTORY + * 05.01.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + m_bIsPreviousNodeInitializable = false; + m_xPreviousNodeOnSAXChain = xParser; + m_xNextNodeOnSAXChain = xDocumentHandler; + m_xElementStackKeeper = xElementStackKeeper; + + initializeSAXChain( ); +} + +void XSecController::clearSAXChainConnector() +/****** XSecController/clearSAXChainConnector ********************************* + * + * NAME + * clearSAXChainConnector -- resets the collaborating components. + * + * SYNOPSIS + * clearSAXChainConnector( ); + * + * FUNCTION + * See NAME. + * + * INPUTS + * empty + * + * RESULT + * empty + * + * HISTORY + * 05.01.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + /* + * before reseting, if the ElementStackKeeper has kept something, then + * those kept key SAX events must be transferred to the SAXEventKeeper + * first. This is to promise the next node to the SAXEventKeeper on the + * SAX chain always receives a complete document. + */ + if (m_xElementStackKeeper.is() && m_xSAXEventKeeper.is()) + { + cssu::Reference< cssxs::XDocumentHandler > xSEKHandler(m_xSAXEventKeeper, cssu::UNO_QUERY); + m_xElementStackKeeper->retrieve(xSEKHandler, sal_True); + } + + chainOff(); + + m_xPreviousNodeOnSAXChain = NULL; + m_xNextNodeOnSAXChain = NULL; + m_xElementStackKeeper = NULL; +} + +void XSecController::endMission() +/****** XSecController/endMission ********************************************* + * + * NAME + * endMission -- forces to end all missions + * + * SYNOPSIS + * endMission( ); + * + * FUNCTION + * Deletes all signature information and forces all missions to an end. + * + * INPUTS + * empty + * + * RESULT + * empty + * + * HISTORY + * 05.01.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + sal_Int32 size = m_vInternalSignatureInformations.size(); + + for (int i=0; i<size; ++i) + { + if ( m_nStatusOfSecurityComponents == INITIALIZED ) + /* + * ResolvedListener only exist when the security components are created. + */ + { + cssu::Reference< cssxc::sax::XMissionTaker > xMissionTaker + ( m_vInternalSignatureInformations[i].xReferenceResolvedListener, cssu::UNO_QUERY ); + + /* + * askes the SignatureCreator/SignatureVerifier to release + * all resouces it uses. + */ + xMissionTaker->endMission(); + } + } + + m_xUriBinding = NULL; + m_xSecurityContext = NULL; + + /* + * free the status change listener reference to this object + */ + if (m_xSAXEventKeeper.is()) + { + cssu::Reference<cssxc::sax::XSAXEventKeeperStatusChangeBroadcaster> + xSAXEventKeeperStatusChangeBroadcaster(m_xSAXEventKeeper, cssu::UNO_QUERY); + xSAXEventKeeperStatusChangeBroadcaster + ->addSAXEventKeeperStatusChangeListener( NULL ); + } +} + +const char* XSecController::getErrorMessage() +/****** XSecController/getErrorMessage **************************************** + * + * NAME + * getErrorMessage -- get the last error message + * + * SYNOPSIS + * pErrorMessage = getErrorMessage( ); + * + * FUNCTION + * see NAME. + * + * INPUTS + * empty + * + * RESULT + * empty + * + * HISTORY + * 22.04.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + return m_pErrorMessage; +} + +void XSecController::exportSignature( + const cssu::Reference<cssxs::XDocumentHandler>& xDocumentHandler, + const SignatureInformation& signatureInfo ) +/****** XSecController/exportSignature **************************************** + * + * NAME + * exportSignature -- export a signature structure to an XDocumentHandler + * + * SYNOPSIS + * exportSignature( xDocumentHandler, signatureInfo); + * + * FUNCTION + * see NAME. + * + * INPUTS + * xDocumentHandler - the document handler to receive the signature + * signatureInfo - signature to be exported + * + * RESULT + * empty + * + * HISTORY + * 26.05.2004 - implemented + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + /* + * defines all element tags in Signature element. + */ + rtl::OUString tag_Signature(RTL_CONSTASCII_USTRINGPARAM(TAG_SIGNATURE)); + rtl::OUString tag_SignedInfo(RTL_CONSTASCII_USTRINGPARAM(TAG_SIGNEDINFO)); + rtl::OUString tag_CanonicalizationMethod(RTL_CONSTASCII_USTRINGPARAM(TAG_CANONICALIZATIONMETHOD)); + rtl::OUString tag_SignatureMethod(RTL_CONSTASCII_USTRINGPARAM(TAG_SIGNATUREMETHOD)); + rtl::OUString tag_Reference(RTL_CONSTASCII_USTRINGPARAM(TAG_REFERENCE)); + rtl::OUString tag_Transforms(RTL_CONSTASCII_USTRINGPARAM(TAG_TRANSFORMS)); + rtl::OUString tag_Transform(RTL_CONSTASCII_USTRINGPARAM(TAG_TRANSFORM)); + rtl::OUString tag_DigestMethod(RTL_CONSTASCII_USTRINGPARAM(TAG_DIGESTMETHOD)); + rtl::OUString tag_DigestValue(RTL_CONSTASCII_USTRINGPARAM(TAG_DIGESTVALUE)); + rtl::OUString tag_SignatureValue(RTL_CONSTASCII_USTRINGPARAM(TAG_SIGNATUREVALUE)); + rtl::OUString tag_KeyInfo(RTL_CONSTASCII_USTRINGPARAM(TAG_KEYINFO)); + rtl::OUString tag_X509Data(RTL_CONSTASCII_USTRINGPARAM(TAG_X509DATA)); + rtl::OUString tag_X509IssuerSerial(RTL_CONSTASCII_USTRINGPARAM(TAG_X509ISSUERSERIAL)); + rtl::OUString tag_X509IssuerName(RTL_CONSTASCII_USTRINGPARAM(TAG_X509ISSUERNAME)); + rtl::OUString tag_X509SerialNumber(RTL_CONSTASCII_USTRINGPARAM(TAG_X509SERIALNUMBER)); + rtl::OUString tag_X509Certificate(RTL_CONSTASCII_USTRINGPARAM(TAG_X509CERTIFICATE)); + + rtl::OUString tag_Object(RTL_CONSTASCII_USTRINGPARAM(TAG_OBJECT)); + rtl::OUString tag_SignatureProperties(RTL_CONSTASCII_USTRINGPARAM(TAG_SIGNATUREPROPERTIES)); + rtl::OUString tag_SignatureProperty(RTL_CONSTASCII_USTRINGPARAM(TAG_SIGNATUREPROPERTY)); + rtl::OUString tag_Date(RTL_CONSTASCII_USTRINGPARAM(TAG_DATE)); +#if 0 + rtl::OUString tag_Timestamp(RTL_CONSTASCII_USTRINGPARAM(TAG_TIMESTAMP)); + rtl::OUString tag_Date(RTL_CONSTASCII_USTRINGPARAM(TAG_DATE)); + rtl::OUString tag_Time(RTL_CONSTASCII_USTRINGPARAM(TAG_TIME)); +#endif + + const SignatureReferenceInformations& vReferenceInfors = signatureInfo.vSignatureReferenceInfors; + SvXMLAttributeList *pAttributeList; + + /* + * Write Signature element + */ + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_XMLNS)), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NS_XMLDSIG))); + + if (signatureInfo.ouSignatureId.getLength()>0) + { + pAttributeList->AddAttribute( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_ID)), + rtl::OUString(signatureInfo.ouSignatureId)); + } + + xDocumentHandler->startElement( tag_Signature, cssu::Reference< cssxs::XAttributeList > (pAttributeList)); + { + /* Write SignedInfo element */ + xDocumentHandler->startElement( + tag_SignedInfo, + cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + { + /* Write CanonicalizationMethod element */ + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_ALGORITHM)), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ALGO_C14N))); + xDocumentHandler->startElement( tag_CanonicalizationMethod, cssu::Reference< cssxs::XAttributeList > (pAttributeList) ); + xDocumentHandler->endElement( tag_CanonicalizationMethod ); + + /* Write SignatureMethod element */ + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_ALGORITHM)), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ALGO_RSASHA1))); + xDocumentHandler->startElement( tag_SignatureMethod, cssu::Reference< cssxs::XAttributeList > (pAttributeList) ); + xDocumentHandler->endElement( tag_SignatureMethod ); + + /* Write Reference element */ + int j; + int refNum = vReferenceInfors.size(); + + for(j=0; j<refNum; ++j) + { + const SignatureReferenceInformation& refInfor = vReferenceInfors[j]; + + pAttributeList = new SvXMLAttributeList(); + if ( refInfor.nType != TYPE_SAMEDOCUMENT_REFERENCE ) + /* + * stream reference + */ + { + pAttributeList->AddAttribute( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_URI)), + refInfor.ouURI); + } + else + /* + * same-document reference + */ + { + pAttributeList->AddAttribute( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_URI)), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CHAR_FRAGMENT))+refInfor.ouURI); + } + + xDocumentHandler->startElement( tag_Reference, cssu::Reference< cssxs::XAttributeList > (pAttributeList) ); + { + /* Write Transforms element */ + if (refInfor.nType == TYPE_XMLSTREAM_REFERENCE) + /* + * xml stream, so c14n transform is needed + */ + { + xDocumentHandler->startElement( + tag_Transforms, + cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + { + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_ALGORITHM)), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ALGO_C14N))); + xDocumentHandler->startElement( + tag_Transform, + cssu::Reference< cssxs::XAttributeList > (pAttributeList) ); + xDocumentHandler->endElement( tag_Transform ); + } + xDocumentHandler->endElement( tag_Transforms ); + } + + /* Write DigestMethod element */ + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_ALGORITHM)), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ALGO_XMLDSIGSHA1))); + xDocumentHandler->startElement( + tag_DigestMethod, + cssu::Reference< cssxs::XAttributeList > (pAttributeList) ); + xDocumentHandler->endElement( tag_DigestMethod ); + + /* Write DigestValue element */ + xDocumentHandler->startElement( + tag_DigestValue, + cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters( refInfor.ouDigestValue ); + xDocumentHandler->endElement( tag_DigestValue ); + } + xDocumentHandler->endElement( tag_Reference ); + } + } + xDocumentHandler->endElement( tag_SignedInfo ); + + /* Write SignatureValue element */ + xDocumentHandler->startElement( + tag_SignatureValue, + cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouSignatureValue ); + xDocumentHandler->endElement( tag_SignatureValue ); + + /* Write KeyInfo element */ + xDocumentHandler->startElement( + tag_KeyInfo, + cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + { + /* Write X509Data element */ + xDocumentHandler->startElement( + tag_X509Data, + cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + { + /* Write X509IssuerSerial element */ + xDocumentHandler->startElement( + tag_X509IssuerSerial, + cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + { + /* Write X509IssuerName element */ + xDocumentHandler->startElement( + tag_X509IssuerName, + cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouX509IssuerName ); + xDocumentHandler->endElement( tag_X509IssuerName ); + + /* Write X509SerialNumber element */ + xDocumentHandler->startElement( + tag_X509SerialNumber, + cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouX509SerialNumber ); + xDocumentHandler->endElement( tag_X509SerialNumber ); + } + xDocumentHandler->endElement( tag_X509IssuerSerial ); + + /* Write X509Certificate element */ + if (signatureInfo.ouX509Certificate.getLength()>0) + { + xDocumentHandler->startElement( + tag_X509Certificate, + cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + xDocumentHandler->characters( signatureInfo.ouX509Certificate ); + xDocumentHandler->endElement( tag_X509Certificate ); + } + } + xDocumentHandler->endElement( tag_X509Data ); + } + xDocumentHandler->endElement( tag_KeyInfo ); + + /* Write Object element */ + xDocumentHandler->startElement( + tag_Object, + cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + { + /* Write SignatureProperties element */ + xDocumentHandler->startElement( + tag_SignatureProperties, + cssu::Reference< cssxs::XAttributeList > (new SvXMLAttributeList())); + { + /* Write SignatureProperty element */ + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_ID)), + signatureInfo.ouPropertyId); + pAttributeList->AddAttribute( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_TARGET)), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CHAR_FRAGMENT))+signatureInfo.ouSignatureId); + xDocumentHandler->startElement( + tag_SignatureProperty, + cssu::Reference< cssxs::XAttributeList > (pAttributeList)); + { + /* Write timestamp element */ + + pAttributeList = new SvXMLAttributeList(); + pAttributeList->AddAttribute( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ATTR_XMLNS)) + +rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(":")) + +rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NSTAG_DC)), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NS_DC))); + + xDocumentHandler->startElement( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NSTAG_DC)) + +rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(":")) + +tag_Date, + cssu::Reference< cssxs::XAttributeList > (pAttributeList)); + + ::rtl::OUStringBuffer buffer; + //If the xml signature was already contained in the document, + //then we use the original date and time string, rather then the + //converted one. When the original string is converted to the DateTime + //structure then information may be lost because it only holds a fractional + //of a second with a accuracy of one hundredth of second. If the string contains + //milli seconds (document was signed by an application other than OOo) + //and the converted time is written back, then the string looks different + //and the signature is broken. + if (signatureInfo.ouDateTime.getLength() > 0) + buffer = signatureInfo.ouDateTime; + else + convertDateTime( buffer, signatureInfo.stDateTime ); + xDocumentHandler->characters( buffer.makeStringAndClear() ); + + xDocumentHandler->endElement( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NSTAG_DC)) + +rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(":")) + +tag_Date); + } + xDocumentHandler->endElement( tag_SignatureProperty ); + } + xDocumentHandler->endElement( tag_SignatureProperties ); + } + xDocumentHandler->endElement( tag_Object ); + } + xDocumentHandler->endElement( tag_Signature ); +} + +SignatureInformation XSecController::getSignatureInformation( sal_Int32 nSecurityId ) const +{ + SignatureInformation aInf( 0 ); + int nIndex = findSignatureInfor(nSecurityId); + DBG_ASSERT( nIndex != -1, "getSignatureInformation - SecurityId is invalid!" ); + if ( nIndex != -1) + { + aInf = m_vInternalSignatureInformations[nIndex].signatureInfor; + } + return aInf; +} + +SignatureInformations XSecController::getSignatureInformations() const +{ + SignatureInformations vInfors; + int sigNum = m_vInternalSignatureInformations.size(); + + for (int i=0; i<sigNum; ++i) + { + SignatureInformation si = m_vInternalSignatureInformations[i].signatureInfor; + vInfors.push_back(si); + } + + return vInfors; +} + +/* + * XSecurityController + * + * no methods + */ + +/* + * XFastPropertySet + */ +/* +void SAL_CALL XSecController::setFastPropertyValue( + sal_Int32 nHandle, + const cssu::Any& aValue ) + throw ( cssb::UnknownPropertyException, + cssb::PropertyVetoException, + cssl::IllegalArgumentException, + cssl::WrappedTargetException, + cssu::RuntimeException) +{ + sal_Int32 nIndex = getFastPropertyIndex(nHandle); + if (nIndex == -1) + { + m_vFastPropertyIndexs.push_back( nHandle ); + m_vFastPropertyValues.push_back( aValue ); + } + else + { + m_vFastPropertyValues[nIndex] = aValue; + } +} + +cssu::Any SAL_CALL XSecController::getFastPropertyValue( + sal_Int32 nHandle ) + throw ( + cssb::UnknownPropertyException, + cssl::WrappedTargetException, + cssu::RuntimeException) +{ + cssu::Any aValue; + + sal_Int32 nIndex = getFastPropertyIndex(nHandle); + if (nIndex != -1) + { + aValue = m_vFastPropertyValues[nIndex]; + } + + return aValue; +} +*/ + +/* + * XSAXEventKeeperStatusChangeListener + */ + +void SAL_CALL XSecController::blockingStatusChanged( sal_Bool isBlocking ) + throw (cssu::RuntimeException) +{ + /* + showMessageBox( rtl::OUString::createFromAscii((isBlocking? + "Blocking Status => TRUE": + "Blocking Status => FALSE")), + rtl::OUString::createFromAscii("SAXEventKeeper Status")); + */ + + this->m_bIsBlocking = isBlocking; + checkChainingStatus(); +} + +void SAL_CALL XSecController::collectionStatusChanged( + sal_Bool isInsideCollectedElement ) + throw (cssu::RuntimeException) +{ + /* + showMessageBox( rtl::OUString::createFromAscii((isInsideCollectedElement? + "Collection Status => TRUE": + "Collection Status => FALSE")), + rtl::OUString::createFromAscii("SAXEventKeeper Status")); + */ + + this->m_bIsCollectingElement = isInsideCollectedElement; + checkChainingStatus(); +} + +void SAL_CALL XSecController::bufferStatusChanged( sal_Bool /*isBufferEmpty*/) + throw (cssu::RuntimeException) +{ + /* + showMessageBox( rtl::OUString::createFromAscii((isBufferEmpty? + "Buffer Empty => TRUE": + "Buffer Empty => FALSE")), + rtl::OUString::createFromAscii("SAXEventKeeper Status")); + */ +} + +/* + * XSignatureCreationResultListener + */ +void SAL_CALL XSecController::signatureCreated( sal_Int32 securityId, com::sun::star::xml::crypto::SecurityOperationStatus nResult ) + throw (com::sun::star::uno::RuntimeException) +{ + int index = findSignatureInfor(securityId); + DBG_ASSERT( index != -1, "Signature Not Found!" ); + + SignatureInformation& signatureInfor = m_vInternalSignatureInformations[index].signatureInfor; + + /* + if (nResult == cssxc::sax::SignatureCreationResult_CREATIONSUCCEED) + { + signatureInfor.nStatus = STATUS_CREATION_SUCCEED; + } + else + { + signatureInfor.nStatus = STATUS_CREATION_FAIL; + } + */ + signatureInfor.nStatus = nResult; +} + +/* + * XSignatureVerifyResultListener + */ +void SAL_CALL XSecController::signatureVerified( sal_Int32 securityId, com::sun::star::xml::crypto::SecurityOperationStatus nResult ) + throw (com::sun::star::uno::RuntimeException) +{ + int index = findSignatureInfor(securityId); + DBG_ASSERT( index != -1, "Signature Not Found!" ); + + SignatureInformation& signatureInfor = m_vInternalSignatureInformations[index].signatureInfor; + + /* + if (nResult == cssxc::sax::SignatureVerifyResult_VERIFYSUCCEED) + { + signatureInfor.nStatus = STATUS_VERIFY_SUCCEED; + } + else + { + signatureInfor.nStatus = STATUS_VERIFY_FAIL; + } + */ + signatureInfor.nStatus = nResult; +} diff --git a/xmlsecurity/source/helper/xsecctl.hxx b/xmlsecurity/source/helper/xsecctl.hxx new file mode 100644 index 000000000000..4a715105d044 --- /dev/null +++ b/xmlsecurity/source/helper/xsecctl.hxx @@ -0,0 +1,577 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XSEC_CTL_HXX +#define _XSEC_CTL_HXX + +#include <xmlsecurity/sigstruct.hxx> + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/xml/crypto/XXMLSignature.hpp> +#include <com/sun/star/xml/crypto/XSEInitializer.hpp> +#include <com/sun/star/xml/crypto/sax/XSecurityController.hpp> +#include <com/sun/star/xml/crypto/sax/XElementStackKeeper.hpp> +#include <com/sun/star/xml/crypto/sax/XSecuritySAXEventKeeper.hpp> +#include <com/sun/star/xml/crypto/sax/XReferenceResolvedListener.hpp> +#include <com/sun/star/xml/crypto/sax/XSAXEventKeeperStatusChangeListener.hpp> +#include <com/sun/star/xml/crypto/sax/XSignatureCreationResultListener.hpp> +#include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultListener.hpp> +#include <com/sun/star/xml/wrapper/XXMLDocumentWrapper.hpp> +#include <com/sun/star/beans/XFastPropertySet.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> + +#include <rtl/ustrbuf.hxx> + +#include <cppuhelper/implbase4.hxx> + +#ifndef INCLUDED_VECTOR +#include <vector> +#define INCLUDED_VECTOR +#endif + +/* + * all error information + */ +#define ERROR_CANNOTCREATEXMLSECURITYCOMPONENT "Can't create XML security components." +#define ERROR_SAXEXCEPTIONDURINGCREATION "A SAX exception is throwed during signature creation." +#define ERROR_IOEXCEPTIONDURINGCREATION "An IO exception is throwed during signature creation." +#define ERROR_EXCEPTIONDURINGCREATION "An exception is throwed during signature creation." + +/* + * all stringS in signature element + */ +#define TAG_SIGNATURE "Signature" +#define TAG_SIGNEDINFO "SignedInfo" +#define TAG_CANONICALIZATIONMETHOD "CanonicalizationMethod" +#define TAG_SIGNATUREMETHOD "SignatureMethod" +#define TAG_REFERENCE "Reference" +#define TAG_TRANSFORMS "Transforms" +#define TAG_TRANSFORM "Transform" +#define TAG_DIGESTMETHOD "DigestMethod" +#define TAG_DIGESTVALUE "DigestValue" +#define TAG_SIGNATUREVALUE "SignatureValue" +#define TAG_KEYINFO "KeyInfo" +#define TAG_X509DATA "X509Data" +#define TAG_X509ISSUERSERIAL "X509IssuerSerial" +#define TAG_X509ISSUERNAME "X509IssuerName" +#define TAG_X509SERIALNUMBER "X509SerialNumber" +#define TAG_X509CERTIFICATE "X509Certificate" +#define TAG_OBJECT "Object" +#define TAG_SIGNATUREPROPERTIES "SignatureProperties" +#define TAG_SIGNATUREPROPERTY "SignatureProperty" +#define TAG_TIMESTAMP "timestamp" +#define TAG_DATE "date" +//#define TAG_TIME "time" + +#define ATTR_XMLNS "xmlns" +#define ATTR_ALGORITHM "Algorithm" +#define ATTR_URI "URI" +#define ATTR_ID "Id" +#define ATTR_TARGET "Target" + +#define NSTAG_DC "dc" + +#define NS_XMLDSIG "http://www.w3.org/2000/09/xmldsig#" +//#define NS_DATETIME "http://www.ietf.org/rfcXXXX.txt" +#define NS_DC "http://purl.org/dc/elements/1.1/" + +#define ALGO_C14N "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" +#define ALGO_RSASHA1 "http://www.w3.org/2000/09/xmldsig#rsa-sha1" +#define ALGO_XMLDSIGSHA1 "http://www.w3.org/2000/09/xmldsig#sha1" + +#define CHAR_FRAGMENT "#" +#define CHAR_BLANK " " + + +/* + * status of security related components + */ +#define UNINITIALIZED 0 +#define INITIALIZED 1 +#define FAILTOINITIALIZED 2 + +#define RTL_ASCII_USTRINGPARAM( asciiStr ) asciiStr, strlen( asciiStr ), RTL_TEXTENCODING_ASCII_US + +// forward declaration +class XSecParser; + +class InternalSignatureInformation +{ +public: + SignatureInformation signatureInfor; + + com::sun::star::uno::Reference< + com::sun::star::xml::crypto::sax::XReferenceResolvedListener > + xReferenceResolvedListener; + + ::std::vector< sal_Int32 > vKeeperIds; + + InternalSignatureInformation( + sal_Int32 nId, + com::sun::star::uno::Reference< com::sun::star::xml::crypto::sax::XReferenceResolvedListener > + xListener) + :signatureInfor(nId) + { + xReferenceResolvedListener = xListener; + } + + void addReference( sal_Int32 type, rtl::OUString uri, sal_Int32 keeperId ) + { + signatureInfor.vSignatureReferenceInfors.push_back( + SignatureReferenceInformation(type, uri)); + vKeeperIds.push_back( keeperId ); + } +}; + +typedef ::std::vector< InternalSignatureInformation > InternalSignatureInformations; + +class XSecController : public cppu::WeakImplHelper4 +< + com::sun::star::xml::crypto::sax::XSecurityController, + //com::sun::star::beans::XFastPropertySet, + com::sun::star::xml::crypto::sax::XSAXEventKeeperStatusChangeListener, + com::sun::star::xml::crypto::sax::XSignatureCreationResultListener, + com::sun::star::xml::crypto::sax::XSignatureVerifyResultListener +> +/****** XSecController.hxx/CLASS XSecController ******************************* + * + * NAME + * XSecController -- the xml security framework controller + * + * FUNCTION + * Controlls the whole xml security framework to create signatures or to + * verify signatures. + * + * HISTORY + * 05.01.2004 - Interface supported: XSecurityController, + * XFastPropertySet, XSAXEventKeeperStatusChangeListener, + * XSignatureCreationResultListener, + * XSignatureVerifyResultListener + * + * NOTES + * The XFastPropertySet interface is used to transfer common values to + * classes in other module, for instance, the signature id for all + * sessions is transferred to xmloff module through this interface. + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + friend class XSecParser; + +private: + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext> mxCtx; + + /* + * used to buffer SAX events + */ + com::sun::star::uno::Reference< + com::sun::star::xml::wrapper::XXMLDocumentWrapper > m_xXMLDocumentWrapper; + + /* + * the SAX events keeper + */ + com::sun::star::uno::Reference< + com::sun::star::xml::crypto::sax::XSecuritySAXEventKeeper > m_xSAXEventKeeper; + + /* + * the bridge component which creates/verifies signature + */ + com::sun::star::uno::Reference< + com::sun::star::xml::crypto::XXMLSignature > m_xXMLSignature; + + /* + * the Security Context + */ + com::sun::star::uno::Reference< + com::sun::star::xml::crypto::XXMLSecurityContext > m_xSecurityContext; + +#if 0 + /* + * the signature creation result listener + */ + com::sun::star::uno::Reference< + com::sun::star::xml::crypto::sax::XSignatureCreationResultListener > m_xSignatureCreationResultListener; + /* + * the signature verify result listener + */ + com::sun::star::uno::Reference< + com::sun::star::xml::crypto::sax::XSignatureVerifyResultListener > m_xSignatureVerifyResultListener; +#endif + + /* + * the security id incrementer, in order to make any security id unique + * to the SAXEventKeeper. + * Because each XSecController has its own SAXEventKeeper, so this variable + * is not necessary to be static. + */ + sal_Int32 m_nNextSecurityId; + + /* + * Signature information + */ + InternalSignatureInformations m_vInternalSignatureInformations; + + /* + * the previous node on the SAX chain. + * The reason that use a Reference<XInterface> type variable + * is that the previous components are different when exporting + * and importing, and there is no other common interface they + * can provided. + */ + com::sun::star::uno::Reference< + com::sun::star::uno::XInterface > m_xPreviousNodeOnSAXChain; + /* + * whether the preivous node can provide an XInitiazlize interface, + * use this variable in order to typecast the XInterface to the + * correct interface type. + */ + bool m_bIsPreviousNodeInitializable; + + /* + * the next node on the SAX chain. + * it can always provide an XDocumentHandler interface. + */ + com::sun::star::uno::Reference< + com::sun::star::xml::sax::XDocumentHandler > m_xNextNodeOnSAXChain; + + /* + * the ElementStackKeeper is used to reserve the key SAX events. + * when the SAXEventKeeper is chained on the SAX chain, it need + * first get all missed key SAX events in order to make sure the + * DOM tree it buffering has the same structure with the original + * document. + * + * For a given section of a SAX event stream, the key SAX events + * are the minimal SAX event subset of that section, which, + * combining with SAX events outside of this section, has the same + * structure with the original document. + * + * For example, sees the following dom fragment: + * <A> + * <B/> + * <C> + * <D> + * <E/> + * </D> + * </C> + * </A> + * + * If we consider the SAX event section from startElement(<A>) to + * startElement(<D>), then the key SAX events are: + * + * startElement(<A>), startElement(<C>), startElement(<D>) + * + * The startElement(<B>) and endElement(<B>) is ignored, because + * they are unimportant for the tree structure in this section. + * + * If we consider the SAX event section from startElement(<D>) to + * endElement(<A>), the key SAX events are: + * + * startElement(<D>), endElement(<D>), endElement(<C>), + * endElement(<A>). + */ + com::sun::star::uno::Reference< + com::sun::star::xml::crypto::sax::XElementStackKeeper > m_xElementStackKeeper; + + /* + * a flag representing whether the SAXEventKeeper is now on the + * SAX chain. + */ + bool m_bIsSAXEventKeeperConnected; + + /* + * a flag representing whether it is collecting some element, + * which means that the SAXEventKeeper can't be chained off the + * SAX chain. + */ + bool m_bIsCollectingElement; + + /* + * a flag representing whether the SAX event stream is blocking, + * which also means that the SAXEventKeeper can't be chained off + * the SAX chain. + */ + bool m_bIsBlocking; + + /* + * a flag representing the current status of security related + * components. + */ + sal_Int32 m_nStatusOfSecurityComponents; + + /* + * a flag representing whether the SAXEventKeeper need to be + * on the SAX chain all the time. + * This flag is used to the situation when creating signature. + */ + bool m_bIsSAXEventKeeperSticky; + + /* + * fast property vector + */ + std::vector< sal_Int32 > m_vFastPropertyIndexs; + std::vector< com::sun::star::uno::Any > m_vFastPropertyValues; + + /* + * error message pointer + */ + const char *m_pErrorMessage; + + /* + * the XSecParser which is used to parse the signature stream + */ + XSecParser *m_pXSecParser; + + /* + * the caller assigned signature id for the next signature in the + * signature stream + */ + sal_Int32 m_nReservedSignatureId; + + /* + * representing whether to verify the current signature + */ + bool m_bVerifyCurrentSignature; +public: + /* + * An xUriBinding is provided to map Uris to XInputStream interfaces. + */ + com::sun::star::uno::Reference< + com::sun::star::xml::crypto::XUriBinding > m_xUriBinding; + +private: + + /* + * Common methods + */ + sal_Bool convertNumber( sal_Int32& rValue, const rtl::OUString& rString, sal_Int32 nMin, sal_Int32 nMax ); + void convertDateTime( ::rtl::OUStringBuffer& rBuffer, const com::sun::star::util::DateTime& rDateTime ); + sal_Bool convertDateTime( com::sun::star::util::DateTime& rDateTime, const ::rtl::OUString& rString ); + + void createXSecComponent( ); + int findSignatureInfor( sal_Int32 nSecurityId ) const; + bool chainOn( bool bRetrievingLastEvent ); + void chainOff(); + void checkChainingStatus(); + void initializeSAXChain(); + + com::sun::star::uno::Reference< + com::sun::star::io::XInputStream > getObjectInputStream( const rtl::OUString& objectURL ); + + //sal_Int32 getFastPropertyIndex(sal_Int32 nHandle) const; + + /* + * For signature generation + */ + rtl::OUString createId(); + com::sun::star::uno::Reference< + com::sun::star::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToWrite( + InternalSignatureInformation& signatureInfo ); + + /* + * For signature verification + */ + void addSignature(); + void addReference( const rtl::OUString& ouUri); + void addStreamReference( + const rtl::OUString& ouUri, + bool isBinary ); + void setReferenceCount() const; + + void setX509IssuerName( rtl::OUString& ouX509IssuerName ); + void setX509SerialNumber( rtl::OUString& ouX509SerialNumber ); + void setX509Certificate( rtl::OUString& ouX509Certificate ); + void setSignatureValue( rtl::OUString& ouSignatureValue ); + void setDigestValue( rtl::OUString& ouDigestValue ); + + void setDate( rtl::OUString& ouDate ); + + void setId( rtl::OUString& ouId ); + void setPropertyId( rtl::OUString& ouPropertyId ); + + com::sun::star::uno::Reference< + com::sun::star::xml::crypto::sax::XReferenceResolvedListener > prepareSignatureToRead( + sal_Int32 nSecurityId ); + +public: + XSecController(const com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext>& rxCtx); + ~XSecController(); + + sal_Int32 getNewSecurityId( ); + + void startMission( const com::sun::star::uno::Reference< + com::sun::star::xml::crypto::XUriBinding >& xUriBinding, + const com::sun::star::uno::Reference< + com::sun::star::xml::crypto::XXMLSecurityContext >& xSecurityContext ); + + void setSAXChainConnector( + const com::sun::star::uno::Reference< + com::sun::star::lang::XInitialization >& xInitialization, + const com::sun::star::uno::Reference< + com::sun::star::xml::sax::XDocumentHandler >& xDocumentHandler, + const com::sun::star::uno::Reference< + com::sun::star::xml::crypto::sax::XElementStackKeeper >& xElementStackKeeper); + + void setSAXChainConnector( + const com::sun::star::uno::Reference< + com::sun::star::xml::sax::XParser >& xParser, + const com::sun::star::uno::Reference< + com::sun::star::xml::sax::XDocumentHandler >& xDocumentHandler, + const com::sun::star::uno::Reference< + com::sun::star::xml::crypto::sax::XElementStackKeeper >& xElementStackKeeper); + + void clearSAXChainConnector(); + void endMission(); + const char* getErrorMessage(); + + SignatureInformation getSignatureInformation( sal_Int32 nSecurityId ) const; + SignatureInformations getSignatureInformations() const; + + void exportSignature( + const com::sun::star::uno::Reference< + com::sun::star::xml::sax::XDocumentHandler >& xDocumentHandler, + const SignatureInformation& signatureInfo ); + + + /* + * For signature generation + */ + void collectToSign( sal_Int32 securityId, const rtl::OUString& referenceId ); + void signAStream( sal_Int32 securityId, const rtl::OUString& uri, const rtl::OUString& objectURL, sal_Bool isBinary); + + + /** sets data that describes the certificate. + + It is absolutely necessary that the parameter ouX509IssuerName is set. It contains + the base64 encoded certificate, which is DER encoded. The XMLSec needs it to find + the private key. Although issuer name and certificate should be sufficient to identify + the certificate the implementation in XMLSec is broken, both for Windows and mozilla. + The reason is that they use functions to find the certificate which take as parameter + the DER encoded ASN.1 issuer name. The issuer name is a DName, where most attributes + are of type DirectoryName, which is a choice of 5 string types. This information is + not contained in the issuer string and while it is converted to the ASN.1 name the + conversion function must assume a particular type, which is often wrong. For example, + the Windows function CertStrToName will use a T.61 string if the string does not contain + special characters. So if the certificate uses simple characters but encodes the + issuer attributes in Utf8, then CertStrToName will use T.61. The resulting DER encoded + ASN.1 name now contains different bytes which indicate the string type. The functions + for finding the certificate apparently use memcmp - hence they fail to find the + certificate. + */ + void setX509Certificate( + sal_Int32 nSecurityId, + const rtl::OUString& ouX509IssuerName, + const rtl::OUString& ouX509SerialNumber, + const rtl::OUString& ouX509Cert); + // see the other setX509Certifcate function + void setX509Certificate( + sal_Int32 nSecurityId, + const sal_Int32 nSecurityEnvironmentIndex, + const rtl::OUString& ouX509IssuerName, + const rtl::OUString& ouX509SerialNumber, + const rtl::OUString& ouX509Cert); + + void setDate( + sal_Int32 nSecurityId, + const ::com::sun::star::util::DateTime& rDateTime ); + + + bool WriteSignature( + const com::sun::star::uno::Reference< + com::sun::star::xml::sax::XDocumentHandler >& xDocumentHandler ); + + /* + * For signature verification + */ + void collectToVerify( const rtl::OUString& referenceId ); + void addSignature( sal_Int32 nSignatureId ); + com::sun::star::uno::Reference< com::sun::star::xml::sax::XDocumentHandler > createSignatureReader(); + void releaseSignatureReader(); + +public: + /* Interface methods */ + + /* + * XSecurityController + * + * no method in XSecurityController interface + */ + + /* + * XFastPropertySet + */ + /* + virtual void SAL_CALL setFastPropertyValue( + sal_Int32 nHandle, + const com::sun::star::uno::Any& aValue ) + throw ( + com::sun::star::beans::UnknownPropertyException, + com::sun::star::beans::PropertyVetoException, + com::sun::star::lang::IllegalArgumentException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + virtual com::sun::star::uno::Any SAL_CALL getFastPropertyValue( + sal_Int32 nHandle ) + throw ( + com::sun::star::beans::UnknownPropertyException, + com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + */ + + /* + * XSAXEventKeeperStatusChangeListener + */ + virtual void SAL_CALL blockingStatusChanged( sal_Bool isBlocking ) + throw (com::sun::star::uno::RuntimeException); + virtual void SAL_CALL collectionStatusChanged( + sal_Bool isInsideCollectedElement ) + throw (com::sun::star::uno::RuntimeException); + virtual void SAL_CALL bufferStatusChanged( sal_Bool isBufferEmpty ) + throw (com::sun::star::uno::RuntimeException); + + /* + * XSignatureCreationResultListener + */ + virtual void SAL_CALL signatureCreated( sal_Int32 securityId, com::sun::star::xml::crypto::SecurityOperationStatus nResult ) + throw (com::sun::star::uno::RuntimeException); + + /* + * XSignatureVerifyResultListener + */ + virtual void SAL_CALL signatureVerified( sal_Int32 securityId, com::sun::star::xml::crypto::SecurityOperationStatus nResult ) + throw (com::sun::star::uno::RuntimeException); +}; + +#endif + diff --git a/xmlsecurity/source/helper/xsecparser.cxx b/xmlsecurity/source/helper/xsecparser.cxx new file mode 100644 index 000000000000..1546acbdb4ef --- /dev/null +++ b/xmlsecurity/source/helper/xsecparser.cxx @@ -0,0 +1,377 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmlsecurity.hxx" + +#include "xsecparser.hxx" +#include <tools/debug.hxx> +#include "cppuhelper/exc_hlp.hxx" + +#include <string.h> + +namespace cssu = com::sun::star::uno; +namespace cssxs = com::sun::star::xml::sax; + +#define RTL_ASCII_USTRINGPARAM( asciiStr ) asciiStr, strlen( asciiStr ), RTL_TEXTENCODING_ASCII_US + +XSecParser::XSecParser( + XSecController* pXSecController, + const cssu::Reference< cssxs::XDocumentHandler >& xNextHandler ) + : m_pXSecController(pXSecController), + m_xNextHandler(xNextHandler), + m_bReferenceUnresolved(false) +{ +} + +rtl::OUString XSecParser::getIdAttr(const cssu::Reference< cssxs::XAttributeList >& xAttribs ) +{ + rtl::OUString ouIdAttr = xAttribs->getValueByName( + rtl::OUString(RTL_ASCII_USTRINGPARAM("id"))); + + if (ouIdAttr == NULL) + { + ouIdAttr = xAttribs->getValueByName( + rtl::OUString(RTL_ASCII_USTRINGPARAM("Id"))); + } + + return ouIdAttr; +} + +/* + * XDocumentHandler + */ +void SAL_CALL XSecParser::startDocument( ) + throw (cssxs::SAXException, cssu::RuntimeException) +{ + m_bInX509IssuerName = false; + m_bInX509SerialNumber = false; + m_bInX509Certificate = false; + m_bInSignatureValue = false; + m_bInDigestValue = false; + m_bInDate = false; + //m_bInTime = false; + + if (m_xNextHandler.is()) + { + m_xNextHandler->startDocument(); + } +} + +void SAL_CALL XSecParser::endDocument( ) + throw (cssxs::SAXException, cssu::RuntimeException) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->endDocument(); + } +} + +void SAL_CALL XSecParser::startElement( + const rtl::OUString& aName, + const cssu::Reference< cssxs::XAttributeList >& xAttribs ) + throw (cssxs::SAXException, cssu::RuntimeException) +{ + try + { + rtl::OUString ouIdAttr = getIdAttr(xAttribs); + if (ouIdAttr != NULL) + { + m_pXSecController->collectToVerify( ouIdAttr ); + } + + if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_SIGNATURE)) ) + { + m_pXSecController->addSignature(); + if (ouIdAttr != NULL) + { + m_pXSecController->setId( ouIdAttr ); + } + } + else if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_REFERENCE)) ) + { + rtl::OUString ouUri = xAttribs->getValueByName(rtl::OUString(RTL_ASCII_USTRINGPARAM(ATTR_URI))); + DBG_ASSERT( ouUri != NULL, "URI == NULL" ); + + if (0 == ouUri.compareTo(rtl::OUString(RTL_ASCII_USTRINGPARAM(CHAR_FRAGMENT)),1)) + { + /* + * remove the first character '#' from the attribute value + */ + m_pXSecController->addReference( ouUri.copy(1) ); + } + else + { + /* + * remember the uri + */ + m_currentReferenceURI = ouUri; + m_bReferenceUnresolved = true; + } + } + else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_TRANSFORM))) + { + if ( m_bReferenceUnresolved ) + { + rtl::OUString ouAlgorithm = xAttribs->getValueByName(rtl::OUString(RTL_ASCII_USTRINGPARAM(ATTR_ALGORITHM))); + + if (ouAlgorithm != NULL && ouAlgorithm == rtl::OUString(RTL_ASCII_USTRINGPARAM(ALGO_C14N))) + /* + * a xml stream + */ + { + m_pXSecController->addStreamReference( m_currentReferenceURI, sal_False); + m_bReferenceUnresolved = false; + } + } + } + else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_X509ISSUERNAME))) + { + m_ouX509IssuerName = rtl::OUString::createFromAscii(""); + m_bInX509IssuerName = true; + } + else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_X509SERIALNUMBER))) + { + m_ouX509SerialNumber = rtl::OUString::createFromAscii(""); + m_bInX509SerialNumber = true; + } + else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_X509CERTIFICATE))) + { + m_ouX509Certificate = rtl::OUString::createFromAscii(""); + m_bInX509Certificate = true; + } + else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_SIGNATUREVALUE))) + { + m_ouSignatureValue = rtl::OUString::createFromAscii(""); + m_bInSignatureValue = true; + } + else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_DIGESTVALUE))) + { + m_ouDigestValue = rtl::OUString::createFromAscii(""); + m_bInDigestValue = true; + } + else if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_SIGNATUREPROPERTY)) ) + { + if (ouIdAttr != NULL) + { + m_pXSecController->setPropertyId( ouIdAttr ); + } + } + else if (aName == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NSTAG_DC)) + +rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(":")) + +rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(TAG_DATE))) + { + m_ouDate = rtl::OUString::createFromAscii(""); + m_bInDate = true; + } + /* + else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_TIME))) + { + m_ouTime = rtl::OUString::createFromAscii(""); + m_bInTime = true; + } + */ + + if (m_xNextHandler.is()) + { + m_xNextHandler->startElement(aName, xAttribs); + } + } + catch (cssu::Exception& ) + {//getCaughtException MUST be the first line in the catch block + cssu::Any exc = cppu::getCaughtException(); + throw cssxs::SAXException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "xmlsecurity: Exception in XSecParser::startElement")), + 0, exc); + } + catch (...) + { + throw cssxs::SAXException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xmlsecurity: unexpected exception in XSecParser::startElement")), 0, + cssu::Any()); + } +} + +void SAL_CALL XSecParser::endElement( const rtl::OUString& aName ) + throw (cssxs::SAXException, cssu::RuntimeException) +{ + try + { + if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_DIGESTVALUE))) + { + m_bInDigestValue = false; + } + else if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_REFERENCE)) ) + { + if ( m_bReferenceUnresolved ) + /* + * it must be a octet stream + */ + { + m_pXSecController->addStreamReference( m_currentReferenceURI, sal_True); + m_bReferenceUnresolved = false; + } + + m_pXSecController->setDigestValue( m_ouDigestValue ); + } + else if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_SIGNEDINFO)) ) + { + m_pXSecController->setReferenceCount(); + } + else if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_SIGNATUREVALUE)) ) + { + m_pXSecController->setSignatureValue( m_ouSignatureValue ); + m_bInSignatureValue = false; + } + else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_X509ISSUERNAME))) + { + m_pXSecController->setX509IssuerName( m_ouX509IssuerName ); + m_bInX509IssuerName = false; + } + else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_X509SERIALNUMBER))) + { + m_pXSecController->setX509SerialNumber( m_ouX509SerialNumber ); + m_bInX509SerialNumber = false; + } + else if (aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_X509CERTIFICATE))) + { + m_pXSecController->setX509Certificate( m_ouX509Certificate ); + m_bInX509Certificate = false; + } + else if (aName == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(NSTAG_DC)) + +rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(":")) + +rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(TAG_DATE))) + { + m_pXSecController->setDate( m_ouDate ); + m_bInDate = false; + } + /* + else if ( aName == rtl::OUString(RTL_ASCII_USTRINGPARAM(TAG_TIME)) ) + { + m_pXSecController->setTime( m_ouTime ); + m_bInTime = false; + } + */ + + if (m_xNextHandler.is()) + { + m_xNextHandler->endElement(aName); + } + } + catch (cssu::Exception& ) + {//getCaughtException MUST be the first line in the catch block + cssu::Any exc = cppu::getCaughtException(); + throw cssxs::SAXException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "xmlsecurity: Exception in XSecParser::endElement")), + 0, exc); + } + catch (...) + { + throw cssxs::SAXException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xmlsecurity: unexpected exception in XSecParser::endElement")), 0, + cssu::Any()); + } +} + +void SAL_CALL XSecParser::characters( const rtl::OUString& aChars ) + throw (cssxs::SAXException, cssu::RuntimeException) +{ + if (m_bInX509IssuerName) + { + m_ouX509IssuerName += aChars; + } + else if (m_bInX509SerialNumber) + { + m_ouX509SerialNumber += aChars; + } + else if (m_bInX509Certificate) + { + m_ouX509Certificate += aChars; + } + else if (m_bInSignatureValue) + { + m_ouSignatureValue += aChars; + } + else if (m_bInDigestValue) + { + m_ouDigestValue += aChars; + } + else if (m_bInDate) + { + m_ouDate += aChars; + } + /* + else if (m_bInTime) + { + m_ouTime += aChars; + } + */ + + if (m_xNextHandler.is()) + { + m_xNextHandler->characters(aChars); + } +} + +void SAL_CALL XSecParser::ignorableWhitespace( const rtl::OUString& aWhitespaces ) + throw (cssxs::SAXException, cssu::RuntimeException) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->ignorableWhitespace( aWhitespaces ); + } +} + +void SAL_CALL XSecParser::processingInstruction( const rtl::OUString& aTarget, const rtl::OUString& aData ) + throw (cssxs::SAXException, cssu::RuntimeException) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->processingInstruction(aTarget, aData); + } +} + +void SAL_CALL XSecParser::setDocumentLocator( const cssu::Reference< cssxs::XLocator >& xLocator ) + throw (cssxs::SAXException, cssu::RuntimeException) +{ + if (m_xNextHandler.is()) + { + m_xNextHandler->setDocumentLocator( xLocator ); + } +} + +/* + * XInitialization + */ +void SAL_CALL XSecParser::initialize( + const cssu::Sequence< cssu::Any >& aArguments ) + throw(cssu::Exception, cssu::RuntimeException) +{ + aArguments[0] >>= m_xNextHandler; +} diff --git a/xmlsecurity/source/helper/xsecparser.hxx b/xmlsecurity/source/helper/xsecparser.hxx new file mode 100644 index 000000000000..8de771569191 --- /dev/null +++ b/xmlsecurity/source/helper/xsecparser.hxx @@ -0,0 +1,165 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _XSEC_CTL_PARSER_HXX +#define _XSEC_CTL_PARSER_HXX + +#include <xsecctl.hxx> + +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> + +#include <cppuhelper/implbase2.hxx> + +class XSecParser: public cppu::WeakImplHelper2 +< + com::sun::star::xml::sax::XDocumentHandler, + com::sun::star::lang::XInitialization +> +/****** XSecController.hxx/CLASS XSecParser *********************************** + * + * NAME + * XSecParser -- a SAX parser that can detect security elements + * + * FUNCTION + * The XSecParser object is connected on the SAX chain and detects + * security elements in the SAX event stream, then notifies + * the XSecController. + * + * HISTORY + * 05.01.2004 - Interface supported: XDocumentHandler, XInitialization + * + * NOTES + * This class is used when importing a document. + * + * AUTHOR + * Michael Mi + * Email: michael.mi@sun.com + ******************************************************************************/ +{ + friend class XSecController; +private: + /* + * the following members are used to reserve the signature information, + * including X509IssuerName, X509SerialNumber, and X509Certificate,etc. + */ + rtl::OUString m_ouX509IssuerName; + rtl::OUString m_ouX509SerialNumber; + rtl::OUString m_ouX509Certificate; + rtl::OUString m_ouDigestValue; + rtl::OUString m_ouSignatureValue; + rtl::OUString m_ouDate; + //rtl::OUString m_ouTime; + + /* + * whether inside a particular element + */ + bool m_bInX509IssuerName; + bool m_bInX509SerialNumber; + bool m_bInX509Certificate; + bool m_bInDigestValue; + bool m_bInSignatureValue; + bool m_bInDate; + //bool m_bInTime; + + /* + * the XSecController collaborating with XSecParser + */ + XSecController* m_pXSecController; + + /* + * the next XDocumentHandler on the SAX chain + */ + com::sun::star::uno::Reference< + com::sun::star::xml::sax::XDocumentHandler > m_xNextHandler; + + /* + * this string is used to remember the current handled reference's URI, + * + * because it can be decided whether a stream reference is xml based or binary based + * only after the Transforms element is read in, so we have to reserve the reference's + * URI when the startElement event is met. + */ + rtl::OUString m_currentReferenceURI; + bool m_bReferenceUnresolved; + +private: + rtl::OUString getIdAttr(const com::sun::star::uno::Reference< + com::sun::star::xml::sax::XAttributeList >& xAttribs ); + +public: + XSecParser( XSecController* pXSecController, + const com::sun::star::uno::Reference< + com::sun::star::xml::sax::XDocumentHandler >& xNextHandler ); + ~XSecParser(){}; + + /* + * XDocumentHandler + */ + virtual void SAL_CALL startDocument( ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL endDocument( ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL startElement( + const rtl::OUString& aName, + const com::sun::star::uno::Reference< + com::sun::star::xml::sax::XAttributeList >& xAttribs ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL endElement( const rtl::OUString& aName ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL characters( const rtl::OUString& aChars ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL ignorableWhitespace( const rtl::OUString& aWhitespaces ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL processingInstruction( + const rtl::OUString& aTarget, + const rtl::OUString& aData ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL setDocumentLocator( + const com::sun::star::uno::Reference< + com::sun::star::xml::sax::XLocator >& xLocator ) + throw (com::sun::star::xml::sax::SAXException, com::sun::star::uno::RuntimeException); + + /* + * XInitialization + */ + virtual void SAL_CALL initialize( + const com::sun::star::uno::Sequence< com::sun::star::uno::Any >& aArguments ) + throw(com::sun::star::uno::Exception, com::sun::star::uno::RuntimeException); +}; + +#endif + diff --git a/xmlsecurity/source/helper/xsecsign.cxx b/xmlsecurity/source/helper/xsecsign.cxx new file mode 100644 index 000000000000..774a07cb28f2 --- /dev/null +++ b/xmlsecurity/source/helper/xsecsign.cxx @@ -0,0 +1,374 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmlsecurity.hxx" + +#include <xsecctl.hxx> +#include <tools/debug.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/XReferenceResolvedBroadcaster.hpp> +#include <com/sun/star/xml/crypto/sax/XBlockerMonitor.hpp> +#include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp> +#include <com/sun/star/xml/crypto/sax/XSignatureCreationResultBroadcaster.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <rtl/uuid.h> + +#include <stdio.h> + +namespace cssu = com::sun::star::uno; +namespace cssl = com::sun::star::lang; +namespace cssxc = com::sun::star::xml::crypto; +namespace cssxs = com::sun::star::xml::sax; + +/* xml security framework components */ +#define SIGNATURECREATOR_COMPONENT "com.sun.star.xml.crypto.sax.SignatureCreator" + +/* protected: for signature generation */ +rtl::OUString XSecController::createId() +{ + cssu::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid ((sal_uInt8 *)aSeq.getArray(), 0, sal_True); + + char str[68]="ID_"; + int length = 3; + for (int i=0; i<16; ++i) + { + length += sprintf(str+length, "%04x", (unsigned char)aSeq[i]); + } + + return rtl::OUString::createFromAscii(str); +} + +cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepareSignatureToWrite( + InternalSignatureInformation& internalSignatureInfor ) +{ + sal_Int32 nSecurityId = internalSignatureInfor.signatureInfor.nSecurityId; + SignatureReferenceInformations& vReferenceInfors = internalSignatureInfor.signatureInfor.vSignatureReferenceInfors; + + sal_Int32 nIdOfSignatureElementCollector; + cssu::Reference< cssxc::sax::XReferenceResolvedListener > xReferenceResolvedListener; + + nIdOfSignatureElementCollector = + m_xSAXEventKeeper->addSecurityElementCollector( cssxc::sax::ElementMarkPriority_AFTERMODIFY, sal_True ); + + m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId); + + /* + * create a SignatureCreator + */ + cssu::Reference< cssl::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() ); + xReferenceResolvedListener = cssu::Reference< cssxc::sax::XReferenceResolvedListener >( + xMCF->createInstanceWithContext( + rtl::OUString::createFromAscii(SIGNATURECREATOR_COMPONENT), mxCtx), + cssu::UNO_QUERY); + + cssu::Reference<cssl::XInitialization> xInitialization(xReferenceResolvedListener, cssu::UNO_QUERY); + + cssu::Sequence<cssu::Any> args(5); + args[0] = cssu::makeAny(rtl::OUString::valueOf(nSecurityId)); + args[1] = cssu::makeAny(m_xSAXEventKeeper); + args[2] = cssu::makeAny(rtl::OUString::valueOf(nIdOfSignatureElementCollector)); + + //i39448 : for nss, the internal module is used for signing, which needs to be improved later + sal_Int32 nEnvIndex = internalSignatureInfor.signatureInfor.nSecurityEnvironmentIndex; + if( nEnvIndex < 0 || nEnvIndex >= m_xSecurityContext->getSecurityEnvironmentNumber()) + {// set defaultEnv + args[3] = cssu::makeAny(m_xSecurityContext->getSecurityEnvironment()); + } + else + { + args[3] = cssu::makeAny(m_xSecurityContext->getSecurityEnvironmentByIndex(nEnvIndex)); + } + + args[4] = cssu::makeAny(m_xXMLSignature); + xInitialization->initialize(args); + + sal_Int32 nBlockerId = m_xSAXEventKeeper->addBlocker(); + m_xSAXEventKeeper->setSecurityId(nBlockerId, nSecurityId); + + cssu::Reference<cssxc::sax::XBlockerMonitor> xBlockerMonitor(xReferenceResolvedListener, cssu::UNO_QUERY); + xBlockerMonitor->setBlockerId(nBlockerId); + + cssu::Reference< cssxc::sax::XSignatureCreationResultBroadcaster > + xSignatureCreationResultBroadcaster(xReferenceResolvedListener, cssu::UNO_QUERY); + + xSignatureCreationResultBroadcaster->addSignatureCreationResultListener( this ); + + cssu::Reference<cssxc::sax::XReferenceResolvedBroadcaster> + xReferenceResolvedBroadcaster + (m_xSAXEventKeeper, + cssu::UNO_QUERY); + + xReferenceResolvedBroadcaster->addReferenceResolvedListener( + nIdOfSignatureElementCollector, + xReferenceResolvedListener); + + cssu::Reference<cssxc::sax::XReferenceCollector> xReferenceCollector + (xReferenceResolvedListener, cssu::UNO_QUERY); + + int i; + int size = vReferenceInfors.size(); + sal_Int32 nReferenceCount = 0; + + for(i=0; i<size; ++i) + { + sal_Int32 keeperId = internalSignatureInfor.vKeeperIds[i]; + + if ( keeperId != -1) + { + m_xSAXEventKeeper->setSecurityId(keeperId, nSecurityId); + xReferenceResolvedBroadcaster->addReferenceResolvedListener( keeperId, xReferenceResolvedListener); + xReferenceCollector->setReferenceId( keeperId ); + nReferenceCount++; + } + } + + xReferenceCollector->setReferenceCount( nReferenceCount ); + + /* + * adds all URI binding + */ + cssu::Reference<cssxc::XUriBinding> xUriBinding + (xReferenceResolvedListener, cssu::UNO_QUERY); + + for(i=0; i<size; ++i) + { + const SignatureReferenceInformation& refInfor = vReferenceInfors[i]; + + cssu::Reference< com::sun::star::io::XInputStream > xInputStream + = getObjectInputStream( refInfor.ouURI ); + + if (xInputStream.is()) + { + xUriBinding->setUriBinding(refInfor.ouURI,xInputStream); + } + } + + cssu::Reference<cssxc::sax::XKeyCollector> keyCollector (xReferenceResolvedListener, cssu::UNO_QUERY); + keyCollector->setKeyId(0); + + internalSignatureInfor.signatureInfor.ouSignatureId = createId(); + internalSignatureInfor.signatureInfor.ouPropertyId = createId(); + internalSignatureInfor.addReference(TYPE_SAMEDOCUMENT_REFERENCE, internalSignatureInfor.signatureInfor.ouPropertyId, -1 ); + size++; + + /* + * replace both digestValues and signatueValue to " " + */ + for(i=0; i<size; ++i) + { + SignatureReferenceInformation& refInfor = vReferenceInfors[i]; + refInfor.ouDigestValue = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CHAR_BLANK)); + } + + internalSignatureInfor.signatureInfor.ouSignatureValue = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(CHAR_BLANK)); + + return xReferenceResolvedListener; +} + +/* public: for signature generation */ +void XSecController::collectToSign( sal_Int32 securityId, const rtl::OUString& referenceId ) +{ + /* DBG_ASSERT( m_xSAXEventKeeper.is(), "the SAXEventKeeper is NULL" ); */ + + chainOn(true); + + if ( m_nStatusOfSecurityComponents == INITIALIZED ) + /* + * if all security components are ready, add a signature. + */ + { + sal_Int32 nKeeperId = m_xSAXEventKeeper->addSecurityElementCollector( + cssxc::sax::ElementMarkPriority_AFTERMODIFY, sal_False); + + int index = findSignatureInfor( securityId ); + + if ( index == -1 ) + { + InternalSignatureInformation isi(securityId, NULL); + isi.addReference(TYPE_SAMEDOCUMENT_REFERENCE, referenceId, nKeeperId ); + m_vInternalSignatureInformations.push_back( isi ); + } + else + { + m_vInternalSignatureInformations[index].addReference(TYPE_SAMEDOCUMENT_REFERENCE, referenceId, nKeeperId ); + } + } +} + +void XSecController::signAStream( sal_Int32 securityId, const rtl::OUString& uri, const rtl::OUString& /*objectURL*/, sal_Bool isBinary) +{ + sal_Int32 type = ((isBinary==sal_True)?TYPE_BINARYSTREAM_REFERENCE:TYPE_XMLSTREAM_REFERENCE); + + int index = findSignatureInfor( securityId ); + + if (index == -1) + { + InternalSignatureInformation isi(securityId, NULL); + isi.addReference(type, uri, -1); + m_vInternalSignatureInformations.push_back( isi ); + } + else + { + m_vInternalSignatureInformations[index].addReference(type, uri, -1); + } +} + +void XSecController::setX509Certificate( + sal_Int32 nSecurityId, + const rtl::OUString& ouX509IssuerName, + const rtl::OUString& ouX509SerialNumber, + const rtl::OUString& ouX509Cert) +{ + setX509Certificate(nSecurityId, -1, ouX509IssuerName, ouX509SerialNumber, ouX509Cert); +} + +void XSecController::setX509Certificate( + sal_Int32 nSecurityId, + const sal_Int32 nSecurityEnvironmentIndex, + const rtl::OUString& ouX509IssuerName, + const rtl::OUString& ouX509SerialNumber, + const rtl::OUString& ouX509Cert) +{ + int index = findSignatureInfor( nSecurityId ); + + if ( index == -1 ) + { + InternalSignatureInformation isi(nSecurityId, NULL); + isi.signatureInfor.nSecurityEnvironmentIndex = nSecurityEnvironmentIndex; + isi.signatureInfor.ouX509IssuerName = ouX509IssuerName; + isi.signatureInfor.ouX509SerialNumber = ouX509SerialNumber; + isi.signatureInfor.ouX509Certificate = ouX509Cert; + m_vInternalSignatureInformations.push_back( isi ); + } + else + { + SignatureInformation &si + = m_vInternalSignatureInformations[index].signatureInfor; + si.ouX509IssuerName = ouX509IssuerName; + si.ouX509SerialNumber = ouX509SerialNumber; + si.ouX509Certificate = ouX509Cert; + si.nSecurityEnvironmentIndex = nSecurityEnvironmentIndex; + } +} + +void XSecController::setDate( + sal_Int32 nSecurityId, + const ::com::sun::star::util::DateTime& rDateTime ) +{ + int index = findSignatureInfor( nSecurityId ); + + if ( index == -1 ) + { + InternalSignatureInformation isi(nSecurityId, NULL); + isi.signatureInfor.stDateTime = rDateTime; + m_vInternalSignatureInformations.push_back( isi ); + } + else + { + SignatureInformation &si + = m_vInternalSignatureInformations[index].signatureInfor; + si.stDateTime = rDateTime; + } +} + +bool XSecController::WriteSignature( + const cssu::Reference<cssxs::XDocumentHandler>& xDocumentHandler ) +{ + bool rc = false; + + DBG_ASSERT( xDocumentHandler.is(), "I really need a document handler!" ); + + /* + * chain the SAXEventKeeper to the SAX chain + */ + chainOn(true); + + if ( m_nStatusOfSecurityComponents == INITIALIZED ) + /* + * if all security components are ready, add the signature + * stream. + */ + { + m_bIsSAXEventKeeperSticky = true; + m_xSAXEventKeeper->setNextHandler(xDocumentHandler); + + try + { + /* + * export the signature template + */ + cssu::Reference<cssxs::XDocumentHandler> xSEKHandler( m_xSAXEventKeeper,cssu::UNO_QUERY); + + int i; + int sigNum = m_vInternalSignatureInformations.size(); + + for (i=0; i<sigNum; ++i) + { + InternalSignatureInformation &isi = m_vInternalSignatureInformations[i]; + + /* + * prepare the signature creator + */ + isi.xReferenceResolvedListener + = prepareSignatureToWrite( isi ); + + exportSignature( xSEKHandler, isi.signatureInfor ); + } + + m_bIsSAXEventKeeperSticky = false; + chainOff(); + + rc = true; + } + catch( cssxs::SAXException& ) + { + m_pErrorMessage = ERROR_SAXEXCEPTIONDURINGCREATION; + } + catch( com::sun::star::io::IOException& ) + { + m_pErrorMessage = ERROR_IOEXCEPTIONDURINGCREATION; + } + catch( cssu::Exception& ) + { + m_pErrorMessage = ERROR_EXCEPTIONDURINGCREATION; + } + + m_xSAXEventKeeper->setNextHandler( NULL ); + m_bIsSAXEventKeeperSticky = false; + } + else + { + m_pErrorMessage = ERROR_CANNOTCREATEXMLSECURITYCOMPONENT; + } + + return rc; +} + diff --git a/xmlsecurity/source/helper/xsecverify.cxx b/xmlsecurity/source/helper/xsecverify.cxx new file mode 100644 index 000000000000..82210fdc91b3 --- /dev/null +++ b/xmlsecurity/source/helper/xsecverify.cxx @@ -0,0 +1,331 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_xmlsecurity.hxx" + +#include <xsecctl.hxx> +#include "xsecparser.hxx" +#include <tools/debug.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/XReferenceResolvedBroadcaster.hpp> +#include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp> +#include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> + +namespace cssu = com::sun::star::uno; +namespace cssl = com::sun::star::lang; +namespace cssxc = com::sun::star::xml::crypto; +namespace cssxs = com::sun::star::xml::sax; + +/* xml security framework components */ +#define SIGNATUREVERIFIER_COMPONENT "com.sun.star.xml.crypto.sax.SignatureVerifier" + +/* protected: for signature verify */ +cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepareSignatureToRead( + sal_Int32 nSecurityId) +{ + if ( m_nStatusOfSecurityComponents != INITIALIZED ) + { + return NULL; + } + + sal_Int32 nIdOfSignatureElementCollector; + cssu::Reference< cssxc::sax::XReferenceResolvedListener > xReferenceResolvedListener; + + nIdOfSignatureElementCollector = + m_xSAXEventKeeper->addSecurityElementCollector( cssxc::sax::ElementMarkPriority_BEFOREMODIFY, sal_False); + + m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId); + + /* + * create a SignatureVerifier + */ + cssu::Reference< cssl::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() ); + xReferenceResolvedListener = cssu::Reference< cssxc::sax::XReferenceResolvedListener >( + xMCF->createInstanceWithContext( + rtl::OUString::createFromAscii( SIGNATUREVERIFIER_COMPONENT ), mxCtx), + cssu::UNO_QUERY); + + cssu::Reference<cssl::XInitialization> xInitialization(xReferenceResolvedListener, cssu::UNO_QUERY); + + cssu::Sequence<cssu::Any> args(5); + args[0] = cssu::makeAny(rtl::OUString::valueOf(nSecurityId)); + args[1] = cssu::makeAny(m_xSAXEventKeeper); + args[2] = cssu::makeAny(rtl::OUString::valueOf(nIdOfSignatureElementCollector)); + args[3] = cssu::makeAny(m_xSecurityContext); + args[4] = cssu::makeAny(m_xXMLSignature); + xInitialization->initialize(args); + + cssu::Reference< cssxc::sax::XSignatureVerifyResultBroadcaster > + signatureVerifyResultBroadcaster(xReferenceResolvedListener, cssu::UNO_QUERY); + + signatureVerifyResultBroadcaster->addSignatureVerifyResultListener( this ); + + cssu::Reference<cssxc::sax::XReferenceResolvedBroadcaster> xReferenceResolvedBroadcaster + (m_xSAXEventKeeper, + cssu::UNO_QUERY); + + xReferenceResolvedBroadcaster->addReferenceResolvedListener( + nIdOfSignatureElementCollector, + xReferenceResolvedListener); + + cssu::Reference<cssxc::sax::XKeyCollector> keyCollector (xReferenceResolvedListener, cssu::UNO_QUERY); + keyCollector->setKeyId(0); + + return xReferenceResolvedListener; +} + +void XSecController::addSignature() +{ + cssu::Reference< cssxc::sax::XReferenceResolvedListener > xReferenceResolvedListener = NULL; + sal_Int32 nSignatureId = 0; + + + if (m_bVerifyCurrentSignature) + { + chainOn(true); + xReferenceResolvedListener = prepareSignatureToRead( m_nReservedSignatureId ); + m_bVerifyCurrentSignature = false; + nSignatureId = m_nReservedSignatureId; + } + + InternalSignatureInformation isi( nSignatureId, xReferenceResolvedListener ); + m_vInternalSignatureInformations.push_back( isi ); +} + +void XSecController::addReference( const rtl::OUString& ouUri) +{ + InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; + isi.addReference(TYPE_SAMEDOCUMENT_REFERENCE,ouUri, -1 ); +} + +void XSecController::addStreamReference( + const rtl::OUString& ouUri, + bool isBinary ) +{ + sal_Int32 type = (isBinary?TYPE_BINARYSTREAM_REFERENCE:TYPE_XMLSTREAM_REFERENCE); + + InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; + + if ( isi.xReferenceResolvedListener.is() ) + { + /* + * get the input stream + */ + cssu::Reference< com::sun::star::io::XInputStream > xObjectInputStream + = getObjectInputStream( ouUri ); + + if ( xObjectInputStream.is() ) + { + cssu::Reference<cssxc::XUriBinding> xUriBinding + (isi.xReferenceResolvedListener, cssu::UNO_QUERY); + xUriBinding->setUriBinding(ouUri, xObjectInputStream); + } + } + + isi.addReference(type, ouUri, -1); +} + +void XSecController::setReferenceCount() const +{ + const InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; + + if ( isi.xReferenceResolvedListener.is() ) + { + 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 == TYPE_SAMEDOCUMENT_REFERENCE ) + /* + * same-document reference + */ + { + referenceCount++; + } + } + + cssu::Reference<cssxc::sax::XReferenceCollector> xReferenceCollector + (isi.xReferenceResolvedListener, cssu::UNO_QUERY); + xReferenceCollector->setReferenceCount( referenceCount ); + } +} + +void XSecController::setX509IssuerName( rtl::OUString& ouX509IssuerName ) +{ + InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; + isi.signatureInfor.ouX509IssuerName = ouX509IssuerName; +} + +void XSecController::setX509SerialNumber( rtl::OUString& ouX509SerialNumber ) +{ + InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; + isi.signatureInfor.ouX509SerialNumber = ouX509SerialNumber; +} + +void XSecController::setX509Certificate( rtl::OUString& ouX509Certificate ) +{ + InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; + isi.signatureInfor.ouX509Certificate = ouX509Certificate; +} + +void XSecController::setSignatureValue( rtl::OUString& ouSignatureValue ) +{ + InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; + isi.signatureInfor.ouSignatureValue = ouSignatureValue; +} + +void XSecController::setDigestValue( rtl::OUString& ouDigestValue ) +{ + SignatureInformation &si = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1].signatureInfor; + SignatureReferenceInformation &reference = si.vSignatureReferenceInfors[si.vSignatureReferenceInfors.size()-1]; + reference.ouDigestValue = ouDigestValue; +} + +void XSecController::setDate( rtl::OUString& ouDate ) +{ + InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; + convertDateTime( isi.signatureInfor.stDateTime, ouDate ); + isi.signatureInfor.ouDateTime = ouDate; +} + +/* +void XSecController::setTime( rtl::OUString& ouTime ) +{ + InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; + isi.signatureInfor.ouTime = ouTime; +} +*/ + +void XSecController::setId( rtl::OUString& ouId ) +{ + InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; + isi.signatureInfor.ouSignatureId = ouId; +} + +void XSecController::setPropertyId( rtl::OUString& ouPropertyId ) +{ + InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; + isi.signatureInfor.ouPropertyId = ouPropertyId; +} + +/* public: for signature verify */ +void XSecController::collectToVerify( const rtl::OUString& referenceId ) +{ + /* DBG_ASSERT( m_xSAXEventKeeper.is(), "the SAXEventKeeper is NULL" ); */ + + if ( m_nStatusOfSecurityComponents == INITIALIZED ) + /* + * if all security components are ready, verify the signature. + */ + { + bool bJustChainingOn = false; + cssu::Reference< cssxs::XDocumentHandler > xHandler = NULL; + + 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(false)) + { + bJustChainingOn = true; + xHandler = m_xSAXEventKeeper->setNextHandler(NULL); + } + + sal_Int32 nKeeperId = m_xSAXEventKeeper->addSecurityElementCollector( + cssxc::sax::ElementMarkPriority_BEFOREMODIFY, sal_False ); + + cssu::Reference<cssxc::sax::XReferenceResolvedBroadcaster> xReferenceResolvedBroadcaster + (m_xSAXEventKeeper, + cssu::UNO_QUERY ); + + cssu::Reference<cssxc::sax::XReferenceCollector> xReferenceCollector + ( isi.xReferenceResolvedListener, cssu::UNO_QUERY ); + + m_xSAXEventKeeper->setSecurityId(nKeeperId, isi.signatureInfor.nSecurityId); + xReferenceResolvedBroadcaster->addReferenceResolvedListener( nKeeperId, isi.xReferenceResolvedListener); + xReferenceCollector->setReferenceId( nKeeperId ); + + isi.vKeeperIds[j] = nKeeperId; + break; + } + } + } + + if ( bJustChainingOn ) + { + cssu::Reference< cssxs::XDocumentHandler > xSEKHandler(m_xSAXEventKeeper, cssu::UNO_QUERY); + if (m_xElementStackKeeper.is()) + { + m_xElementStackKeeper->retrieve(xSEKHandler, sal_True); + } + m_xSAXEventKeeper->setNextHandler(xHandler); + } + } +} + +void XSecController::addSignature( sal_Int32 nSignatureId ) +{ + DBG_ASSERT( m_pXSecParser != NULL, "No XSecParser initialized" ); + + m_nReservedSignatureId = nSignatureId; + m_bVerifyCurrentSignature = true; +} + +cssu::Reference< cssxs::XDocumentHandler > XSecController::createSignatureReader() +{ + m_pXSecParser = new XSecParser( this, NULL ); + cssu::Reference< cssl::XInitialization > xInitialization = m_pXSecParser; + + setSAXChainConnector(xInitialization, NULL, NULL); + + return m_pXSecParser; +} + +void XSecController::releaseSignatureReader() +{ + clearSAXChainConnector( ); + m_pXSecParser = NULL; +} + |